paulund

6. Response Shape

6. Response Shape

Wrapping every response in a consistent envelope gives you a stable contract with your clients. It also buys you room to add metadata — pagination links, request IDs, warnings — without changing the shape of the actual data.

Success Envelope

Wrap collection and single-resource responses in a data key. Attach pagination metadata and navigation links at the top level:

{
    "data": [
        { "id": 1, "name": "Widget A" },
        { "id": 2, "name": "Widget B" }
    ],
    "meta": {
        "total": 120,
        "per_page": 20,
        "current_page": 2,
        "last_page": 6
    },
    "links": {
        "self": "/products?page=2",
        "next": "/products?page=3",
        "prev": "/products?page=1"
    }
}

For a single resource, data contains the object directly rather than an array:

{
    "data": {
        "id": 42,
        "name": "Widget A",
        "price": 19.99
    }
}

Error Envelope

Errors follow the same top-level structure so that clients can handle them uniformly regardless of the error type:

{
    "error": {
        "code": 404,
        "message": "The requested product was not found."
    }
}

For validation errors, include a details object that maps each invalid field to an array of error messages (see topic 13 for the full convention).

Why an Envelope?

Without an envelope, a collection endpoint returns a bare JSON array. This creates two problems:

  1. You cannot add metadata later without breaking the response contract (an array cannot suddenly become an object).
  2. Top-level JSON arrays are a minor security concern in older browsers due to historical JSON hijacking vulnerabilities.

An envelope solves both problems from day one and makes your API far easier to extend over time.