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

# Errors and rate limits

> Refusals are RFC 9457 problem details with a stable code; every response counts against your rate limit and says how much is left.

<Warning>
  **Preview: nothing is served yet.** This describes the Distribution API contract (version `1.0.0`).
</Warning>

## Errors

A refused request answers with an RFC 9457 problem, `Content-Type: application/problem+json`:

```json theme={null}
{
  "type": "https://api.gridbeds.com/problems/insufficient-scope",
  "title": "…",
  "status": 403,
  "code": "insufficient_scope",
  "required_scopes": ["read:ari"],
  "instance": "urn:uuid:5f0c6f0e-6a53-4a8e-9f57-3c1f0f0b8b1d",
  "request_id": "5f0c6f0e-6a53-4a8e-9f57-3c1f0f0b8b1d"
}
```

| Field | |
| - | - |
| `type` | A URL naming the problem, `https://api.gridbeds.com/problems/<slug>`, which resolves to a page describing it. |
| `code` | A stable identifier of the refusal. Branch on `code` or `type`. |
| `title` | For a person, in the language of `Accept-Language`. **Never branch on it.** |
| `status` | The HTTP status. |
| `detail` | When present, more about this occurrence. |
| `request_id` | The same as the `Request-Id` header and the `instance` (`urn:uuid:<Request-Id>`). Quote it to support. |

A validation failure (`invalid_parameters`) adds `errors`, one entry per failed rule, each with a `detail`, the rule's `code` (`max`, `date_format`, `url_not_allowed`, `max_nights`, …) and where it failed: `parameter`, `header` or `pointer` (an RFC 6901 JSON Pointer into the request body).

| Status | `code` |
| - | - |
| 400 | `invalid_parameters`, `invalid_cursor`, `window_beyond_horizon` (with the property's `horizon_end`) |
| 401 | `missing_api_key`, `invalid_api_key`, `api_key_wrong_environment`, `api_key_expired`, `api_key_revoked` ([Authentication](/en/distribution-api/authentication)) |
| 403 | `insufficient_scope` (with `required_scopes`), `partner_suspended` |
| 404 | `not_found`: the resource does not exist, was never distributed to you, belongs to another channel or its id is malformed, or (for availability) the property is withdrawn or deleted. The answer is identical in every case. |
| 405 | `method_not_allowed` |
| 409 | `webhook_endpoint_exists`, `webhook_endpoint_limit_reached`, `webhooks_suspended_by_platform`, `webhook_endpoint_still_failing` |
| 410 | `sync_window_expired`, `event_cursor_expired` ([Synchronisation](/en/distribution-api/synchronisation)) |
| 415 | `unsupported_media_type` |
| 429 | `rate_limited`, `too_many_failed_authentications` |
| 500 | `internal` |
| 503 | `service_unavailable` |

Like every enum here, the list of codes is open: treat a code you do not know by its status. 405 and 503 are answered the same way on every path.

## Rate limits

Your channel's limit is a number of requests per minute, at least 600; `GET /channel` gives yours in `rate_limit.per_minute`. Every authenticated response counts against it, refusals included, and carries how much is left:

| Header | |
| - | - |
| `RateLimit-Limit` | The requests allowed in the window. |
| `RateLimit-Remaining` | The requests left in it. |
| `RateLimit-Reset` | Seconds until the window resets. |
| `RateLimit-Policy`, `RateLimit` | The same, in the shape of the IETF draft `draft-ietf-httpapi-ratelimit-headers`, such as `"partner";q=600;w=60` and `"partner";r=598;t=37`. Provisional: the three headers above are the stable contract. |

A page of `GET /availability` costs `max(1, ceil(nights / 1000))` units instead of one. Over the limit, the answer is `429` with a `Retry-After` header, the seconds to wait before trying again. Repeated failed authentication from one address is answered `429` the same way.


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