Back to blog
APIs3 min readVektosys

JSON API Tutorial: Designing Clean Request and Response Bodies

Practical patterns for JSON APIs including envelopes, errors, pagination, versioning, and examples you can adapt.

What “JSON API” means here

This tutorial focuses on HTTP APIs that exchange JSON—not exclusively the formal JSON:API specification (though some ideas overlap). You will design predictable request bodies, response shapes, and error objects that clients can rely on.

Start with resources, not RPC soup

Model nouns your product already uses: users, projects, invoices. Prefer:

GET /projects/42

over overloaded endpoints that hide meaning in the body alone. Use JSON bodies for create/update payloads:

{
  "name": "Northwind Launch",
  "status": "planned"
}

Keep verbs in HTTP methods: POST to create, PATCH for partial updates, PUT when replacing a resource makes sense for your domain.

Response consistency

Pick a convention and apply it everywhere. Two common styles:

Direct resource

{
  "id": 42,
  "name": "Northwind Launch",
  "status": "planned"
}

Envelope

{
  "data": {
    "id": 42,
    "name": "Northwind Launch",
    "status": "planned"
  },
  "meta": { "requestId": "req_9f3" }
}

Envelopes help when you always need meta or pagination fields. Direct resources feel lighter. Either works—mixing them freely does not.

Errors clients can parse

Avoid returning HTML error pages to API clients. Prefer structured JSON:

{
  "error": {
    "code": "validation_failed",
    "message": "name is required",
    "details": [
      { "field": "name", "issue": "required" }
    ]
  }
}

Use appropriate status codes (400, 401, 404, 409, 422, 500) and keep code stable for programmatic handling.

Pagination pattern

{
  "data": [ ... ],
  "pagination": {
    "nextCursor": "eyJpZCI6MTAwfQ",
    "limit": 25
  }
}

Cursor pagination scales better than naive offset for large datasets. Include links if your clients prefer HATEOAS-style navigation.

Versioning without chaos

Options include URL prefixes (/v1/), headers, or media types. URL versioning is the most obvious for public APIs. Do not silently break JSON field meanings inside an existing version—add fields, deprecate carefully, remove only in a new version.

Content negotiation basics

Send Content-Type: application/json on bodies. Ask clients to send Accept: application/json. Reject ambiguous payloads early rather than guessing.

While integrating, keep a formatter/validator nearby. JSON Editor is handy for shaping example requests and verifying fixtures before you wire them into Postman or automated tests.

Testing checklist

  • Happy-path create/read/update/delete
  • Validation errors return stable JSON
  • Auth failures do not leak internal traces
  • Pagination empty states return arrays, not null
  • Unknown fields policy is documented (ignore vs reject)

Ship a small vertical slice

Implement one resource end-to-end with docs and examples. Expand patterns only after the first slice feels boringly consistent. Clean JSON APIs are less about clever tricks and more about repeating simple shapes until clients trust you.

Related articles