# Errors

## Success and error payloads

Structured errors return JSON of the form:

```json
{
  "detail": {
    "error_code": "SOME_CODE",
    "message": "Human-readable explanation."
  }
}
```

**Validation errors** (`error_code: "VALIDATION_ERROR"`) additionally include a `fields` array describing each rejected input. Each entry has `type` (a stable code such as `missing`, `extra_forbidden`, `int_parsing`, `string_too_long`), `loc` (path to the field), `msg` (human text), and `input` (the value that failed). Use **`detail.message`** for a single-line summary and **`detail.fields`** if you need per-field structured detail.

Authentication failures use the same object form: `401 AUTH_API_KEY_MISSING` (no `X-API-Key`), `403 AUTH_API_KEY_INVALID` (unknown or inactive key), `403 AUTH_USER_INACTIVE`, `403 AUTH_EMAIL_NOT_VERIFIED`. Every 4xx and 5xx response uses the object form above.

An error returned after credits were debited also carries **`credits_used`**, the credits that request used.

**Plan-tier responses.** A request may be rejected because the caller's plan does not include the requested endpoint or option. These return **`403`** with one of `PLAN_TIER_INSUFFICIENT`, `PLAN_TIER_INSUFFICIENT_HISTORY`, `PLAN_TIER_INSUFFICIENT_FORMULA_OVERRIDE`, or `PLAN_TIER_INSUFFICIENT_COVERAGE`. The `detail` body also carries `required_tier` (the lowest plan that would accept the request) and `current_tier` (the caller's current plan). See **[API key, account, and plan errors](/documents/errors.md#api-key-account-and-plan-errors)**.

## API key, account, and plan errors

| HTTP | When |
|------|------|
| 401 | `AUTH_API_KEY_MISSING` — no `X-API-Key` header. |
| 403 | `AUTH_API_KEY_INVALID` — unknown or inactive key. |
| 403 | `AUTH_USER_INACTIVE` — the key's account is inactive or deleted. |
| 403 | `AUTH_EMAIL_NOT_VERIFIED` — the key's account has not verified its email. |
| 403 | `AUTH_API_KEY_EXPIRED` — key past its expiry. |
| 403 | `AUTH_API_KEY_INACTIVE` — key disabled by inactivity policy. |
| 403 | `AUTH_MCP_CLIENT_REVOKED` — the MCP connection behind this access token was disconnected. |
| 403 | `PLAN_TIER_INSUFFICIENT` — the endpoint, or a filing, metric group, transaction or holding requested by id, is not available on the caller's current plan. |
| 403 | `PLAN_TIER_INSUFFICIENT_HISTORY` — a request names one filing by `ticker` and a `fiscal_year` before the caller's plan's history window. The body carries `filing_fiscal_year` and `earliest_allowed_fiscal_year`. |
| 403 | `PLAN_TIER_INSUFFICIENT_FORMULA_OVERRIDE` — the `formula_override` request field is not available on the caller's current plan. Omit `formula_override` to proceed, or upgrade. |
| 403 | `PLAN_TIER_INSUFFICIENT_COVERAGE` — the company named by `ticker` or `cik`, or the requested `jurisdiction`, is outside the caller's plan's coverage scope. Body also carries `coverage_band`. |

Every `PLAN_TIER_*` response includes `required_tier` and `current_tier` strings (lowercase plan names) in the `detail` body so clients can prompt for an upgrade without parsing the message text.

## Request limits (validation)

These caps apply at validation time (**422** when exceeded):

| Limit | Value |
|-------|--------|
| Line items per request (`/data/line-items`, `/data/compare/line-items`) | 50 |
| Fact ids per request (`/data/facts`) | 500 |
| Fact ids per row (`/data/compare/facts`) | 500 |
| Total fact ids (`/data/compare/facts`) | 2500 |
| Filings per compare request | 25 |
| Metric names (`/metric/items`, optional `/metric/historical`) | 100 |
| Concepts per metric in `formula_override` (`/metric/all`, `/metric/items`, `/metric/historical`) | 50 |
| Form types (`/metric/filings`) | 8 |
| Historical page size | 5 |
| Corporate event Item codes (`/events/filing`, `/screener/events`) | 33 |
| Corporate event screening tickers | 100 |
| Corporate event screening page size | 10 (default 5) |
| Corporate event screening cumulative results | page × page_size ≤ 500 |
| Screening cumulative results (`/screener/*`) | page × page_size ≤ 500 |
| Ids per request (`/ownership/transaction-ids`, `/ownership/initial-holding-ids`) | 100 |
| Page number (`page`, `ids_page`) | 1,000,000 |
| Search `query` (`/data/company/search`, `/ownership/institutional-holdings/managers`) | 64 characters |

*AkkruData — API user guide.*
