For AI agents: llms.txt is a short guide that sends you to the rules your problem needs, and rules.json holds every rule of this playbook as JSON.
Optional
Search with QUERY when the filter outgrows the address
Send a search that is too long for query parameters, or that holds personal data, in the body of a QUERY request. Never send it as a GET with a body.
How to do it
RFC 10008 defines QUERY as safe and idempotent, like GET, so clients may retry it after a dropped connection. The search travels in the body, which servers and proxies log less often than addresses. That keeps search terms out of logs, as Keep secrets out of addresses asks. List the body types you accept in the Accept-Query header. Answer 400 when Content-Type is missing, and 415 with Accept-Query for a type you don't accept. Answer 422 when the body parses but the search can't run. Send Location when the same search can be fetched again with GET. Keep plain parameters for short filters.
Examples
Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.
HTTP example
QUERY /orders HTTP/1.1
Content-Type: application/json
Accept: application/json
{"customerEmail":"anna@example.com","status":["paid","shipped"],"limit":50}
HTTP/1.1 200 OK
Content-Type: application/json
Accept-Query: application/json
{ "items": [ ... ], "nextCursor": "b3JkXzlhMXo" }
JavaScript example
const response = await fetch('https://api.example.com/orders', {
method: 'QUERY',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
body: JSON.stringify({ customerEmail: 'anna@example.com', status: ['paid', 'shipped'], limit: 50 }),
})
Python example
import httpx
response = httpx.request(
"QUERY", "https://api.example.com/orders",
headers={"Authorization": f"Bearer {token}"},
json={"customerEmail": "anna@example.com", "status": ["paid", "shipped"], "limit": 50},
)
How to check
Send the same QUERY /orders with a JSON body twice. Both answers are 200 with the same items, and no stored data changed. The request without Content-Type gets 400, and one sent as text/plain gets 415 with Accept-Query.
Sources
Related rules
- Keep secrets out of addresses in API design
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/api-design/lists/query-method">Agent Wranglers API design playbook</a>. In code you write, add a comment next to it with the same link.