Requests & Querying
Rules for query parameters, filtering, sorting, pagination, and request patterns.
These rules define request/query conventions (filtering, sorting, pagination) so list/search endpoints are consistent across APIs.
Related guides:
Related reference:
Query Parameters & Filtering
#600 - Use Conventional Query Parameters
Intent: keep APIs predictable and make client libraries reusable.
Use consistent, conventional query parameter names and semantics across APIs.
How to implement:
- Use
limit+offsetfor offset-based pagination (see Pagination). - Use
count(boolean) when you support returning a total count (be explicit about cost/performance). - Use
filtersfor filter expressions andsortersfor ordering (see guidance in API Contract & Documentation). - Document the allowed fields (whitelist) for filtering and sorting. If the set differs per endpoint, document per endpoint.
Standards guidance:
- Avoid inventing per-endpoint bespoke query DSLs.
- Prefer OpenAPI-defined encoding for arrays/objects (
style/explode) when parameters are multi-valued (see [#601]).
Examples:
GET /accounts?limit=50&offset=0&filters=status eq \"ACTIVE\"&sorters=name:ascTestability:
- Reviewers can verify each endpoint uses conventional parameter names and documents the supported field lists.
#601 - Define Collection Formats for Header and Query Parameters
Intent: ensure clients can reliably build requests and servers can parse them.
Recommendation:
- For multi-valued query params, prefer repeated parameters:
?status=ACTIVE&status=DISABLED
- If you need a compact representation, use comma-separated values:
?status=ACTIVE,DISABLED
Rules:
- Choose one canonical encoding per parameter.
- Do not accept multiple encodings unless you explicitly document which encodings are supported and which one is canonical.
OpenAPI guidance (examples):
- Repeated parameters:
parameters:
- in: query
name: status
required: false
schema:
type: array
items:
type: string
style: form
explode: true- Comma-separated:
parameters:
- in: query
name: status
required: false
schema:
type: array
items:
type: string
style: form
explode: falseTestability:
- Ensure the OpenAPI parameter definition includes
styleandexplode(or an explicit description of the encoding).
#603 - Document Implicit Filters and Default Sorting
Intent: prevent “missing data” surprises and make list results reproducible.
List/search endpoints MUST document any implicit constraints that affect which items appear, and MUST document the default ordering applied when the caller does not specify sorters.
1) Implicit filtering
Examples of implicit filtering:
- Results are scoped to the authenticated tenant/org.
- Results are limited to “resources visible to the caller” (RBAC/ABAC visibility filtering).
- Results exclude soft-deleted entities by default.
- Results exclude items in certain lifecycle states unless explicitly requested.
How to document:
- In the OpenAPI operation description, explicitly state the implicit constraints.
- If behavior is caller-dependent (authorization), say so clearly.
- If possible, expose explicit parameters to control behavior (e.g.,
includeDeleted=true) and document defaults.
2) Default sorting (required)
For every collection/list endpoint (including POST-based search endpoints), if the caller does not provide an explicit sorter, the API MUST apply exactly one documented default ordering policy.
Requirements:
- The default ordering is deterministic (repeat requests return consistent ordering absent data changes).
- The default ordering is documented per endpoint.
- The default ordering is stable enough for pagination (especially offset-based pagination).
Notes:
- The default ordering MAY be multi-field for tie-breaking stability, but it is documented as a single default policy (e.g., “default order:
createdAt desc, id asc”).
Example (docs text):
- If
sortersis omitted, results are ordered bycreatedAt:desc(ties broken byid:asc).
Related rules: [#600], [#602], [#604]
#604 - Use One Query Format Across the API
Intent: make querying consistent so docs, parsing, and shared logic can be reused.
APIs MUST align on a single, consistent query format across endpoints so all query experiences share the same documentation patterns and parsing logic.
Baseline conventions:
- Use the same parameter names and shapes across APIs:
filtersfor filter expressionssortersfor orderinglimit/offsetfor pagination (see Pagination)
- The grammar for
filtersandsortersMUST be consistent across endpoints. - Endpoints MUST document the allowed field list for filtering and sorting.
1) Simple queries via query parameters (GET)
Use query params for simple filters and ordering.
Example:
GET /accounts?filters=status eq "ACTIVE"&sorters=createdAt:desc&limit=50&offset=02) Complex queries via a single standard search endpoint pattern (POST)
When queries exceed practical URL length/complexity, use a dedicated POST search endpoint with GET-like semantics (no resource creation):
POST /{resource}/search
Requirements:
- Clearly document “search semantics; no creation”.
- Safe to retry when combined with idempotency guidance (see [#409], [#410]).
- Use a single standard request body shape across APIs (same field names, same operator set).
Example:
POST /accounts/search
Content-Type: application/json
{
"filters": [
{ "field": "status", "op": "eq", "value": "ACTIVE" },
{ "field": "createdAt", "op": "gte", "value": "2025-01-01T00:00:00Z" }
],
"sorters": [{ "field": "createdAt", "direction": "desc" }],
"limit": 50,
"offset": 0
}Notes:
- Do not invent bespoke query syntaxes per endpoint.
- Keep the documentation for the shared query grammar in one place and link to it from endpoints.
Related rules: [#600], [#601], [#603]
Pagination
#602 - Support Offset Pagination for List Endpoints
Intent: protect services and clients from unbounded responses and provide consistent navigation.
List endpoints MUST support offset-based pagination using limit and offset.
Required request parameters:
limit(integer): number of items to return- MUST document default and max
offset(integer): number of items to skip (default 0)count(boolean, optional): whether to include total count (if supported)
Response shape (required):
Return an object wrapper to preserve compatibility and allow metadata:
{
"items": [{ "id": "A" }, { "id": "B" }],
"limit": 2,
"offset": 0,
"count": 123
}Critical requirements:
- Define a stable default sort order (otherwise pagination is non-deterministic).
- Document performance characteristics:
- maximum supported
offset - cost of
count=true
- maximum supported
Cursor-based pagination:
- Not standard for these guidelines.
- Allowed only by exception and MUST be explicitly justified and documented (including sort stability, cursor encoding, and expiration semantics).
Related rules: [#204], [#600]