# TellTide errors

Stable error handling for agents.

## Envelope

```json
{
  "error": {
    "code": "string",
    "message": "string",
    "requestId": "req_..."
  }
}
```

Return `requestId` to the user when asking for help.

## Common codes

| HTTP | `code` | Meaning | Agent action |
|------|--------|---------|--------------|
| 400 | (validation) | Bad body / field limits | Fix payload; do not blind-retry |
| 401 | auth failure | Missing/invalid credential | Check env key; stop |
| 403 | `insufficient_scope` | Key lacks required scope | Use a key with the right scopes |
| 403 | `subscription_required` | No active Pro/trial | Tell user to start trial / subscribe |
| 403 | origin / policy | Publishable key origin blocked | Fix allowed websites or use private key |
| 404 | `resource_not_found` | Unknown id / wrong app | Verify feedbackId and key app |
| 409 | conflict | Idempotency key reused with different body | New `Idempotency-Key` or same body |
| 429 | rate limited | Too many requests | Wait `Retry-After`; retry same idempotency key |
| 503 | config / dependency | Temporary service issue | Backoff and retry |

## Retry policy

| Condition | Retry? |
|-----------|--------|
| Network timeout / connection reset | Yes — exponential backoff, same `Idempotency-Key` |
| `429` | Yes — honor `Retry-After` |
| `5xx` | Yes — limited retries with backoff |
| `400` / `401` / `403` / `404` | No — fix input or credentials |
| `409` idempotency mismatch | No — new key or identical body |

## Idempotency

- Required on create.
- Same key + same body → safe replay.
- Same key + different body → `409`.
- Generate keys from a stable run id when possible (e.g. `agent-{runId}-{intent}`).

## Security notes

- Do not log full `Authorization` headers.
- On `401` after a suspected leak, tell the user to **rotate** the key in **Apps → Manage → API credentials**.
