API Filtering Guidelines¶
Introduction¶
APIs often deal with large datasets, such as devices or building resources. API clients of the API are often concerned with only a small subset of the overall data available, meaning that filtering, querying or respective selection of resources is important.
Data is typically transferred over network boundaries and it is usually impractical or infeasible to transfer entire datasets at once. Instead, API clients are expected to load only the data they need.
API SHOULD NOT support more than 4 parameters at once for selecting resources [400]¶
An API SHOULD NOT support more than 4 parameters at once for selecting resources according to rule 401.
As a rule of thumb, you should limit the query to 4 parameters. Using more than 4 query parameters impacts the readability of the query and the length of the URL query parameters.
Other specialized query languages use the request body to structure the query and offer a more developer-friendly representation. This might change in the future if the HTTP verb QUERY
is widely supported, and the "GET
with request body problem" is mitigated.
Information
It is recommended to use a specialized query language approach like GraphQL Queries if an API offers a wide range of combining more than 4 parameters at once to filter the collection to return.
API MAY provide selection of resources in response [401]¶
API filtering allows API clients to fetch the data they need based on the specific criteria. If you require search on your endpoint, you can add support for filters directly with the query parameters.
The query parameter filter
SHOULD be used to filter or query data [401.1]¶
An API SHOULD support a filter
query parameter that can be used by API clients to provide a resource query expression to filter results. All members or properties of a resource objects SHOULD queryable.
The API client specifies the selection of resources in the following format.
GET /devices?filter=<expression>
The <expression> MUST contain the query and is on the right-hand side of the equal sign. The <expression> specifies the logical filtering operation on a field in the resource that is being read. The resource is returned to the API client only if the filter condition is satisfied.
Queries on one member MAY directly be offered [401.1.1]¶
There are API scenarios where only one dedicated member is queried. For such scenarios, the filter=<expression>
syntax is more difficult to read and specify. We recommend a direct query option to retrieve data for a specific member. Here is the example for direct query option.
GET /buildings?name=buildingA
The filter
query parameter SHOULD consider syntax and semantic of common operations [401.2]¶
The filter
parameters are usually applied as query parameters in the REST URI that supports the GET
verb as well.
An API MAY support several operations but does not need to support all at once. The intention and semantics of an operation listed below MUST be retained and MUST be kept unique.
As an example
- For defined operator like 'eq' for equality comparison, don't use 'eq' for another semantics.
- Don't introduce another operator like 'eql' with the same semantic as 'eq' provides.
An API MUST use the appropriate notation for different data types within the filter <expression>.
- String values must be delimited by single quotation marks
'
. - Numeric values require no delimiters.
- Boolean values are represented by the literals
true
,false
. null
-values are represented by the literalnull
(see example not equal below).
Multiple filter options could be specified using the combination operators like and
, or
, see combining filters below.
Note
There are several grammars available to specify the desired filter. For REST API the OData query syntax and grammar v4.01 inspired the selection of possible operations listed below.
Comparison Operators¶
Operator | Description | Example |
---|---|---|
eq | equals | /employees?filter=name eq 'Alex' selects all employees with name Alex |
ne | not equals | /employees?filter=profession ne null selects all employees which have specified a profession not equal null value |
gt | greater than | /employees?filter=age gt 30 selects all employees which are older than 30 |
lt | less than | /employees?filter=age lt 30 selects all employees which are younger than 30 |
ge | greater than or equal to | /employees?filter=age ge 30 selects all employees which are 30 or older than 30 |
le | less than or equal to | /employees?filter=age le 30 selects all employees which are 30 or younger than 30 |
Combining Filters¶
Combination | Description | Example |
---|---|---|
and | Logical AND | /employees?filter=name eq 'Alex' and age gt 65 selects all employees with name Alex and are older than 65 |
or | Logical OR | /employees?filter=name eq 'John' or name eq 'Alex' selects all employees with name John or Alex |
not | Logical NOT, inverts to opposite | /employees?filter=not(name eq 'Alex') selects all employees which have a different name than Alex (same as ne in this example) |
() | Grouping with the open ( and close ) parenthesis operators. | /employees?filter=name eq ' John' and (age gt 65 or age lt 18) selects all employees with name John which are older than 65 or younger than 18 |
Representing logical exclusive OR (XOR) operation
The comparison operators do not offer the XOR operation but can be represented by combining the filters properly: not(paramA eq true and paramB eq true) and (paramA eq true or paramB eq true)
Further operations of Open Data Protocol grammar¶
An API MAY support more operations than the common, harmonized operations. The API provider MUST document all supported operations in the API specification so that the API client knows about all the supported operations.
We are not proposing to follow the entire OData query syntax but you can refer for guidance.
Here are some examples of the OData grammar, which provide more possibilities to query resources.
String Functions¶
- contains function (filters if a string contains another substring)
- startswith function (filters if string starts with a substring)
- length function (filters if string has the defined length)
Geography Functions¶
- geo.distance function (filters on distance between 2 geographical points (latitude/longitude))
Further Comparison Operator¶
Operator | Description | Example |
---|---|---|
in | Is a member of | /employees?filter=name in ('Alex', 'John, 'Thomas') selects all employees with name Alex, John or Thomas |
has | Has flags | /employees?filter=state has Employment.Status 'Employed' selects all employees which are flagged as still employed |