Learning to document an API response is one of the best ways to understand how an API actually behaves. Instead of copying a response and moving on, you will turn each request into a clear reference that explains the data, rules, errors, and assumptions behind it.
What API response documentation should explain
A useful response document answers more than “what JSON came back?” It should help another person—or your future self—understand how to make the request, interpret the result, and handle situations where the result changes.
For each endpoint, document these areas:
- The HTTP method and URL path
- Required authentication and permissions
- Query parameters, path parameters, and request body fields
- The expected status code
- Response headers that matter to the client
- The response body structure
- The meaning and type of each important field
- Optional, missing, null, or empty values
- Pagination, sorting, filtering, and ordering rules
- Common error responses
- A complete example request and response
While learning, you do not need to produce a large formal specification immediately. Start with a small, accurate record. Expand it as you discover more behavior.
A good response description is precise without pretending that you know more than you have verified. If you do not know whether a field is always present, write “observed in this example” until you confirm it with additional requests.
Start with one real request
Choose one endpoint that is simple enough to investigate. A list endpoint such as GET /users, a detail endpoint such as GET /users/{id}, or a public weather endpoint is usually easier than an endpoint involving uploads, webhooks, or complex authentication.
Record the request exactly as you sent it. Include the full method, URL, parameters, and relevant headers, but remove secrets before saving or sharing it.
For example:
GET https://api.example.com/v1/books?limit=2&sort=title HTTP/1.1
Accept: application/json
Authorization: Bearer REDACTED_TOKEN
Then save the raw response before rewriting it:
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-ID: 8f31c2
{
"items": [
{
"id": "bk_104",
"title": "Practical APIs",
"available": true
}
],
"next_cursor": "eyJwYWdlIjoyfQ=="
}
Keeping the raw response is important because it prevents your explanation from quietly changing the evidence. You can format or annotate a copy, but retain the original status, headers, and body somewhere safe.
Describe the endpoint before the response
Readers need context before they can interpret a JSON object. Begin each endpoint entry with a compact summary:
- Purpose: What the endpoint does
- Method:
GET,POST,PUT,PATCH, orDELETE - Path: The endpoint path without environment-specific secrets
- Authentication: Whether a token, API key, or session is required
- Inputs: Parameters or request fields
- Successful result: What the response represents
For the example above, you might write:
GET /v1/booksreturns a list of books visible to the authenticated user. Thelimitparameter controls the maximum number of items returned, andsort=titlerequests alphabetical ordering. A successful response returns an object containing anitemsarray and a cursor for retrieving another page.
Avoid vague descriptions such as “gets books.” Explain what the client receives and why it might call the endpoint.
If the endpoint is environment-dependent, document the stable path separately from the host. For example, use https://api.example.com/v1/books as a sample rather than exposing an internal development URL or a personal account identifier.
Build a response field table
A field table is one of the fastest ways to turn a confusing response into useful documentation. Keep it compact and focus on fields a client needs to understand.
| Field | Type | Required? | Meaning | Example |
|---|---|---|---|---|
items | array | Yes | Books returned on this page | [{...}] |
items[].id | string | Yes | Stable identifier for a book | "bk_104" |
items[].title | string | Yes | Display title | "Practical APIs" |
items[].available | boolean | Yes | Whether the book can currently be borrowed | true |
next_cursor | string or null | No | Cursor for the next page | "eyJ..." |
The “required” column needs careful wording. A field may be required in the schema but absent in a particular situation, or present with a null value. Distinguish these cases:
- Required: The field should appear in every valid response.
- Optional: The field may be omitted entirely.
- Nullable: The field appears, but its value may be
null. - Conditionally present: The field appears only for certain records, permissions, or query options.
Do not infer a field’s type from one convenient value. An identifier that looks numeric might actually be a string because it can contain letters or leading zeroes. Check the API’s schema if one exists, and compare several responses when possible.
Explain nesting and relationships
Nested JSON is easier to learn when you describe it from the outside in. Start with the top-level type, then identify the important child structures.
For example:
{
"items": [
{
"id": "bk_104",
"author": {
"id": "au_22",
"name": "R. Patel"
}
}
],
"next_cursor": null
}
Document it in a way that connects the structure to application behavior:
- The top-level value is an object.
itemsis an array of book objects.- Each book has an
authorobject rather than only an author name. author.idcan be used to connect the author to another endpoint.next_cursorisnullwhen there is no additional page.
When an array is empty, explain what that means. It might mean that no records match the filter, the account has no data, or the server returned an incomplete result. Those possibilities are not interchangeable.
Also document units and formatting. A field named created_at could use UTC ISO 8601 timestamps, while price could be an integer number of cents rather than a decimal currency value. State the convention explicitly when you can verify it.
Include status codes and headers
The body is only one part of an API response. Status codes tell the client whether the operation succeeded and often determine which branch of application logic should run.
Create a short status-code section for each endpoint. For example:
200 OK The request succeeded and returns the requested books.
400 Bad Request A parameter is invalid or cannot be parsed.
401 Unauthorized Authentication is missing or invalid.
403 Forbidden The identity is recognized but lacks permission.
404 Not Found The requested resource does not exist.
429 Too Many Requests The rate limit has been exceeded.
500 Server Error The server failed while processing the request.
Do not list every theoretically possible code unless you have a reliable source. Prioritize codes documented by the API or observed during legitimate testing.
Headers can carry information that is easy to miss. Document headers when they affect client behavior, such as:
Content-Type, which identifies the body formatLocation, often used after creating a resourceETagorLast-Modified, used for caching- Rate-limit headers showing remaining quota or reset time
- Request or correlation IDs used for support and debugging
- Pagination links or continuation tokens
Never copy authorization tokens, cookies, private request IDs, or personal data into public documentation. Replace them with clearly marked values such as REDACTED_TOKEN.
Document errors as carefully as success
Beginners often write one successful response and call the endpoint documented. That creates a misleading reference. Clients also need to know what failure looks like.
Capture representative errors without deliberately harming a production system. Safe learning examples include using an invalid format in a local environment, omitting a required parameter where permitted, or requesting a known nonexistent test resource.
An error response might look like this:
{
"error": {
"code": "invalid_parameter",
"message": "limit must be between 1 and 100",
"field": "limit",
"request_id": "req_7d91"
}
}
Explain each part and describe the recommended client action:
codeis a stable machine-readable category.messageis useful for debugging but may not be suitable for a user interface.fieldidentifies the input that needs correction.request_idhelps support teams trace the failed request.
Mention whether errors share one format or vary by status code. If the API returns HTML, plain text, or an empty body for some failures, document that limitation so clients do not blindly parse every response as JSON.
Use a learning notebook and update it incrementally
A simple notebook, Markdown file, or repository documentation page is enough. Organize it so that each endpoint has the same shape:
## List books
### Purpose
### Request
### Parameters
### Successful response
### Response fields
### Errors
### Notes and open questions
The “open questions” section is especially valuable while learning. Write down uncertainties such as:
- Does
limithave a default value? - Is ordering stable between requests?
- What happens when a cursor expires?
- Is
nulldifferent from an omitted field? - Does the endpoint return records the current user cannot edit?
Turn each question into a small investigation. Change one input at a time, compare the result, and record what changed. This makes your notes easier to trust and teaches you how the API’s rules interact.
Use version control if possible. Small commits such as “Document pagination cursor” or “Add 401 response example” show how your understanding developed and make incorrect notes easy to revise.
Validate the documentation against the API
Before publishing, compare the written example with a fresh request. Check that:
- The method and path are correct.
- Required headers are included.
- Secrets and private data are removed.
- The example JSON is valid.
- Field names match the actual response exactly, including capitalization.
- Types are described correctly.
- Status codes and error behavior are not overstated.
- Pagination instructions work from the reader’s perspective.
If the API provides an OpenAPI document, use it as a reference, but do not assume it is perfect. Generated schemas can be outdated, incomplete, or too general. Your documentation should identify differences between the published contract and observed behavior instead of silently choosing one.
A useful compromise is to label evidence:
- Contract: stated in the official schema or reference
- Observed: confirmed from an example response
- Inference: a reasonable interpretation that still needs confirmation
This habit prevents a common learning mistake: converting an assumption into a rule after seeing only one response.
Common problems and practical fixes
The response is too large
Save the full raw response separately, then show a shortened example with only representative fields. Mark the omission clearly. Do not remove fields without saying that the example is abbreviated.
Values change on every request
Use stable test data where available. Explain which values are dynamic, such as timestamps, random IDs, balances, or availability counts. Readers should not think that a changing value indicates a broken example.
The API returns different shapes
Document the condition that causes each shape, such as a filter, permission level, API version, or empty result. Show both variants when the difference changes client code.
You cannot tell whether a field is required
Check the schema, official examples, and multiple legitimate responses. Until confirmed, describe the field as “observed” rather than promising that it always exists.
Authentication prevents sharing examples
Replace credentials and private values with placeholders, but preserve the structure. If the response contains sensitive customer data, create a synthetic example instead of redacting so much that the result becomes unreadable.
The example works once but not later
Record expiration rules, pagination cursor lifetime, rate limits, and environment assumptions. A cursor or signed URL may be temporary by design.
Know the limits of your documentation
An API response document is not automatically a complete API contract. It may not cover concurrency, retries, webhook timing, eventual consistency, permission differences, undocumented legacy behavior, or future version changes.
State the scope of your notes. For example, say that the example was collected from a test account, a particular API version, or a specific locale. Avoid claiming that behavior is universal when you investigated only one account or dataset.
The goal while learning is not to produce flawless documentation in one sitting. The goal is to create a reliable explanation that improves as your questions become more specific. Start with one real request, preserve the raw evidence, describe the response structure, test meaningful variations, and clearly separate verified facts from assumptions. That workflow builds both better documentation and a much stronger understanding of the API itself.