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

> ## Agent Instructions
> Base URL: https://api.eventory.ai. Send your API key in the apikey header. Market Data and Live Availability calls cost credits, pings included; GET /usage is free, so use it to test a key. Costs per endpoint: https://eventory.ai/docs/credits-and-access.md

# API error codes

> Every error code the API can return, what it actually means, and what to do.

Errors come from two places. The **gateway** decides authentication, access, billing,
rate limiting and routing, and answers with one envelope. If the request gets past
the gateway, the **API you called** may reject it in its own format. Key on the
status code and the machine-readable code, never on the message text, which is
prose and may be reworded.

## Gateway errors

```json theme={null}
{ "error": { "code": "limit_reached", "message": "You have reached your usage limit." } }
```

| Status | `error.code` | Meaning | What to do |
| - | - | - | - |
| `401` | `unauthenticated` | No credential was sent. | Check that the `apikey` header is present. An empty shell variable sends the request bare. |
| `401` | `invalid_credentials` | A key was sent and rejected. | The key is wrong or revoked, or was sent in `Authorization` instead of `apikey`. Not a routing problem. |
| `403` | `forbidden` | The key is valid but not granted this API. | See [Credits & access](/docs/credits-and-access.md). Contact Eventory to enable it. |
| `402` | `limit_reached` | Credits exhausted against the hard cap. | Wait for the period to reset or raise the cap. Free endpoints keep working. |
| `402` | `no_subscription` | No active or trialing subscription, or a plan without API credits (Monitors Essential). | Check `GET /usage`. Paused, cancelled or unpaid subscriptions are not served. |
| `402` | `no_billing_account` | The key has no billing account. | Contact Eventory. |
| `402` | `plan_unavailable` | Your plan could not be loaded, either briefly or because it is misconfigured. | Retry once after a short wait. If it persists, contact Eventory. |
| `402` | `payment_required` | Another billing denial. | Contact Eventory. |
| `400` | `invalid_parameter` | A quantity-billed parameter is out of range or malformed. | Today this is only `sales_limit`, which must be `1..200`. |
| `429` | `rate_limited` | More than 30 Live Availability (`/events/…`) requests this minute. Other APIs are not rate limited. | Back off. See [Rate limits](/docs/rate-limits.md). |
| `404` | `not_found` | Unknown route or malformed path. Also returned for a wrong HTTP method. | Check the path and method against the reference. |
| `500` / `502` / `503` / `504` | `service_unavailable` | The API you called failed (its status is kept), the service is unreachable (`503`), or the gateway could not reach its authentication or billing service (`502`). | Retry with backoff. The underlying error is deliberately not forwarded. |

Two patterns worth recognising immediately:

* **`401 unauthenticated` on every route** almost always means the key is missing
  from the request, not that it is wrong.
* **`502` on everything** means the gateway could not reach its authentication
  service. It fails closed by design. Retry with backoff.

## Market Data errors

```json theme={null}
{ "status": "error", "code": "EVENT_NOT_FOUND", "message": "No viagogo event with id E-1." }
```

| Status | `code` | Meaning |
| - | - | - |
| `400` | `INVALID_VIAGOGO_ID` | The path id does not match `E-<digits>`. |
| `400` | `INVALID_VIVIDSEATS_ID` | The `/vividseats` path id is not all digits. |
| `400` | `INVALID_TICKETMASTER_ID` | The `/ticketmaster` path id is not 1 to 64 letters, digits, `-` or `_`. |
| `400` | `INVALID_REQUEST` | Request validation failed: missing or wrong-type body or query fields, or an expression that is too long. |
| `400` | `INVALID_FILTER` | The search `filterExpression` is malformed. The message says where parsing failed. |
| `400` | `MISSING_URL` | `GET /artist` called with an empty `url`. Without `url` at all, the code is `INVALID_REQUEST`. |
| `404` | `EVENT_NOT_FOUND` | No tracked event matches the identifier. |
| `404` | `ARTIST_NOT_FOUND` | No artist on file with that exact URL. |

Server-side failures keep their status (`500`, `502`, `503`, `504`) but come back in
the [gateway envelope](#gateway-errors) as `service_unavailable`; the underlying error
is not forwarded. Retry with backoff, and contact Eventory if it persists.

## Live Availability errors

```json theme={null}
{ "detail": "Scrape timed out after 60s" }
```

| Status | Meaning |
| - | - |
| `400` | Unknown platform, a region the platform does not list, or an `event_id` the platform cannot take, such as a bare Eventim id. Check the values against `GET /events/platforms`. |
| `404` | Event not found on the platform. It may be sold out, expired, removed, or the id is wrong. |
| `408` | The platform took longer than 60 seconds. Retry once; if it persists the event id is probably invalid. |

An unexpected error during the scrape returns `500`, and an unreachable service `503`.
Both come back in the [gateway envelope](#gateway-errors) as `service_unavailable`,
not with `detail`.

## Watchlist errors

Validation errors carry `error`; a body that is not valid JSON is rejected earlier
and carries `detail`.

```json theme={null}
{ "error": "One or more IDs are invalid for ticketmaster. Example: 0200642CF18CAA24" }
```

> [!WARNING]
>
> The Watchlist API has **no machine-readable `code` field** — unlike Market Data and
> the gateway, the message string is all you get. The messages below are listed verbatim
> for that reason. They are still prose: match on the status code first, and treat a
> message match as a hint rather than a contract.

### `400` — validation

| Message | When |
| - | - |
| `Website is required` | `website` missing or empty on create. |
| `Event ID is required` | `event` missing or empty on create. |
| `Region is required` | `region` missing or empty on create. |
| `At least one Event ID is required` | `event` was present but blank after trimming. |
| `One or more IDs are invalid for <website>. Example: <example>` | The most common one. `event` does not match the id format for that platform and region. `<example>` is a real, valid id or URL for the platform, so the message tells you the exact shape expected. Only produced for platforms with a validated id format — see [Watchlist platforms](/docs/guides/watchlist-platforms.md). |
| `Unknown website: "<website>". Use one of the supported website values listed at https://docs.eventory.ai/guides/watchlist-platforms.` | `website` is not a known platform key. See [Watchlist platforms](/docs/guides/watchlist-platforms.md). |
| `Unknown field(s): <a>, <b>` | The body contains keys that are not part of the schema. The read-only fields returned by `GET` (`id`, `client_id`, `created_at`, `updated_at`, `deleted`, `website_id`) are accepted and ignored, so sending back an item you read does not trigger it. |
| `<field> must be a whole number greater than 0, or null to disable it` | A stock-threshold field such as `min_stock_increase_filter` was sent as `0`, negative, or a non-integer. |
| `change_type must be one of stock_increase, stock_decrease, price_decrease, price_increase, or null` | `change_type` is not one of the accepted values. |
| `"limit" must be an integer between 1 and 1000` | `GET /watchlist?limit=…` out of range or not an integer. |
| `"offset" must be an integer >= 0` | `GET /watchlist?offset=…` negative or not an integer. |
| `"action" is not a field of the watchlist API. Use POST /watchlist to create, PATCH /watchlist/{id} to update and DELETE /watchlist/{id} to delete.` | The body contains an `action` key. The HTTP method selects the operation. |
| `"id" must be a positive integer` | The `{id}` in a `GET` or `DELETE` path is `0` or negative. |
| `Watchlist monitor id is required` | The `{id}` in a `PATCH` path is `0` or negative. |

When `event` carries several comma-separated ids, the whole request is rejected if
**any** of them fails the format check, and nothing is created.

A non-integer `{id}` in the path is rejected before it reaches the Watchlist service
and comes back as a `422` with a `detail` array, not one of the messages above.

A `POST` or `PATCH` body that is not valid JSON is rejected with
`{ "detail": "request body is not valid JSON" }`; a valid JSON body that is not an
object gets `{ "detail": "request body must be a JSON object" }`.

### `403`

| Message | When |
| - | - |
| `Website "<website>" is not available on this account` | The platform is available on request and is not enabled for your account. See [Watchlist platforms](/docs/guides/watchlist-platforms.md). |
| `Event limit reached: your plan allows no more active events. Delete or deactivate (task_active: false) some watchlist items, or upgrade your plan.` | A create or update would take your account past your plan's limit of active events. |

A key without watchlist access gets the gateway's `403 forbidden` in the
[gateway envelope](#gateway-errors) on every watchlist path, `GET /watchlist/health`
included.

### `404`

| Message | When |
| - | - |
| `Watchlist monitor not found` | No item with that id belongs to your account. Also returned instead of `403` when the item belongs to someone else — ids are never confirmed to exist across accounts. |
| `Referenced resource not found` | `webhook_setting_id` or `role_id` points at a webhook or Discord role that is not yours. |

An unsupported method on a watchlist path is answered by the gateway as
`404 not_found` in the [gateway envelope](#gateway-errors), not by this API.

### `500`, `502`, `504`

Server-side failures are answered with the gateway envelope
(`{ "error": { "code": "service_unavailable", … } }`); the underlying message is
deliberately not forwarded. Retry once with backoff. If a `500` persists on a request
that should clearly succeed, report it — it is not something a client can fix.

## Account errors

| Status | `detail` | Meaning |
| - | - | - |
| `409` | `no_stripe_customer` | Your account has no billing account yet. Contact Eventory. |

Server-side failures, such as billing being unreachable or a misconfigured plan
(`502`), come back in the [gateway envelope](#gateway-errors) as `service_unavailable`.
Retry with backoff, and contact Eventory if it persists.

## Stream errors

The WebSocket returns HTTP errors before the upgrade completes. After the upgrade, the
server closes the socket with close code `1011` when its own feed of notifications
ends: reconnect with backoff. See [Connecting to the stream](/docs/stream/connecting.md#errors).

## Retry policy

| Status | Retry? |
| - | - |
| `400`, `401`, `403`, `404` | No. The same request will fail again. |
| `402` | No. Fix the billing state first. `plan_unavailable` can be temporary: retry it once. |
| `408` | Once. |
| `429` | Yes, after backing off. |
| `500`, `502`, `503`, `504` | Yes, with exponential backoff. |

Paid requests are billed when the gateway forwards them, so each one is billed once
whatever the API answers: a `4xx`, a `5xx` or a timeout included. A retry loop on a
bad request spends credits for nothing, and every retry is billed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.