# Request & Response Envelope


Every response uses a consistent JSON envelope. Learn it once and you can
read any endpoint.

## The envelope

```json
{
  "status": "success",
  "code": 200,
  "message": "Human-readable summary.",
  "data": [ ... ]
}
```

| Field | Type | Meaning |
| --- | --- | --- |
| `status` | string | `"success"` or `"error"`. |
| `code` | integer | Mirrors the HTTP status code of the response. |
| `message` | string | Human-readable summary. Safe to log; not for branching logic. |
| `data` | array / object | The payload. Reads return the resource(s); some responses return `[]`. |

{{< callout type="info" >}}
Branch your code on `status` and the HTTP status code - not on `message`.
Messages are wording that can change; `status` and `code` are stable.
{{< /callout >}}

## Success - single resource read

```json
{
  "status": "success",
  "code": 200,
  "message": "...",
  "data": [
    { "id": 123, "name": "..." }
  ]
}
```

## Paginated responses

Reads come in two shapes under `data`:

- **Flat reads** return a bare array directly under `data` - the single-resource
  reads and most reference catalogs.
- **List and large-catalog reads** wrap the array in a pagination object: `data`
  carries an `items` array plus a `pagination` block with `current_page`,
  `per_page`, `total` and `last_page`.

```json
{
  "status": "success",
  "code": 200,
  "message": "...",
  "data": {
    "items": [ { "id": 88, "name": "..." } ],
    "pagination": { "current_page": 1, "per_page": 25, "total": 137, "last_page": 6 }
  }
}
```

Paginated reads accept `page`, `per_page` and `search` query parameters. The
`per_page` default and cap depend on the surface:

| Surface | Default `per_page` | Cap |
| --- | --- | --- |
| Resource lists (audiences, activations, cohorts, projects, schedules) | 25 | 100 |
| Reference reads (Common, Web, CTV) | 500 | 500 |
| Apps reference reads | 250 | uncapped |

Each endpoint's page documents its exact paging. See
[Limits & Quotas](/concepts/limits) for the full table.

## Error envelope

Errors keep the same top-level shape with `status: "error"` and an `errors`
object describing what went wrong:

```json
{
  "status": "error",
  "code": 422,
  "message": "Validation error.",
  "data": [],
  "errors": {
    "field_name": [
      "The field_name field is required.",
      "The field_name field is required to be string type."
    ]
  }
}
```

See [Errors](/concepts/errors) for each status code.
