# Errors

Use the HTTP status and the shared JSON error envelope.

API errors use one JSON shape:

```json
{"code": "invalid_key", "message": "A valid API key is required."}
```

Branch on the HTTP status and stable `code`, not the prose in `message`. Messages never repeat your request content. Intermediaries can still return non-JSON failures; treat those as transport failures rather than successful decisions.

Every response, success or error, carries an `X-Request-Id` header (`req_` and 32 hex characters). Log it and quote it when contacting Secnd. The SDK errors expose it as `requestId` (TypeScript) and `request_id` (Python).

| Status | Meaning | Your next step |
| --- | --- | --- |
| `400` | Malformed JSON or compression, or JSON nested deeper than 64 levels | Fix the body or headers |
| `401` | Missing, invalid, or revoked bearer key | Fix credentials; do not blindly retry |
| `413` | Body over 4 MB, or input over 2048 tokens | Reduce the request; no automatic truncation |
| `415` | Unsupported content type or content encoding | Use JSON and a supported single encoding |
| `400 unknown_model` | Unknown, shortened, or case-variant model ID | Use `ren-1.1.0`, `ren-latest`, or `ren-preview` |
| `422` | Unknown or missing fields at any level, option or level count, duplicate IDs, invalid levels | Fix the schema |
| `429` | Key or account rate limit reached | Honor `retry-after-ms` or `Retry-After` and back off |
| `502` | Invalid or unavailable inference response | Retry within a bounded budget |
| `503` | Gateway temporarily unavailable | Retry within a bounded budget |
| `504` | Inference timed out | Retry within a bounded budget |
| `529` | Inference overloaded | Back off and reduce concurrency |

If inference fails, do not manufacture an answer or proceed as if the gate passed. Queue review or return a temporary failure from your own application.

A `429` always means the same request can succeed later. Requests the gateway can reject outright (`400`, `413`, `415`, `422`) are rejected for what they are, before rate limiting, and do not count against your limit. The 2048-token limit is checked by inference after rate limiting, so an over-limit request counts as one request and returns `413`.

The SDKs retry `429` and server errors with bounded backoff. Apply a separate application timeout and avoid wrapping SDK retries in an unbounded retry loop. Authentication and validation errors need corrected input.
