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

# Errors

> One body shape on every status, and a machine-readable code to branch on.

Every failure, whatever the status, comes back in the same envelope. You write the error handler
once.

```json theme={null}
{
  "error": {
    "code": "redirect_not_found",
    "message": "Redirect not found.",
    "request_id": "req_4f3c1..."
  }
}
```

## **Just focus on `code`**

`code` field doesn't change within the same API version and was made for you to make sure what caused this error.

While `message` is just a human readable string. We made it just for easier logging of possible errors in your integration. **The text may be changed in the future.**

`request_id` is the same value as the `X-Request-Id` header. Log it on failures and quote it in
support tickets — it is how we find your exact request. See [Resource IDs](/api-v1/api-v1/resource-ids#request-ids).

## Validation failures

`invalid_request` adds a `details` array with one entry per violation, so you can point a user at
the field that needs fixing instead of at the request as a whole. `field` is a path, nested with
dots, for example `items.0.slug` at bulk operations.

```json theme={null}
{
  "error": {
    "code": "invalid_request",
    "message": "Request validation failed.",
    "request_id": "req_4f3c1e8ab29d4d7fa1c6e05b7d9a2f31",
    "details": [
      { "field": "name", "code": "max_length", "message": "name must be shorter than 100 characters" },
      { "field": "target_url", "code": "invalid_url", "message": "target_url must be a valid http(s) URL" }
    ]
  }
}
```

Codes inside `details` are their own set and never overlap with the catalogue below.

| `code`                      | When                                 |
| --------------------------- | ------------------------------------ |
| `required`                  | A required field is missing or empty |
| `invalid_type`              | Wrong type                           |
| `min_length` / `max_length` | String length out of range           |
| `min_value` / `max_value`   | Number out of range                  |
| `min_items` / `max_items`   | Array size out of range              |
| `duplicate_items`           | Repeated values in an array          |
| `invalid_url`               | Not an http(s) address               |
| `invalid_format`            | Did not match a mask: slug, hostname |
| `invalid_date`              | Not ISO 8601                         |
| `invalid_value`             | Value outside the allowed set        |
| `unknown_field`             | Field is not part of the contract    |

<Note>
  Fields with unknown/incorrect names also count as a validation error.
</Note>

## Catalogue

| HTTP | `code`                                     | When                                                              |
| ---- | ------------------------------------------ | ----------------------------------------------------------------- |
| 400  | `invalid_request`                          | Invalid body, parameters or public id                             |
| 400  | `domain_not_found`                         | `domain` is not one of yours or the system domain                 |
| 400  | `domain_not_active`                        | Domain exists but verification is not complete                    |
| 400  | `slug_required_for_system_domain`          | A slug is required on the system domain                           |
| 401  | `invalid_api_key`                          | Key missing, unknown or revoked                                   |
| 403  | `account_suspended`                        | The account owning the key is suspended                           |
| 403  | `api_access_not_available_on_current_plan` | Your plan does not include the API                                |
| 403  | `feature_not_available_on_current_plan`    | Your plan does not include this feature                           |
| 403  | `plan_limit_reached`                       | Entity limit of your plan reached                                 |
| 403  | `analytics_range_exceeds_plan_limit`       | Requested period is deeper than your plan allows                  |
| 404  | `redirect_not_found`                       | Redirect not found, or not yours                                  |
| 404  | `landing_not_found`                        | Landing page not found, or not yours                              |
| 404  | `group_not_found`                          | Group not found, or not yours                                     |
| 404  | `domain_not_found`                         | Domain from the path not found, or not yours                      |
| 409  | `slug_already_taken`                       | The address is taken                                              |
| 409  | `hostname_already_taken`                   | The hostname is connected to another account                      |
| 409  | `hostname_is_system_domain`                | The hostname belongs to the platform                              |
| 409  | `analytics_not_configured`                 | This link has no analytics attached, and never will               |
| 413  | `payload_too_large`                        | Request body exceeds 100 KB                                       |
| 415  | `unsupported_media_type`                   | `Content-Type` must be `application/json`                         |
| 429  | `rate_limit_exceeded`                      | Per-minute limit, or too many rejected requests from your address |
| 429  | `daily_quota_exceeded`                     | Daily quota exhausted                                             |
| 500  | `internal_error`                           | Everything else                                                   |
| 503  | `domain_provider_unavailable`              | The domain provider did not respond                               |
| 503  | `analytics_temporarily_unavailable`        | The analytics store did not respond                               |

Two more codes appear only inside bulk responses: `duplicate_id_in_batch` and
`duplicate_slug_in_batch`. See [Bulk operations](/api-v1/api-v1/bulk-operations#per-element-errors).

<Note>
  New codes can appear for new scenarios without a new major version, so give your handler a
  fallback branch that keys off the HTTP status class. See
  [Forward compatibility](/api-v1/api-v1/forward-compatibility#enumerated-values-grow).
</Note>
