> For the complete documentation index, see [llms.txt](https://docs.usepylon.com/pylon-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.usepylon.com/pylon-docs/developer/api/errors.md).

# Errors

Handling errors from Pylon's API

Pylon's API returns errors with [HTTP status codes](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) alongside a shared response body:

```json
{
  "errors": ["All To recipients are suppressed. Remove the suppressions to send to these recipients."],
  "request_id": "1867f3d2-c360-4fe3-b17b-1e94cd955227",
  "code": "recipients_suppressed"
}
```

The `request_id` is a reference to that specific API request. If you need help, reach out to Pylon support with the `request_id` of your call.

## What is safe to depend on

**`code` is stable. Branch on it.** Once published, the condition that raises a code will not change, and new codes are only ever added — never renamed or repurposed.

**`errors` is not stable. Do not match on it.** The messages are human-readable and we reword them freely. Some are translated into the caller's locale, so the same failure can return different text on different requests. If your integration matches error strings today, `code` is the replacement.

**`code` is absent, not empty, when a failure has no code yet.** Check for presence (`if (body.code)`). Many failures do not have one; fall back to the HTTP status and message. Codes are added over time, so a response gaining a `code` is never a breaking change.

**`errors` always contains exactly one message.** Reading `errors[0]` is safe.

## Fields

| Field        | Description                                                      |
| ------------ | ---------------------------------------------------------------- |
| `errors`     | Array containing exactly one human-readable message. Not stable. |
| `request_id` | Unique request identifier. Include it in support requests.       |
| `code`       | Stable machine-readable identifier. Absent when unassigned.      |
| `exists_id`  | On `duplicate_object`, the ID of the existing object.            |

## Error codes

### Authentication — 401

| Code                           | Meaning                                                                  |
| ------------------------------ | ------------------------------------------------------------------------ |
| `invalid_authorization_header` | The `Authorization` header is missing or does not use the Bearer scheme. |
| `invalid_api_token`            | The API token was rejected. Covers every reason a token is not accepted. |
| `invalid_oauth_token`          | The OAuth token was rejected.                                            |
| `wrong_region_token`           | The token belongs to another region; use that region's API URL.          |
| `organization_deactivated`     | The organization has been deactivated.                                   |
| `organization_suspended`       | The organization's subscription is suspended.                            |

### Authorization — 403

| Code                  | Meaning                                                                |
| --------------------- | ---------------------------------------------------------------------- |
| `permission_denied`   | The authenticated caller lacks the permissions this endpoint requires. |
| `oauth_not_permitted` | This endpoint cannot be called with an OAuth token; use an API token.  |

### Request

| Code                 | Status | Meaning                                                       |
| -------------------- | ------ | ------------------------------------------------------------- |
| `duplicate_object`   | 400    | The object already exists; its ID is returned in `exists_id`. |
| `not_found`          | 404    | The request path does not correspond to an API endpoint.      |
| `method_not_allowed` | 405    | The endpoint does not support this HTTP method.               |

### Messaging — 400

| Code                               | Meaning                                                                                                                              |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `recipients_suppressed`            | Every To recipient of the outbound email is on the organization's suppression list. Clear it with `DELETE /email-suppressions/{id}`. |
| `email_bounced`                    | The email provider rejected a recipient as inactive — a hard bounce, a spam complaint, or a manual suppression at the provider.      |
| `internal_issue_reply_not_allowed` | A customer-facing reply was attempted on an internal issue. Post an internal note instead.                                           |

### Rate limiting and server errors

| Code             | Status | Meaning                                                                                              |
| ---------------- | ------ | ---------------------------------------------------------------------------------------------------- |
| `rate_limited`   | 429    | The applicable rate limit was exceeded. See [Rate limits](/pylon-docs/developer/api/rate-limits.md). |
| `internal_error` | 500    | An unexpected error occurred. Retry, or contact support with the `request_id`.                       |

### Inbound webhooks

These codes are returned only by the inbound webhook endpoint, `POST /inbound-webhooks/{id}`.

| Code                          | Status | Meaning                                                           |
| ----------------------------- | ------ | ----------------------------------------------------------------- |
| `invalid_request_body`        | 400    | The request body could not be read, or is not valid JSON.         |
| `invalid_webhook_credentials` | 401    | The webhook ID or its bearer token was rejected.                  |
| `organization_inactive`       | 401    | The organization is deactivated or its subscription is suspended. |
| `payload_too_large`           | 413    | The request body is larger than 1 MB.                             |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.usepylon.com/pylon-docs/developer/api/errors.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
