In OpenAPI, when do you use requestBody instead of a parameter, and what does its content map key on?
answer
- Two homes for input, one for bytes in the body
- The map's keys are not field names
- One boolean defaults the permissive way
- Ranges are allowed, most specific wins
- Form fields moved here in 3.x
basics
~20 sIn OpenAPI 3.x anything sent in the HTTP message body is a requestBody, never a parameter. Its content map is keyed by media type, each entry carrying its own schema and examples. requestBody defaults to required: false, so a mandatory payload must say so explicitly.
solid answer
~40 sOpenAPI 3.x splits inputs cleanly: values in the URL, headers or cookies are Parameter Objects; everything in the message body is the single `requestBody`. The Request Body Object has three fields — `description`, `required` (default **false**), and `content`. `content` is a map keyed by media type, so one operation can accept `application/json` and `application/xml` with different schemas, or a `multipart/form-data` variant. Keys may be ranges such as `text/*` or `*/*`, and when a request matches several keys the most specific one applies. Form fields belong here too: Swagger 2.0's `in: formData` was replaced by an `application/x-www-form-urlencoded` entry. The spec gives no defined semantics for a body on `GET`, `HEAD` or `DELETE` and advises avoiding it, so a search with a large payload usually becomes a POST.
code
yaml · 27 linespaths:
/orders:
post:
operationId: createOrder
requestBody:
description: The order to create
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
examples:
minimal:
value:
sku: A-100
quantity: 2
application/x-www-form-urlencoded:
schema:
type: object
properties:
sku:
type: string
quantity:
type: integer
responses:
'201':
description: Createdgo deeper
Know that the payload of a POST or PUT is described by requestBody with a content map keyed by media type, and that parameters cover the URL, headers and cookies.
Explain the required: false default, how several media types coexist in one content map, and that form fields moved from in: formData into a urlencoded body in 3.x.
Show judgment on the debatable cases — large filters as a POST search versus a long query string — and catch the missing required: true in review before it reaches generated clients.
Own where shared payloads live in components.requestBodies and set the rule on media types the platform accepts, so every service's generated clients offer the same set.
## The 3.x split Swagger 2.0 had a single `parameters` list containing everything, including `in: body` and `in: formData`. OpenAPI 3.x separated the two ideas: a **Parameter Object** describes a value that travels in the URL, a header or a cookie; the **Request Body Object** describes the message body. An operation has at most one `requestBody` and any number of parameters. If a candidate mentions `in: body`, they are describing 2.0. ## The Request Body Object Three fields: - **`description`** — free text, CommonMark allowed. - **`required`** — boolean, **defaults to `false`**. This is the single most commonly missed default in the whole document: an operation that cannot work without a payload still declares the body optional unless you write `required: true`. Generated clients then make the body argument nullable, and request validators let an empty POST through. - **`content`** — a map from media type to Media Type Object. This field is required. ## The content map Each key is a media type or media type range; each value is a Media Type Object holding `schema`, `example` or `examples`, and (for form and multipart bodies) `encoding`. Keying on media type is what makes one operation able to accept several representations — an `application/json` entry and an `application/xml` entry can even point at the same schema via `$ref`. Ranges are legal — `image/*`, `text/*`, `*/*` — and when a request matches more than one key, only the most specific applies: an explicit `text/plain` entry wins over `text/*`. Note that the media type is the *key*: you do not declare a `Content-Type` header parameter. A header parameter named `Content-Type` is explicitly ignored by the specification precisely because this map already carries that information. ## Form bodies HTML form submissions are request bodies in 3.x, not parameters. `application/x-www-form-urlencoded` takes an object schema whose properties are the form fields; `multipart/form-data` does the same with each property becoming one part. The `encoding` map on the Media Type Object then tunes how individual properties are serialized — for urlencoded bodies it accepts `style`, `explode` and `allowReserved`, mirroring the query-string keywords, and for multipart it accepts `contentType` and `headers`. ## Bodies on GET, HEAD and DELETE OpenAPI notes that `requestBody` is only meaningful for HTTP methods whose semantics define a body, and that for methods where the HTTP specification is vague — `GET`, `HEAD`, `DELETE` — a body is permitted in the document but has no well-defined meaning and should be avoided. Practically: intermediaries, client libraries and server frameworks vary in whether they forward or read such a body at all. When a query genuinely needs a structured payload the usual answer is a POST-based search operation, described with a normal `requestBody`. ## Choosing between a parameter and a body The decision is mechanical rather than stylistic — it follows from where the bytes go. Values that identify the resource belong in the path; values that select, filter or page belong in the query; per-request metadata belongs in headers; the representation being created or replaced belongs in the body. The genuinely debatable case is the large query, and the tradeoff there is cacheability and bookmarkability against URL length limits and expressiveness. ## Reuse A whole request body can be reused: `components.requestBodies` holds named Request Body Objects, referenced with `$ref` from operations. This is the right home for a payload shared across several operations, and it keeps the schema, the examples and the `required` flag together rather than re-deriving them per operation. ## Common defects - Omitting `required: true` on a body the operation cannot work without. - Declaring a `Content-Type` header parameter alongside the content map, which is ignored. - Writing `in: body`, a Swagger 2.0 construct that no 3.x validator accepts. - Declaring one `application/json` entry while the service actually also accepts `application/x-www-form-urlencoded`, so generated clients cannot express the second form. - Putting a body on a `GET` and expecting the whole toolchain to carry it.
- What is the default value of requestBody's required field, and why does it matter?It defaults to `false`. An operation whose handler dereferences the payload immediately will still be documented as accepting no body, so generated clients make the argument optional or nullable and request validators accept an empty POST. Any body the operation genuinely needs must carry `required: true` explicitly — it is the most frequently missed default in the document.
- How does an OpenAPI document describe an HTML form submission?As a request body, not as parameters. Use a `content` entry keyed `application/x-www-form-urlencoded` (or `multipart/form-data` for file uploads) whose schema is an object; each property is one field. Swagger 2.0's `in: formData` parameter location no longer exists in 3.x, and the `encoding` map on the media type tunes per-field serialization.
- If a content map has both text/plain and text/* keys, which applies?The most specific matching key wins, so a request with `Content-Type: text/plain` is described by the `text/plain` entry and any other `text/...` type falls back to `text/*`. Media type ranges are legal keys precisely so a document can describe a catch-all alongside one or two exact types without enumerating every possibility.
saying these in an interview costs you the question
- Says in: body is valid in OpenAPI 3.x
- Assumes requestBody is required by default
- Adds a Content-Type header parameter beside the content map
- Thinks one operation can describe only one media type
- Relies on a GET request body being carried end to end