> ## Documentation Index
> Fetch the complete documentation index at: https://docs.endl.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and the response envelope

> One response shape, and the status codes the webhooks API returns

## The envelope

Every response — success or error — shares one shape.

```json theme={null}
{
  "code": 200,
  "message": "Success",
  "status": "SUCCESS",
  "data": { },
  "errors": [ ]
}
```

<ResponseField name="code" type="integer">
  The HTTP status code, repeated in the body.
</ResponseField>

<ResponseField name="message" type="string">
  A human-readable summary of the outcome.
</ResponseField>

<ResponseField name="status" type="enum">
  Either `SUCCESS` or `ERROR`.
</ResponseField>

<ResponseField name="data" type="object | null">
  The payload. `null` on error.
</ResponseField>

<ResponseField name="errors" type="array">
  A list of `{code, message, field}` objects. Empty on success. Body-validation failures return one entry per offending field.
</ResponseField>

## Status codes

| HTTP  | `code`                        | When                                                                                                               |
| ----- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `400` | `VALIDATION_ERROR`            | Missing permission, `limit` below `1`, a retry rate limit, or per-field body validation.                           |
| `400` | `INVALID_CURSOR`              | The `after` cursor is malformed, forged, or from another feed or partner.                                          |
| `400` | `INVALID_PARAMETER`           | A path or query value will not convert — a non-UUID id, an unknown status.                                         |
| `400` | `MALFORMED_REQUEST`           | The JSON body could not be parsed.                                                                                 |
| `401` | `UNAUTHORIZED`                | Missing or invalid API credentials.                                                                                |
| `404` | `NOT_FOUND`                   | No such resource, it belongs to another partner, or there is no active PULL subscription.                          |
| `405` | `METHOD_NOT_ALLOWED`          | Wrong verb on a valid path.                                                                                        |
| `409` | `CONFLICT`                    | A duplicate, or an operation invalid for the current state — retrying an already-delivered delivery, for instance. |
| `422` | `DELIVERY_MODE_NOT_AVAILABLE` | A delivery mode that is not available yet, `SQS` or `SSE`.                                                         |
| `500` | `INTERNAL_ERROR`              | Unexpected server error.                                                                                           |
| `503` | `DIRECTORY_UNAVAILABLE`       | Credentials could not be verified right now. Retry with backoff.                                                   |

<Note>
  **There is no `429`.** This API never returns `429` to partners. Rate limits surface as `400 VALIDATION_ERROR` instead, so do not build your retry logic around a `429`.
</Note>

<Warning>
  A missing permission is a `400`, not a `403`. If a call fails validation for no apparent reason, check the permissions on the key before you check the body.
</Warning>
