# Read responses and errors

## A single object

```json
{ "data": { "id": "evt_01JB...", "object": "event", "livemode": false, "created_at": "...", "updated_at": "..." } }
```

Every object has `id`, `object` (its type name), `livemode`, `created_at` and `updated_at`. Field names are `snake_case` and timestamps are ISO 8601 in UTC.

## A list

```json
{
  "data": [ ],
  "meta": { "pagination": { "limit": 20, "has_more": true, "next_cursor": "c_eyJ...", "prev_cursor": null } }
}
```

Pass `next_cursor` back as `cursor` to get the next page. See [pagination](https://docs.vabu.live/concepts/pagination.md).

## Money

Money is an object with an integer amount in minor units and an ISO 4217 currency. It is never a float.

```json
{ "amount": 150000, "currency": "KES" }
```

That is KES 1,500.00. Phone numbers are always E.164, for example `+254712345678`.

## Response headers

| Header | Meaning |
|---|---|
| `Vabu-Request-Id` | `req_...`. Quote it when you contact support. |
| `Vabu-Version` | The API version that handled the request. |
| `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` | Your [rate limit](https://docs.vabu.live/concepts/rate-limits.md) state. |
| `Retry-After` | On `429`, seconds to wait. Readable from browser code. |
| `Idempotent-Replayed` | `true` when the response is a stored replay. See [idempotency](https://docs.vabu.live/concepts/idempotency.md). |

## Errors

Every error response, including from middleware, has this shape.

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "ticket_type_sold_out",
    "message": "VIP is sold out.",
    "param": "items[0].ticket_type",
    "details": { "items.0.quantity": ["Only 0 left."] },
    "request_id": "req_01JB...",
    "doc_url": "https://docs.vabu.live/errors.html#ticket_type_sold_out"
  }
}
```

Handle errors in this order:

1. Branch on `error.code`. Codes are stable. Messages are for people and can change.
2. Use `error.type` for a fallback. `rate_limit_error` and `api_error` are worth retrying. The rest need a fix to the request.
3. Show `error.details` next to the matching form field. `error.param` names the field.
4. Log `error.request_id`.

Read [errors](https://docs.vabu.live/concepts/errors.md) for the retry rules, and the [error codes](https://docs.vabu.live/errors.md) page for the list.
