HTTP Content Negotiation for JSON and XML Payloads

Content negotiation in modern web APIs allows clients and servers to dynamically agree on the data serialization format—primarily JSON or XML—used for exchanging information. By utilizing standard HTTP headers such as Accept and Content-Type, along with preference weighting, applications can serve multiple media formats from a single endpoint without altering the underlying resource URI.

The Core Negotiation Headers

Content negotiation primarily relies on two HTTP headers:

Requesting Formats with the Accept Header

When a client queries an endpoint, it explicitly requests its preferred format:

Clients can also express preferences using quality values (q-factors), which range from 0.0 to 1.0. A higher value denotes higher priority. For example:

Accept: application/json;q=1.0, application/xml;q=0.8, */*;q=0.1

In this case, the server evaluates the request and delivers JSON if supported. If JSON is unavailable, it falls back to XML before considering any other fallback representation.

Server Response and Status Codes

The server evaluates the incoming Accept header against its supported serialization engines:

  1. Successful Negotiation (200 OK): The server generates the payload in the selected format and returns a Content-Type header matching the output (e.g., Content-Type: application/json; charset=utf-8).
  2. Unfulfillable Preference (406 Not Acceptable): If the server cannot provide any of the requested formats in the Accept header, it should ideally return an HTTP 406 Not Acceptable status, though many modern APIs simply fall back to a default format (typically JSON).
  3. Invalid Payload (415 Unsupported Media Type): When a client sends a POST, PUT, or PATCH request with an unsupported payload format declared in its Content-Type, the server rejects the request with an HTTP 415 status.

Caching and the Vary Header

To ensure intermediary caches and CDNs do not serve a cached JSON response to a client requesting XML (or vice versa), servers must include the Vary: Accept response header. This instructs caching layers to store separate copies of the resource indexed by the client’s Accept header value.