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

# Errors

> HTTP error codes returned by the DecimalAI API and how to handle them.

The DecimalAI API uses standard HTTP status codes and returns structured JSON error bodies.

## Error response shape

```json theme={null}
{
  "detail": "Skill 'search-flights' not found"
}
```

For validation errors raised by Pydantic, `detail` is a list of structured field errors:

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "agent_name"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

## Status codes

| Code    | Meaning               | Common causes                                                                                                                                      | What to do                                                                                                                                          |
| ------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **200** | OK                    | Request succeeded.                                                                                                                                 | Use the response body.                                                                                                                              |
| **201** | Created               | Resource created (skill, dataset, API key).                                                                                                        | Persist the returned ID.                                                                                                                            |
| **400** | Bad Request           | Missing field, malformed JSON, invalid enum value, or webhook signature mismatch.                                                                  | Check the `detail` for the failing field; fix the request body and retry.                                                                           |
| **401** | Unauthorized          | Missing or invalid API key, expired Clerk session, or webhook signature header missing.                                                            | Re-issue the API key from Settings → API Keys. Confirm the header is `Authorization: Bearer dai_sk_...`.                                            |
| **402** | Payment Required      | Plan quota exhausted (traces ingested, SFT rows, or other metered resource).                                                                       | Upgrade the plan in Settings → Billing, or wait for the next billing period. The `detail` names the exhausted metric.                               |
| **403** | Forbidden             | Your role lacks permission for this action, or you're attempting to access a workspace you don't belong to.                                        | Ask a workspace admin to grant the required role, or scope the action to a workspace you have access to.                                            |
| **404** | Not Found             | The named resource (trace ID, skill name, manifest ID, dataset version) doesn't exist or has been deleted.                                         | Check the resource ID; verify it exists with a `list` call.                                                                                         |
| **409** | Conflict              | Idempotency conflict — e.g., installing a registry skill that's already installed, or syncing a skill whose body hash matches an existing version. | This is usually safe to ignore. The conflicting resource is returned in `detail`.                                                                   |
| **422** | Unprocessable Entity  | Request validation failed (Pydantic).                                                                                                              | The `detail` array lists each invalid field.                                                                                                        |
| **429** | Too Many Requests     | Rate limit exceeded for your plan tier.                                                                                                            | Honor the `Retry-After` response header and back off. See the [Tracing guide](/guides/tracing) for batch ingest patterns that reduce request count. |
| **500** | Internal Server Error | Unhandled exception on the backend.                                                                                                                | Retry with backoff; if persistent, file a support request with the response `X-Request-ID` header.                                                  |
| **501** | Not Implemented       | Feature is gated, deprecated, or not enabled on your plan.                                                                                         | Check the [Pricing page](/pricing) for plan availability.                                                                                           |
| **503** | Service Unavailable   | Backend overloaded or in maintenance.                                                                                                              | Retry with backoff; if persistent, email [support@decimal.ai](mailto:support@decimal.ai) with your `X-Request-ID`.                                  |

## Idempotency

Several endpoints are idempotent by design:

* `POST /api/v1/manifests` — same `manifest_hash` returns the existing `manifest_id` with `status: "existing"`.
* `POST /api/v1/skills/sync` — unchanged skills return `{"status": "unchanged"}`; changes auto-create a new version.
* `POST /api/v1/traces` — duplicate `trace_id` returns the existing trace.

Re-running these is safe and will not double-count toward your quota.

## Rate limits

Indicative rate limits per plan tier (the per-minute numbers are illustrative targets, not a hard contract — limiting is currently global rather than per-plan-enforced):

| Plan       | Trace ingest (per min) | Read endpoints (per min) |
| ---------- | ---------------------- | ------------------------ |
| Free       | 60                     | 120                      |
| Core       | 600                    | 1,200                    |
| Pro        | 1,800                  | 3,600                    |
| Enterprise | Custom                 | Custom                   |

When you hit a limit, responses include:

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 12
```

The SDK respects `Retry-After` automatically. If you're calling the API directly, sleep for the indicated number of seconds before retrying.

## Reporting an issue

For 5xx errors or unexpected behavior, include the `X-Request-ID` response header when filing a support ticket — it lets us look up the failing request in logs.
