2026-09-19 · 8 min read
- http
- content-negotiation
- api-design
Proactive HTTP content negotiation lets a client describe acceptable response representations and lets the server select one it can produce. Accept can contain exact media types, wildcards, parameters, and quality values, so selection is more than checking whether a string contains application/json.
A good API publishes the variants each route can produce, the default when Accept is absent, the policy when no variant is acceptable, and the request fields that affect shared-cache variants.
Model server capabilities first
Represent each available variant with its media type, required parameters, language or encoding dimensions handled elsewhere, and a stable server preference. Do not advertise a type that an error serializer, streaming path, or gateway cannot actually produce.
- Treat an absent Accept field as allowing any media type.
- Treat q=0 as explicit unacceptability for the matched range.
- Use a compliant parser for quoted parameters and repeated fields.
- Reject or handle malformed input under one documented policy.
Rank matches deterministically
Match available representations against the client's media ranges using the HTTP specification and framework behavior chosen for the API. Specific ranges and parameters can override broader wildcards; quality values express relative preference among acceptable matches.
When several variants remain equally preferred, use a stable server-side order rather than object iteration or deployment-dependent registration order. Preserve this decision in contract tests before upgrading the framework's negotiator.
Choose clear failure and response metadata
For APIs with a strict representation contract, 406 Not Acceptable is often clearer than silently returning a type the client excluded. If the product intentionally disregards an unusable Accept field, document that fallback and make clients resilient to it.
- Return the selected Content-Type on success and errors.
- Avoid sending a body whose bytes do not match its declared type.
- Use Problem Details or another stable error contract consistently.
- Keep representation selection separate from request Content-Type validation.
Make caches and tests variant-aware
When Accept influences the response, send an appropriate Vary field and ensure the CDN or reverse proxy honors it. Minimize unnecessary dimensions so the cache does not fragment on headers that never change the selected bytes.
Use Flashman's URL tool for endpoint fixtures, JSON formatter for sample representations, diff for header sets, case converter for token-handling checks, and hash for exact public response fixtures. Test absence, exact matches, wildcards, parameters, zero and equal weights, malformed values, repeated lines, errors, cache hits, and every client and intermediary.