skip to content

In OpenAPI 3.x, how are an operation's responses keyed, and what does default mean?

level: middleimportance: should knowfreq 52%

answer

  1. A map, not an array
  2. Quote the codes in YAML
  3. Uppercase X in range keys
  4. One required field per response object
  5. Fallback for anything undescribed

basics

~20 s

An OpenAPI responses object maps quoted HTTP status codes such as '200', uppercase range wildcards such as '4XX', and the literal key default to Response Objects. default covers any status not matched explicitly. Every Response Object requires a description.

solid answer

~40 s

`responses` is a map, not a list. Its keys are HTTP status codes written as strings — `'200'`, `'404'` — because YAML would otherwise read them as integers, plus optional range wildcards `1XX` through `5XX` with an uppercase X, plus the literal key `default`. A more specific key always wins over a range, and `default` is the fallback for any code not otherwise described; it is commonly used for a shared error envelope. Each Response Object requires a `description` — that is the single most-forgotten required field in the whole spec — and may carry `content` (a map keyed by media type, each with a schema and examples), `headers` (response headers, excluding `Content-Type`, which is expressed by the content keys), and `links`. A 204 response legitimately has a description and no `content` at all.

code

yaml · 25 lines
yaml
responses:
  '200':
    description: The order
    headers:
      ETag:
        schema:
          type: string
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Order'
  '204':
    description: Order exists but has no body to return
  '4XX':
    description: Client error
    content:
      application/problem+json:
        schema:
          $ref: '#/components/schemas/Problem'
  default:
    description: Unexpected error
    content:
      application/problem+json:
        schema:
          $ref: '#/components/schemas/Problem'

go deeper

for a junior

Recall that responses is a map from quoted status codes to objects, and that each one needs a description.

for a middle

Explain range keys, the specificity order of explicit code over range over default, and why a 204 is modelled by omitting content entirely.

for a senior

Show the production judgment: enumerate the failures callers branch on, reuse shared error responses from components, and know that a stray 201 falling into default breaks generated clients.

for a principal

Own the error-response convention across the estate — one envelope shape, one reusable set of components, and rules about which codes every operation must document.

## The shape of the responses object Under an operation, `responses` describes every outcome the endpoint can produce. It is a map whose keys identify status codes and whose values are Response Objects (or `$ref`s to reusable ones under `components.responses`). Three kinds of key are allowed: 1. **An explicit status code**, written as a string: `'200'`, `'201'`, `'404'`, `'422'`. In YAML these must be quoted, otherwise the parser produces the integer `200` and strict tooling rejects the document. 2. **A range wildcard**: `'1XX'`, `'2XX'`, `'3XX'`, `'4XX'`, `'5XX'`. The `X` is uppercase — a lowercase `4xx` is not a valid key. A range matches any code in that class. 3. **`default`** — the literal word, describing the response for any status code not covered by an explicit key or a matching range. When more than one key could match, the most specific wins: an explicit `'404'` beats `'4XX'`, which beats `default`. ## The Response Object `description` is REQUIRED. A response with a schema but no description is an invalid document, and this is the most common validation failure in hand-written specs. The description is prose — "The requested order", "Validation failed" — and is what documentation renderers show next to the status code. `content` is a map keyed by media type: `application/json`, `application/problem+json`, `text/csv`, and wildcards such as `application/*` or `*/*`. Each media-type entry holds a `schema` plus optional `example`/`examples` and `encoding`. Because the response's content type is expressed by these keys, you do **not** declare a `Content-Type` response header — the specification explicitly says a `Content-Type` entry in `headers` is ignored. `headers` is a map of header name to Header Object, describing headers the response carries: `Location`, `Retry-After`, `X-RateLimit-Remaining`, `ETag`. Header names are case-insensitive in HTTP, and the spec says a header named `Content-Type` is ignored here. `links` describes how the result of this operation can be used as input to another one, referencing that operation by `operationId` or `operationRef`. It is the specification's hypermedia hook and is sparsely supported by tooling. ## Responses with no body A `204 No Content` or a `304 Not Modified` has no payload. The correct modelling is a Response Object with a `description` and no `content` key at all — not `content` mapped to an empty schema, and not a schema of `type: 'null'`. Generators read the absence of `content` as a void return type. ## What `default` is good for, and its trap The usual pattern is a single shared error envelope: describe the success codes explicitly and put the error schema under `default`, so any unenumerated failure still has a documented shape. The trap is over-reliance: if `default` is the only non-2xx entry, the document tells a consumer nothing about which failures are actually possible, and generated clients often collapse every error into one exception type. Mature specs enumerate the failures a caller must branch on — 401, 403, 404, 409, 422 — and let `default` catch the rest. A second trap is that `default` is not the same as `'2XX'`. It is a catch-all for *anything* undescribed, including success codes. If an operation can return either 200 or 201 and only 200 is listed, a 201 falls into `default` — which is usually your error schema, and the generated client then tries to deserialize a success body as an error. ## Reuse Repeating the same 401 or 429 block on forty operations is a smell. Put it under `components.responses` once and reference it from each operation. The status-code key stays local to each operation; only the Response Object body is shared. ## What an interviewer is checking That you know `responses` is a keyed map rather than a list, that codes are strings, that `description` is required, that content-type lives in the `content` keys rather than a declared header, and that you have an opinion about enumerating errors versus leaning on `default`.

  • How do you model a 204 No Content response?
    A Response Object with a `description` and no `content` key. Omitting `content` is what tells tooling there is no body; declaring an empty schema instead makes generators emit a pointless empty model type and can make validators expect a payload.
  • Why must status codes be quoted in a YAML OpenAPI document?
    Unquoted `200` parses as an integer, but the specification requires the keys of the responses object to be strings. Many parsers coerce it silently and some linters fail the document, so quoting is the portable habit. The `default` key is a bare word by contrast.
  • Where do you declare the response's Content-Type?
    You do not declare it as a header. The media-type keys under `content` — `application/json`, `text/csv` — are the declaration. The specification says a `Content-Type` entry in the response `headers` map is ignored, so writing one is dead documentation.

saying these in an interview costs you the question

  • Writes responses as an array of status codes
  • Omits the required description on a response
  • Declares Content-Type as a response header
  • Uses lowercase 4xx as a range key
  • Puts only default and calls the errors documented

context