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

# Errors

> Status codes, the error envelope, and how to handle failures.

Errors use the same envelope as successful responses, with `success: false` and a human-readable `message`.

```json theme={null}
{
  "success": false,
  "message": "API key is required"
}
```

Validation failures may include an `errors` array with per-field detail.

## Status codes

| Code  | Meaning         | What to do                                                                          |
| ----- | --------------- | ----------------------------------------------------------------------------------- |
| `200` | Success         | —                                                                                   |
| `201` | Created         | The resource exists; the response carries it                                        |
| `204` | No content      | Success with nothing to return                                                      |
| `400` | Bad request     | A required field is missing or malformed. Fix the request — retrying won't help     |
| `401` | Unauthenticated | Missing, invalid, expired, or deactivated key                                       |
| `403` | Forbidden       | Key is valid but lacks the permission, or the resource belongs to another workspace |
| `404` | Not found       | Wrong ID, or the resource isn't in this workspace                                   |
| `429` | Rate limited    | Back off and retry — see [Rate limits](/api-reference/rate-limits)                  |
| `5xx` | Server error    | Retry with backoff; if it persists, contact support                                 |

<Note>
  `403` is returned rather than `404` when a resource exists but isn't yours — and `404` when it isn't visible to your workspace at all. Neither confirms the existence of another workspace's data.
</Note>

## Common causes

<AccordionGroup>
  <Accordion title="401 on a key that used to work" icon="key">
    The key was deactivated, it hit its expiry date, or you're sending a truncated value. Check for whitespace or a partially-copied key in your environment variables.
  </Accordion>

  <Accordion title="403 on a request you expect to work" icon="lock">
    A missing permission scope. Transcript and recording access are separate from `calls:read` — see [Authentication](/api-reference/authentication).
  </Accordion>

  <Accordion title="400 on a phone number" icon="phone">
    Send E.164 — `+14155551234`, with country code and no punctuation.
  </Accordion>

  <Accordion title="403 when sending SMS" icon="comment-sms">
    The `from` number doesn't belong to your workspace. Use one of your own provisioned numbers.
  </Accordion>

  <Accordion title="429 on call creation" icon="gauge-high">
    Either the API rate limit or your plan's call limit. The message distinguishes them.
  </Accordion>
</AccordionGroup>

## Handling errors well

<Steps>
  <Step title="Branch on status code, not message text">
    `message` is written for humans and may be reworded. Status code and `success` are the stable contract.
  </Step>

  <Step title="Don't retry 4xx">
    Except `429`. A `400` or `403` will fail identically every time — retrying just burns your rate limit.
  </Step>

  <Step title="Retry 5xx and 429 with exponential backoff">
    Respect `Retry-After` on `429`. Add jitter so parallel workers don't retry in lockstep.
  </Step>

  <Step title="Log the whole response">
    Status, `message`, and any `errors` array. Diagnosing from "the API failed" is guesswork.
  </Step>
</Steps>

<Warning>
  Don't log the API key itself, and don't include full call transcripts in application logs — they contain customer personal data. See [Security & privacy](/account/security-and-privacy).
</Warning>

## Checking service health

```bash theme={null}
curl https://api.recepta.ai/api/v1/health
```

Returns status, a timestamp, and version. Useful for confirming the API is reachable before you go digging into your own integration.
