Sending request data
Understanding how to properly structure and handle request data is crucial for building robust APIs. This guide covers best practices and common patterns for working with API request data.
URL structure
Every API request starts with a URL that identifies the resource and any query parameters:
Key components:
- Resource path: Identifies what you’re interacting with.
- Query parameters: Filter, sort, or modify the request.
- API version: Often included in the path.
HTTP request bodies
Requests can also have a “request body”, which is a payload of data being sent
the API for processing. It is very frowned upon to use a request body for the
HTTP method GET
, but expected for POST
, PUT
, PATCH
, and `QUERY.
The request body can be in a variety of formats, but the most common are JSON, XML, and form data.
This POST
request to the /places
endpoint is trying to add a new place to
the API, once again using a JSON body. The Content-Type
header lets the server
know to expect JSON data, so it can parse the body and create a new place with
the name “High Wood” and the coordinates 50.464569783, -4.486597585
.
So far the examples of HTTP requests and responses have been using text, but in reality they are just a series of bytes. The text is just a human-readable representation of the bytes, and the tools that interact with the API will convert the text to bytes before sending it, and convert the bytes back to text when receiving it.
Most of you will interact with APIs using a programming language, and the code to send a request will look something like this:
HTTP tooling is essentially the same thing no matter the language. It’s all about URLs, methods, body, and headers. This makes REST API design a lot easier, as you have a “uniform interface” to work with, whether everything is following all these set conventions already.
Requests like POST
, PUT
, and PATCH
typically include data in their body.
An example of a PATCH request following the RFC 7386: JSON Merge
Patch
This request body is yours to do with as you want. There’s a lot of freedom in how you structure your data, but there are some best practices to follow which you can learn more about in the [API Collections & Resources](/api-design api-collections) guide.
Data formats
This is generally where all of the domain-specific modelling will happen for data and workflows the API is meant to handle, but generally its not just spitting raw data around. The understand more about structuring request bodies, its important to understand data formats.
File uploads
Instead of sending JSON data, files can be sent in the request body.
Learn more about file uploads in the File Uploads guide.
Best Practices
1. Keep request & response data consistent
Maintain the same structure for data going in and out of your API. You want to
strive for predictability and consistency in your API design. When a user sends
a POST
request to create a new resource, they should get back a response that
looks like the resource they just created. If a user updates a resource, the
response should return the new state of the updated resource.
More on this in the API Responses guide.
2. Do not use request bodies for DELETE requests
Some API designers use a request body for a DELETE request to capture more information about the deletion of a resource.
Doing so is recommended against in both RFC9110: HTTP
Semantics
Instead it would be more appropriate to create a new resource called POST /drinks/1/cancellation
and essentially create a DrinkCancellation resource.
This resource can then be used to track the reason for the cancellation, and any
other information that might be useful, as well as avoiding the need for a
request body on the DELETE request.
3. Use the correct content type
The Content-Type
header is used to indicate the media type of the resource
being sent in the request body. The most common content types are:
application/json
: JSON dataapplication/xml
: XML dataapplication/x-www-form-urlencoded
: Form datamultipart/form-data
: File uploads
Make sure to remind the user to set the Content-Type
header in their request
to the correct value, and if they send the wrong thing then return a 415 Unsupported Media Type
response.
4. Avoid optional request bodies
When designing your API, avoid making request bodies optional. It’s a little confusing, and harder for the user to understand what they need to send, harder to document, harder to validate, harder to generate code for, and harder to test.
For example, if you have a POST /loans/{id}/renewal
endpoint with an optional renewal date, instead of making the whole request body optional make it required and make the renewal date property optional.
This way, the user always knows what to expect in the request body, and you can validate the request body more easily. If the user doesn’t send a renewal date, you can just use the current date as the default value. This is a lot easier to understand and work with than having to check if the request body is present or not, and then check if the renewal date is present or not.
Last updated on