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

# Errors, idempotency & versioning

> Problem details, retry semantics and the compatibility contract

## Errors — RFC 9457 problem details

Every error is `application/problem+json` with a stable machine-readable `code`:

```json theme={null}
{ "type": "https://docs.gleap.io/s2s/problems/conversation_closed",
  "title": "Conversation Closed", "status": 409, "code": "conversation_closed",
  "detail": "This conversation is closed. Reopen it to send messages.",
  "request_id": "req_66c0ffee0000000000000001" }
```

Branch on `code`, never on `detail` (human wording can change). Every response — success or error — carries a `Gleap-Request-Id` header; include it when contacting support about a request.

| Code                       | Status | Meaning                                                                      |
| -------------------------- | ------ | ---------------------------------------------------------------------------- |
| `unauthorized`             | 401    | Missing, invalid or revoked service-account token                            |
| `forbidden`                | 403    | Token cannot access this resource/channel                                    |
| `not_found`                | 404    | Resource does not exist in this project (also: pruned/deleted conversations) |
| `validation_failed`        | 400    | Request shape invalid (`errors` extension carries field details)             |
| `conversation_closed`      | 409    | Customer messages rejected until reopened                                    |
| `contact_blocked`          | 403    | The contact is blocked in this project                                       |
| `agent_not_capable`        | 400    | The AI agent lacks the "Reply to customer" tool                              |
| `workflow_not_found`       | 404    | Unknown or non-live workflow                                                 |
| `idempotency_in_flight`    | 409    | Original request with this key still processing — retry after `Retry-After`  |
| `idempotency_key_reuse`    | 422    | Same key, different request body                                             |
| `rate_limited`             | 429    | Over budget — honor `Retry-After`                                            |
| `rate_limiter_unavailable` | 503    | Transient infrastructure state — retry after `Retry-After`                   |
| `unsupported_version`      | 400    | Unknown `Gleap-Version` value                                                |
| `webhook_limit_reached`    | 409    | More than 5 webhook endpoints                                                |
| `payload_too_large`        | 413    | Upload exceeds 25 MB                                                         |
| `upload_failed`            | 500    | Storage/transcode failure                                                    |
| `internal_error`           | 500    | Unexpected server error — safe to retry                                      |

## Idempotency

Send an `Idempotency-Key` header (≤255 chars, e.g. a UUID) on any POST you might retry:

* A **successful** response is stored and replayed for **24 hours** — replays carry `Gleap-Idempotency-Replayed: true` and are byte-equivalent (file URLs re-signed fresh).
* **Error responses are never stored** — retry them normally with the same key.
* The same key with a **different body** returns `422 idempotency_key_reuse`.
* Semantics are **at-least-once**: a retry racing a crashed or >60-second-running original may re-execute. Design consumers to tolerate a rare duplicate (e.g. reconcile by conversation `number`/content), as you would with Stripe-style idempotency.

## Versioning & compatibility

* Pin with `Gleap-Version: 2026-08-01`; responses echo the resolved version.
* Within a version, changes are **additive only** — ignore unknown fields and unknown event types.
* Breaking changes ship as a new dated version; the previous version remains supported for **at least 12 months** with written notice.
