Content Negotiation in OpenAPI
Content negotiation selects a representation format for HTTP requests and responses. OpenAPI records supported media types and their schemas, while runtime code handles the actual selection, parsing, and response headers.
Content negotiation is the process by which a client and server select a representation format for an HTTP message. Media types such as `application/json` and `text/csv` identify formats; they do not, by themselves, define the data structure.
For a request body, the client commonly sends `Content-Type` to state the format it is sending. In OpenAPI, the operation's `requestBody.content` map declares which media types and schemas the operation accepts. A server may reject an unsupported request format, commonly with `415 Unsupported Media Type`.
For a response, the client can send `Accept` to express which formats it prefers or permits. OpenAPI declares response representations under each response's `content` map. The server chooses a supported representation and labels the actual response body with `Content-Type`; if it cannot provide an acceptable format, it may return `406 Not Acceptable`.
OpenAPI documents the contract, but does not perform negotiation or require a particular selection algorithm. Servers should implement behavior consistent with the declared contract, including handling quality values in `Accept` if they support them. When a response varies based on `Accept`, HTTP caching may need `Vary: Accept` so caches distinguish representations.
Key points
- `Content-Type` describes the body format being sent; `Accept` expresses acceptable response formats.
- OpenAPI places request formats in `requestBody.content` and response formats in each response's `content`.
- A media type names a representation format; a schema describes its data shape.
- OpenAPI documents supported representations but does not execute runtime negotiation.
- Use appropriate error behavior for unsupported request formats or unacceptable response formats.
Interview questions
What is the difference between `Accept` and `Content-Type`?
`Content-Type` identifies the format of the body being sent, while `Accept` communicates which response formats the client can handle. For example, a client may send JSON with `Content-Type: application/json` and request a JSON response using `Accept: application/json`. The server's response `Content-Type` identifies the format it actually returned.
How do you describe request and response media types in OpenAPI?
Declare request formats under the operation's `requestBody.content`, with a schema for each media type as needed. Declare response formats under the relevant response's `content` map. This documents the formats clients may send and receive, but the application still needs to parse requests, select responses, and return appropriate headers.
How should a server handle an `Accept` header with multiple media types and quality values?
An `Accept` header can list multiple media types and assign quality weights using `q` parameters. A server that supports these weights should choose the best acceptable representation it can provide, while respecting its own supported formats and any applicable specificity rules. If no supported representation is acceptable, the server can return `406 Not Acceptable`. The chosen response should carry the matching `Content-Type`.
How do media types relate to schemas in an OpenAPI contract?
The schema describes the data shape, whereas the media type identifies the representation format used to carry that data. A schema can be used for JSON and another format if both formats encode the same logical data, though serialization constraints may differ. In OpenAPI, the schema is associated with a particular media type inside the `content` map. Clients should not assume that a schema alone tells them how bytes on the wire are encoded.