REST API Filter Query Examples
REST API filtering best practices begin with a small, documented query grammar: allowlist fields and operators, define deterministic sorting, validate every value, and keep query complexity bounded.
For common equality filters, simple query parameters are usually the clearest API:
GET /v1/orders?status=paid&customer_id=cus_42&sort=-created_atFor range and comparison operations, define an explicit syntax instead of accepting raw SQL-like expressions:
GET /v1/orders?created_at_gte=2026-10-01T00:00:00Z&amount_lte=50000&sort=-created_at,idAnother option is a structured operator grammar:
GET /v1/orders?filter[status][eq]=paid&filter[amount][lte]=50000&sort=-created_atChoose one grammar and document it. Consistency is more important than squeezing every possible operator into the first version.
REST API Filtering Syntax: Common Patterns
| Pattern | Example | Good for | Watch for |
|---|---|---|---|
| Direct parameters | ?status=paid | Simple equality filters | Name collisions with control parameters. |
| Operator suffix | ?amount_gte=100 | Small known operator set | Field/operator parsing must be explicit. |
| Structured filter | ?filter[amount][gte]=100 | Larger query surface | Nested parsing and documentation complexity. |
| Single expression | ?filter=status:eq:paid | Custom advanced grammars | Easy to accidentally build an unsafe mini-language. |
Avoid passing user text directly into ORM “order by” or dynamic SQL helpers. Parse public filter names into internal allowlisted fields and typed operators.
Whatever grammar you choose, document URL encoding with real examples. Characters such as brackets, commas, colons and spaces can be encoded or normalized differently by SDKs, gateways and frameworks, so test the exact representation that reaches the application.
REST API Filter Operators
- Equality:
eq/ exact match. - Inequality:
newhen the use case truly requires it. - Ranges:
gt,gte,lt,ltefor numbers and timestamps. - Membership:
infor bounded lists of values. - Text search: expose a dedicated
qor search parameter instead of generic arbitrary regex by default. - Null/existence: include only if the resource model needs clients to distinguish missing from explicit values.
REST API Sorting Best Practices
A compact convention is a comma-separated sort parameter where a leading minus means descending:
GET /v1/orders?sort=-created_at,idAllowlist sortable fields. Always add a deterministic unique tiebreaker for pagination. If many orders have the same created_at, sorting by created_at alone can produce unstable pages; created_at, id defines a total order.
Default sort
Every collection endpoint should have a documented default ordering. “Whatever the database returns” is not a stable API contract.
Expensive sorts
Do not expose arbitrary sorting on unindexed or high-cardinality computed fields without understanding the cost.
Filtering, Sorting and Pagination Together
Pagination must preserve the exact filter and sort semantics across continuation requests. Cursor pagination should bind its continuation state to the logical query, so a cursor created for status=paid cannot be silently reused for status=failed.
See the companion REST API pagination examples and best practices for cursor and offset response formats.
Safe Filtering Implementation Pattern
PUBLIC_FILTERS = {
"status": {"column": "status", "ops": ["eq", "in"]},
"amount": {"column": "amount_cents","ops": ["eq", "gte", "lte"]},
"created_at": {"column": "created_at", "ops": ["gte", "lte"]}
}
PUBLIC_SORTS = {"created_at", "amount", "id"}
MAX_FILTERS = 8
MAX_IN_VALUES = 50The public parameter name should map to an internal field through application code. Values should be parsed into expected types and then passed as bound parameters. Do not concatenate untrusted field names, operators or values into SQL text.
Security Controls for REST API Filtering
- Allowlist filter fields, sort fields and operators.
- Validate type, length and cardinality of every value.
- Set maximum filter count and maximum list size for
inoperations. - Reject unknown parameters when strict contracts are important; silent ignore can hide client mistakes.
- Authorize the resulting dataset independently of the filter. A filter is not an access-control boundary.
- Monitor expensive combinations and automated enumeration patterns.
- Prevent regex, wildcard or full-text expressions from becoming denial-of-service primitives.
See REST API endpoint security best practices for the broader validation and authorization model.
Common Filtering and Sorting Mistakes
- Exposing arbitrary database column names as public filter fields.
- Accepting a raw SQL fragment in
filterorsort. - Letting clients sort by any property even when no supporting index exists.
- Combining cursor pagination with a non-deterministic sort.
- Returning different filter behavior on different endpoints for the same resource type.
- Adding complex operators without limits, cost controls or query observability.
How Multiple REST API Filters Should Combine
Document whether repeated or separate filters are combined with AND or OR semantics. A predictable default is to AND different fields and define a separate membership operator for OR-like matching within one field.
# AND across fields
GET /v1/orders?status=paid®ion=eu
# OR-like membership within a field
GET /v1/orders?status_in=paid,refunded
# Range
GET /v1/orders?amount_gte=1000&amount_lt=5000Avoid ambiguous repeated parameters unless your framework preserves them reliably across proxies and SDKs. If ?status=paid&status=failed is supported, state whether it means OR, AND, first-wins or last-wins.
Filtering Performance, Indexes and Query Complexity
Every public filter combination has a physical cost. A query that looks harmless at ten thousand rows can become a table scan at hundreds of millions. Review the filters and sort combinations you intentionally support, then design indexes and limits around those access patterns.
- Put hard bounds on range width where very broad scans are not a valid product use case.
- Limit the number of values accepted by membership operators such as
in. - Avoid arbitrary leading-wildcard text search on transactional tables unless a search index is designed for it.
- Measure query plans for common filter + sort + pagination combinations.
- Consider asynchronous export jobs when the real use case is “download everything,” rather than stretching the normal collection endpoint.
Security and performance align here: the same unbounded query flexibility that makes databases slow also gives attackers a useful resource-exhaustion surface.
For public APIs, consider a query-complexity budget in addition to raw request rate: number of filters, membership-list size, sort fields, requested expansions and estimated result cost can all contribute to one request becoming disproportionately expensive.
How Ammune Fits
Filtering can amplify enumeration and data-extraction behavior because a client can systematically narrow and traverse a collection. Ammune can observe query-parameter patterns, endpoint usage and response behavior at runtime, helping teams identify unusual filtering, scraping or automated discovery while the API enforces strict query grammar and authorization.
Production Implementation Checklist
- Define one documented filter syntax.
- Allowlist filter fields and operators.
- Parse values into explicit types before querying.
- Allowlist sortable fields and define a deterministic default sort.
- Document AND/OR and repeated-parameter semantics.
- Cap filter count, list cardinality and expensive search ranges.
- Use parameterized database queries.
- Design indexes for supported filter + sort combinations.
- Bind cursor pagination to the same filter/sort state.
- Monitor high-cost query combinations and automated enumeration.
Frequently Asked Questions
What is the best way to implement filtering in a REST API?
Use documented query parameters with an allowlisted set of fields and operators. Parse values into expected types and translate them into parameterized database queries rather than accepting raw query expressions.
How should sorting work in a REST API?
A common pattern is a sort parameter with comma-separated fields and a leading minus for descending order. The API should allowlist sortable fields and provide a deterministic default order.
What filter operators should a REST API support?
Start with the smallest set the product needs: equality, bounded membership, and range operators are common. Add text, null or advanced operators only when use cases justify their cost and complexity.
Can REST API filters cause SQL injection?
Yes, if field names, operators or values are concatenated directly into SQL. Use allowlisted mappings for identifiers and parameterized queries for values.
How do filters work with cursor pagination?
The cursor must resume the same logical filtered and sorted result set. Bind or validate the cursor against the filter and sort configuration so it cannot be reused under incompatible query semantics.
Primary References
See How Clients Query Your APIs in Production
Strict filter grammar controls what clients may ask for. Runtime API behavior shows how those filters are actually being used at scale.
