OpenAPI
Requests

Request Body Object in OpenAPI

The request body describes the data a client sends to an API in the body of an HTTP request.

FieldTypeRequiredDescription
descriptionStringA description of the request body. May contain CommonMark syntax (opens in a new tab) to provide a rich description.
contentContentA map of Media Type Objects that defines the possible media types that can be used for the request body.
requiredBooleanWhether the request body is required. Defaults to false.
x-*ExtensionsAny number of extension fields can be added to the Request Body Object that can be used by tooling and vendors.

Supporting Multiple Content Types

Modern APIs often need to accept different format options for the same endpoint to accommodate various client needs.

Why Support Multiple Content Types?

  • Client flexibility: Some clients may prefer JSON, others form data.
  • Ecosystem integration: To support legacy systems requiring XML.
  • Special use cases: To handle file uploads with multipart/form-data.

Here’s how to define multiple content types in an OpenAPI document:

paths:
/users:
post:
summary: Create a new user
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/UserForm'
application/xml:
schema:
$ref: '#/components/schemas/UserXML'

Common Content Type Scenarios

JSON and Form Data

Combining JSON and form data allows you to support both programmatic clients and web forms:

content:
application/json:
schema:
$ref: '#/components/schemas/OrderRequest'
application/x-www-form-urlencoded:
schema:
type: object
properties:
productId:
type: string
quantity:
type: integer

API Versioning Using Content Types

To version an API using media types:

content:
application/vnd.company.v1+json:
schema:
$ref: '#/components/schemas/UserV1'
application/vnd.company.v2+json:
schema:
$ref: '#/components/schemas/UserV2'

File Uploads With multipart/form-data

File uploads require special handling in your API documentation.

Single File Upload

To upload a single file, define a multipart/form-data request body:

requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
description: The file to upload
description:
type: string
description: Description of the file
required:
- file

Uploading Multiple Files

To upload multiple files simultaneously, define an array of files:

requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
files:
type: array
items:
type: string
format: binary
description: Multiple files to upload
required:
- files

Tips for File Uploads:

  1. Define allowed file types using the encoding object:
encoding:
file:
contentType: application/pdf, image/jpeg, image/png
headers:
Content-Disposition: {...}
  1. Document file size limits in your description:
description: 'Maximum file size: 5MB'
  1. Include validation requirements that clients should be aware of.
  2. Specify how to handle file metadata, like filenames and types.

Organizing Complex Request Bodies

As an API grows, request bodies can become complex. To keep them organized and maintainable, consider the following strategies.

Use Component References

Break down complex objects into reusable components:

components:
schemas:
CreateOrderRequest:
type: object
properties:
customer:
$ref: '#/components/schemas/CustomerInfo'
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
shippingAddress:
$ref: '#/components/schemas/Address'
billingAddress:
$ref: '#/components/schemas/Address'

Group Related Properties

Organize properties into logical groups to make the request structure easier to understand:

ShippingRequest:
type: object
properties:
# Group 1: Shipment details
shipment:
type: object
properties:
items: {...}
packaging: {...}
# Group 2: Destination
destination:
type: object
properties:
address: {...}
instructions: {...}

To Wrap or Not To Wrap: Should I Wrap Request Data in a Data Object?

Whether to wrap request data in a container object is a common API design question that impacts how data is structured.

Wrapped Requests

In a wrapped request, core data is nested inside a container object. This pattern allows for the easy inclusion of additional metadata (such as client identifiers or request tracking information) without affecting the primary data schema. This approach is useful when you anticipate future changes or need to maintain consistency with other response patterns.

For example:

requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
email:
type: string
format: email
name:
type: string
required:
- email
- name
metadata:
type: object
properties:
clientId:
type: string
requestId:
type: string
example:
clientId: "web-app"
requestId: "req_123456"
required:
- data
example:
data:
email: "user@example.com"
name: "John Doe"
metadata:
clientId: "web-app"
requestId: "req_123456"

Unwrapped Requests

An unwrapped request uses a flat structure with minimal nesting. This results in a more direct and less verbose interface, which can be beneficial for simple operations or high-frequency endpoints where performance is a priority.

For example:

requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
format: email
name:
type: string
required:
- email
- name
example:
email: "user@example.com"
name: "John Doe"

Choosing the Appropriate Structure

  • Wrapped requests: Use wrapped requests if you expect to add metadata later, need to support versioning, or want to maintain consistency with other API components.
  • Unwrapped requests: Use a flat structure when the request body is straightforward.

Select the approach that best aligns with your API’s complexity, future evolution, and the expectations of its consumers.

Schema Versioning

As an API evolves, it’s important to version request schemas without breaking existing clients. Two common approaches to versioning request schemas are content type versioning and using the discriminator pattern.

Content Type Versioning

This approach defines schema versions using different media types in the content object:

requestBody:
content:
application/vnd.api.v1+json:
schema:
$ref: '#/components/schemas/UserRequestV1'
application/vnd.api.v2+json:
schema:
$ref: '#/components/schemas/UserRequestV2'

Using Schema Discriminator

The discriminator pattern (opens in a new tab) allows a single endpoint to describe multiple schema versions by using a property to specify the version:

requestBody:
content:
application/json:
schema:
type: object
required: ["version"]
discriminator:
propertyName: version
mapping:
"1": '#/components/schemas/UserV1'
"2": '#/components/schemas/UserV2'
oneOf:
- $ref: '#/components/schemas/UserV1'
- $ref: '#/components/schemas/UserV2'

Encoding Object for Form Data and Multipart Requests

The Encoding Object provides additional information for multipart and application/x-www-form-urlencoded requests, defining how complex properties should be serialized.

paths:
/drinks:
post:
requestbody:
content:
multipart/form-data:
schema:
properties:
# ... other properties ...
photo:
description: A photo of the drink.
type: string
format: binary
encoding:
photo:
contentType: image/jpeg, image/png
headers:
Content-Disposition:
description: Specifies the disposition of the file (attachment and file name).
schema:
type: string
default: 'form-data; name="photo"; filename="default.jpg"'
allowReserved: false
# style: form - not applicable to strings
# explode: false - not applicable to strings
FieldTypeRequiredDescription
contentTypeStringThe field’s content type. If the field is an object, the default is application/json. If the field is an array, the default is based on the inner type. Otherwise, the default is application/octet-stream. Valid values are either a media type (for example, application/json), a wildcard media type (for example, image/*), or a comma-separated list of media types and wildcard media types (for example, image/png, application/*).
headersMap[string, Header Object | Reference Object]Only applies to multipart requests. Specifies additional headers for the field, such as Content-Disposition for uploaded files. A Content-Type header in this map is ignored in favor of the encoding object’s contentType.
styleStringCan take one of the following values: form, spaceDelimited, pipeDelimited, or deepObject. Specifies the style of the field’s serialization only in requests with media type multipart/form-data or application/x-www-form-urlencoded. See the description of style under Query Parameters.
explodeBooleanOnly applies to requests with multipart/form-data or application/x-www-form-urlencoded media types and fields with array or object types. If style is form, the default is true. Otherwise, the default is false.
allowReservedBooleanOnly applies to requests with media type application/x-www-form-urlencoded. Determines whether reserved characters (those allowed in literals but with reserved meanings) are allowed in the parameter’s content. The default is false. When true, it allows reserved characters as defined by RFC 3986 (opens in a new tab) to be included without percent-encoding. This can be useful for parameters with content such as URLs.