| title | HTTP Finally Has a `QUERY` Method: What It Means for API Design | ||
|---|---|---|---|
| date | 2026-07-06 01:21:56 +0530 | ||
| tags |
|
For years, API developers have faced an awkward choice when implementing complex read operations:
- Use
GETand squeeze everything into query parameters. - Use
POSTwith a request body, even though the operation doesn't actually modify anything.
Neither option was ideal.
The newly standardized HTTP QUERY method aims to solve this problem by providing a safe, idempotent request method that supports request bodies for complex queries. The method was standardized in RFC 10008 in 2026.
GET is perfect for simple retrieval operations:
GET /users?role=admin&page=1However, modern APIs often require much more complex filters:
{
"filters": {
"roles": ["admin", "moderator"],
"createdAfter": "2025-01-01",
"active": true
},
"sort": [
{
"field": "createdAt",
"direction": "desc"
}
],
"page": 1,
"limit": 50
}Encoding this into a URL becomes messy and may hit practical URL length limits imposed by browsers, proxies, or servers.
Many APIs use POST for search endpoints:
POST /users/search
Content-Type: application/json
{
"filters": {
"roles": ["admin"]
}
}While this works, it introduces semantic problems:
POSTis not guaranteed to be safe.- It is not inherently idempotent.
- Caches and intermediaries often treat it differently.
- Automatic retries become more complicated.
The operation is fundamentally a read operation, but the HTTP method suggests otherwise.
The new QUERY method combines the best aspects of both approaches.
It allows request bodies while maintaining the semantics of a read-only operation:
QUERY /users
Content-Type: application/json
{
"filters": {
"roles": ["admin", "moderator"]
},
"sort": [
{
"field": "createdAt",
"direction": "desc"
}
]
}According to RFC 10008, QUERY requests are:
- Safe (they should not modify server state)
- Idempotent (multiple identical requests produce the same effect)
- Compatible with caching mechanisms
- Suitable for automatic retries by clients and intermediaries
E-commerce platforms often support complex filtering:
{
"categories": ["electronics"],
"priceRange": {
"min": 100,
"max": 1000
},
"brands": ["Apple", "Sony"],
"inStock": true
}QUERY provides a natural way to express these searches without abusing POST.
GraphQL commonly uses POST even for read-only operations:
query {
users(role: "admin") {
id
name
email
}
}The QUERY method aligns much better with GraphQL's read semantics while still allowing complex request bodies.
Reporting systems frequently accept large, structured filter definitions:
{
"dateRange": {
"start": "2026-01-01",
"end": "2026-06-30"
},
"dimensions": ["country", "device"],
"metrics": ["revenue", "sessions"]
}These requests are perfect candidates for QUERY.
Probably not.
Support across browsers, frameworks, proxies, CDNs, and API gateways is still limited. Adoption will likely take years, much like previous HTTP extensions.
In the short term:
- Continue using
GETfor simple retrieval operations. - Use
POSTfor complex read requests if infrastructure support is required. - Consider experimenting with
QUERYin controlled environments or internal APIs.
The introduction of QUERY fills a long-standing gap in HTTP semantics.
For the first time, developers have a standardized way to perform complex, read-only operations with request bodies while preserving the safety and idempotency guarantees that GET provides.
It may take time before it becomes mainstream, but it represents an important step toward more expressive and semantically correct API design.
The next generation of data-heavy APIs might finally stop pretending that every complex search is a POST request.
fin.