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

# Errors and retries in the TypeScript SDK

> Handle Darwin API errors in @meetdarwin/api: DarwinError and its classes by status, automatic retries on 429, 5xx and network errors, idempotency keys on every write, and cancelling a call.

## Errors

Every failure is a `DarwinError`. HTTP errors carry the API's [problem document](https://docs.meetdarwin.ai/api-reference/errors.md):

```ts theme={null}
import { DarwinError, NotFoundError, RateLimitError } from "@meetdarwin/api";

try {
  await darwin.contacts.retrieve("ct_missing");
} catch (error) {
  if (error instanceof NotFoundError) {
    // 404
  } else if (error instanceof DarwinError) {
    console.error(error.status, error.code, error.detail, error.param, error.requestId);
  }
}
```

| Field | Meaning |
| - | - |
| `status` | HTTP status; `undefined` for network errors and timeouts |
| `code` | Stable machine-readable code, such as `insufficient_scope`. Branch on this. |
| `detail` | A sentence for a person |
| `param` | The field at fault, such as `limit` or `buttons[0].label` |
| `requestId` | Quote it to Darwin support |
| `requiredPlan` | With `plan_required` (403): the plan that unlocks it, `growth` or `agency` |
| `headers` | The response headers (`RateLimit-*`, `Retry-After`, `WWW-Authenticate`) |

Classes by status: `InvalidRequestError` (400), `AuthenticationError` (401), `PaymentRequiredError` (402), `PermissionDeniedError` (403), `NotFoundError` (404), `ConflictError` (409), `UnprocessableError` (422), `RateLimitError` (429, with `retryAfter` in seconds), `InternalServerError` (5xx), `ConnectionError` and its subclass `TimeoutError` (no response). Error messages never contain your API key.

## Retries

The client retries, up to `maxRetries` times (default 2):

* **429**: after the `Retry-After` delay. If the API asks for more than a minute, the client gives up at once with a `RateLimitError` so you can schedule the work.
* **5xx and network errors**: with exponential backoff and jitter (about 0.5 s, 1 s, 2 s…).
* **409 `idempotency_key_in_use`**: an earlier attempt is still running; the retry gets its answer.

## Idempotency

Every `POST`, `PATCH` and `DELETE` carries an `Idempotency-Key`. The client makes up a random UUID when you do not pass one and reuses it on every retry, so a retried write is applied once. The API keeps a key's response for 24 hours; a replayed response has the `Idempotent-Replayed: true` header.

Pass your own key when a write may be repeated across processes or restarts, such as a queue job:

```ts theme={null}
await darwin.contacts.create({ email: "ada@example.com" }, { idempotencyKey: `signup-${userId}` });
```

Reusing a key with a different body is refused with `422 idempotency_key_reused`. More in [Idempotency](https://docs.meetdarwin.ai/api-reference/idempotency.md).

## Cancel a call

Cancel a call, and its retry waits, with an `AbortSignal`:

```ts theme={null}
await darwin.analytics.get({ range: "30d" }, { signal: AbortSignal.timeout(5_000) });
```


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