Introduction to Media Types
Media types, also called MIME types or content types, identify the format of data exchanged over HTTP. Registered by IANA and governed by RFC 6838, they underpin content negotiation, API versioning, and interoperability. A media type tells a recipient how to parse a body: application/json is JSON, text/html; charset=utf-8 is UTF-8 HTML. Understanding their structure, the vendor tree, and structured suffixes lets you design content types that evolve without breaking clients.
1. Structure and Registration Trees
A media type is a type/subtype pair, optionally followed by ; parameters. Type and subtype names are case-insensitive; parameter values follow per-parameter rules.
application/vnd.api+json; version=2└─────────┘ └─┘└─┘ └──┘ └───────┘ type tree name suffix parameterThe top-level type categorizes the data (application, text, image, audio, video, and others). RFC 6838 organizes subtypes into registration trees:
| Tree | Prefix | Purpose |
|---|---|---|
| Standards | (none) | General-interest types approved by IETF or recognized bodies. |
| Vendor | vnd. |
Types tied to a publicly available product; lets vendors define custom formats. |
| Personal | prs. |
Experimental or non-commercial use. |
| Unregistered | x. |
Private, local use; discouraged now that vendor/personal registration is simple. |
The structured suffix
A +suffix names the underlying data format regardless of the specific semantics. application/vnd.api+json is parseable as JSON (+json) but adds the semantics defined by the JSON:API specification. Common suffixes include +json, +xml, and +zip. This lets a generic parser recognize the base structure even for a custom type.
2. The Content-Type and Accept Headers
Two headers carry media types across the request/response cycle.
Content-Type
The Content-Type header declares the media type of a message body. Servers set it on responses so clients know how to interpret the payload; clients set it on POST, PUT, and PATCH requests to describe the body they are sending.
POST /orders HTTP/1.1Host: api.apiguide.devContent-Type: application/json
{ "sku": "A-100", "qty": 3 }Accept
The Accept header lets a client state which media types it is willing to receive, enabling content negotiation. Wildcards (*/*, type/*) and q quality values rank preferences.
GET /orders/501 HTTP/1.1Host: api.apiguide.devAccept: application/json, text/csv;q=0.8This client prefers JSON but accepts CSV if JSON is unavailable. Note that while q is standard in Accept, the media type registry disallows a q parameter in registration to avoid interfering with negotiation.
3. Versioning via Media Types
Media types offer an alternative to URL-path versioning that keeps a single URI stable across versions. Version information can live in the subtype name or in a parameter:
Accept: application/vnd.status.v2+jsonAccept: application/vnd.status+json; version=2JSON:API uses application/vnd.api+json with ext and profile parameters to negotiate extensions and profiles, a form of semantic negotiation layered on the base type. When a request uses the JSON:API media type with any parameter other than ext or profile, servers must respond with 415 Unsupported Media Type. See the versioning guide for how this compares to path- and header-based schemes.
4. Best Practices
- Prefer standard types. Use
application/json(andapplication/xmlwhere needed) for general data exchange; reach for custom types only when new semantics demand it. - Design custom types sparingly. Create a
vnd.*type when a resource carries genuinely new processing semantics, not for every minor variation, and document it publicly. - Always set
Content-Type. Set it accurately on every response and on every request that carries a body, including acharsetfor text formats. - Default to JSON. When
Acceptis absent, respond with JSON for maximum compatibility. - Vary on
Accept. When a response’s format depends on theAcceptheader, addVary: Acceptso caches store representations separately. - Disable MIME sniffing. Send
X-Content-Type-Options: nosniffso browsers do not second-guess your declared type.
5. Common Pitfalls
- Media type explosion. Minting an overly specific type for every attribute or resource complicates the API and hurts interoperability. Favor “chunky” representations over fine-grained ones, and let a schema, rather than the media type, describe structure.
- Unsupported request bodies. If a client sends a body the server cannot process, return
415 Unsupported Media Type. - Ignored client preferences. If no representation satisfies the
Acceptheader, return406 Not Acceptable, ideally listing supported formats. - Missing or mismatched
Content-Type. An absent header, or one that disagrees with the actual body, commonly produces a400 Bad Request.
Summary
Media types are the vocabulary of HTTP content negotiation. Their type/subtype structure, the vnd. vendor tree, and the +json structured suffix together allow custom formats that generic tooling can still parse. Carry them with Content-Type and Accept, use them judiciously for versioning, default to standard types, and return 415 or 406 when negotiation fails. The result is an interoperable API that can evolve without breaking its clients.