The Filtering and sorting pattern helps clients to retrieve resources based upon specific criteria and sort order.
14.1. Filtering and Sorting Conventions (query parameters, filter syntax)
Filtering and sorting are applied to the GET operation of a resource collection as query arguments:
- Simple equality:
GET /customers?status=ACTIVE
- Multiple values:
GET /customers?status=ACTIVE&status=ACTIVE,PENDING
- Range filters:
fromDate,toDate,minTotalAmount,maxTotalAmount
- Sorting:
sort=createdAtorsort=-createdAt- Structured sort object in body for POST-based search (e.g.,
/search-orders).
14.2. When to Use This Pattern
Use this pattern when the number of filters is limited and the filtering can be expressed with query arguments. Switch to a POST with a structured request body when more complex queries are needed.
Filtering and sorting need consistent patterns when applied, as not to confuse developers and machine-based consumers.
14.3. When NOT to Use This Pattern
-
If the number of filters exceeds a predetermined number, e.g., 20 fields, or require more expressive queries, use the Query / Search Model pattern instead.
-
Avoid using this pattern when filters contain PII/NPI data, as those values may be (and likely are) logged by intermediary servers, such as CDNs, API gateways, and in client and server log files. Use the Query / Search Model pattern to move sensitive data into the body, which is commonly not logged in web access logs.
14.4. Filtering OpenAPI Example
paths:
/customers:
get:
operationId: listCustomers
summary: List customers with equality and multi-value filters
description: |
Retrieves customers using **query parameter filters**.
**Filter Logic**:
- **AND**: Multiple different parameters combine with AND logic
- `?status=ACTIVE®ion=US` → status=ACTIVE AND region=US
- **OR**: Comma-separated values within a parameter use OR logic
- `?status=ACTIVE,PENDING` → status=ACTIVE OR status=PENDING
**Examples**:
- `GET /customers?status=ACTIVE` — Active customers only
- `GET /customers?status=ACTIVE,PENDING` — Active OR Pending customers
- `GET /customers?status=ACTIVE®ion=US` — Active customers in US
- `GET /customers?status=ACTIVE,PENDING®ion=US,CA` — (Active OR Pending) AND (US OR CA)
tags: [Customers]
parameters:
# --- Simple Equality Filter ---
- name: status
in: query
description: |
Filter by customer status.
- Single value: `status=ACTIVE`
- Multiple values (OR logic): `status=ACTIVE,PENDING`
required: false
schema:
type: string
example: ACTIVE,PENDING
examples:
single:
summary: Single status filter
value: ACTIVE
multiple:
summary: Multiple statuses (OR)
value: ACTIVE,PENDING
# --- Simple Equality Filter ---
- name: region
in: query
description: |
Filter by geographic region code.
- Single value: `region=US`
- Multiple values (OR logic): `region=US,CA,MX`
required: false
schema:
type: string
example: US
examples:
single:
summary: Single region
value: US
multiple:
summary: Multiple regions (OR)
value: US,CA,MX
# --- Simple Equality Filter ---
- name: customerType
in: query
description: |
Filter by customer type.
- `INDIVIDUAL`: Personal/consumer accounts
- `BUSINESS`: Business/corporate accounts
required: false
schema:
type: string
enum: [INDIVIDUAL, BUSINESS]
example: BUSINESS
# --- Simple Equality Filter ---
- name: accountManagerId
in: query
description: |
Filter by assigned account manager (UUID).
Returns customers managed by specified employee.
required: false
schema:
type: string
format: uuid
example: 7c9e6679-7425-40de-944b-e07fc1f90ae7
# --- Pagination (using offset for this example) ---
- name: offset
in: query
description: Zero-based starting index.
required: false
schema:
type: integer
minimum: 0
default: 0
- name: limit
in: query
description: Maximum items to return.
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: Filtered customer list.
headers:
X-Total-Count:
description: Total customers matching filter criteria.
schema:
type: integer
example: 342
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Customer'
example:
- customerId: "550e8400-e29b-41d4-a716-446655440001"
name: "Acme Corporation"
email: "contact@acme.com"
status: "ACTIVE"
region: "US"
customerType: "BUSINESS"
createdDate: "2024-01-10T09:00:00Z"
- customerId: "550e8400-e29b-41d4-a716-446655440002"
name: "TechStart Inc"
email: "info@techstart.com"
status: "PENDING"
region: "US"
customerType: "BUSINESS"
createdDate: "2024-02-15T11:30:00Z"
'400':
description: Invalid filter parameter.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
example:
type: "https://api.example.com/problems/invalid-parameter"
title: "Invalid Filter Parameter"
status: 400
detail: "Invalid status value 'UNKNOWN'. Allowed values: ACTIVE, PENDING, SUSPENDED, CLOSED."
instance: "/customer-management/v1/customers"
14.5. Sorting OpenAPI Example
paths:
/customers:
get:
operationId: listCustomers
summary: List customers with sorting options
description: |
Retrieves customers with **sorting** via query parameters.
**Sorting Convention**:
- `sort`: Field name to sort by
- `sortOrder`: Direction (`asc` for ascending, `desc` for descending)
**Examples**:
- `?sort=createdDate&sortOrder=desc` — Newest customers first
- `?sort=name&sortOrder=asc` — Alphabetical by name
- `?sort=totalSpend&sortOrder=desc` — Highest spenders first
**Default behavior**:
- If `sort` is omitted: results sorted by `createdDate`
- If `sortOrder` is omitted: defaults to `desc` (descending)
**Combining with filters**:
- `?status=ACTIVE&sort=totalSpend&sortOrder=desc`
→ Active customers sorted by highest spend
tags: [Customers]
parameters:
# --- Sorting Parameters ---
- name: sort
in: query
description: |
Field name to sort results by.
Must be a sortable field (not all fields support sorting).
required: false
schema:
type: string
enum:
- createdDate
- updatedDate
- name
- email
- totalSpend
- orderCount
- status
default: createdDate
example: createdDate
- name: sortOrder
in: query
description: |
Sort direction.
- `asc`: Ascending (A→Z, oldest→newest, lowest→highest)
- `desc`: Descending (Z→A, newest→oldest, highest→lowest)
required: false
schema:
type: string
enum: [asc, desc]
default: desc
example: desc
# --- Filters (for combining with sort) ---
- name: status
in: query
description: Filter by status (comma-separated for OR).
required: false
schema:
type: string
example: ACTIVE
# --- Pagination ---
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: Sorted customer list.
headers:
X-Total-Count:
description: Total customers matching filter criteria.
schema:
type: integer
example: 250
X-Sort:
description: The sort field applied.
schema:
type: string
example: totalSpend
X-Sort-Order:
description: The sort direction applied.
schema:
type: string
enum: [asc, desc]
example: desc
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Customer'
examples:
sortedBySpend:
summary: Sorted by total spend (descending)
value:
- customerId: "550e8400-e29b-41d4-a716-446655440001"
name: "MegaCorp Industries"
email: "procurement@megacorp.com"
status: "ACTIVE"
totalSpend: 125000.00
createdDate: "2023-06-15T10:00:00Z"
- customerId: "550e8400-e29b-41d4-a716-446655440002"
name: "Global Solutions"
email: "billing@globalsolutions.com"
status: "ACTIVE"
totalSpend: 89500.00
createdDate: "2023-09-22T14:30:00Z"
- customerId: "550e8400-e29b-41d4-a716-446655440003"
name: "StartupXYZ"
email: "founder@startupxyz.io"
status: "ACTIVE"
totalSpend: 45200.00
createdDate: "2024-01-08T09:15:00Z"
sortedByName:
summary: Sorted by name (ascending)
value:
- customerId: "550e8400-e29b-41d4-a716-446655440004"
name: "Alpha Tech"
email: "info@alphatech.com"
status: "ACTIVE"
totalSpend: 32000.00
createdDate: "2024-02-12T11:00:00Z"
- customerId: "550e8400-e29b-41d4-a716-446655440005"
name: "Beta Industries"
email: "contact@betaind.com"
status: "ACTIVE"
totalSpend: 18500.00
createdDate: "2024-03-05T08:45:00Z"
- customerId: "550e8400-e29b-41d4-a716-446655440006"
name: "Gamma Corp"
email: "sales@gammacorp.com"
status: "ACTIVE"
totalSpend: 67800.00
createdDate: "2023-11-20T16:20:00Z"
'400':
description: Invalid sort parameter.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
example:
type: "https://api.example.com/problems/invalid-parameter"
title: "Invalid Sort Parameter"
status: 400
detail: "The field 'lastLoginDate' is not sortable. Sortable fields: createdDate, updatedDate, name, email, totalSpend, orderCount, status."
instance: "/customer-management/v1/customers"