Skip to main content

Media Types & Vendor Content Types

How media types structure content, how the vendor tree and +json suffix work, and how to version APIs through the Accept header.

Topic:RepresentationUpdated:2026-10-13

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 parameter

The 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.1
Host: api.apiguide.dev
Content-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.1
Host: api.apiguide.dev
Accept: application/json, text/csv;q=0.8

This 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+json
Accept: application/vnd.status+json; version=2

JSON: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 (and application/xml where 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 a charset for text formats.
  • Default to JSON. When Accept is absent, respond with JSON for maximum compatibility.
  • Vary on Accept. When a response’s format depends on the Accept header, add Vary: Accept so caches store representations separately.
  • Disable MIME sniffing. Send X-Content-Type-Options: nosniff so 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 Accept header, return 406 Not Acceptable, ideally listing supported formats.
  • Missing or mismatched Content-Type. An absent header, or one that disagrees with the actual body, commonly produces a 400 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.

On this page (7 sections)