# Error reference

<!-- GENERATED by gateway/scripts/generate-error-docs.mjs — DO NOT EDIT. This page renders gateway/contracts/errors.json; edit the catalogue and regenerate. -->

# Error reference

Every failure this API can return is listed below. Each error is an RFC 9457
Problem Detail sent as `application/problem+json`, and the `type` member of every
error body is a stable URI that resolves to its page in this reference — the link
in the body you are holding is the documentation for it. A `type` never changes
without a documented deprecation.

## The two 503s are different claims — do not treat them alike

Two errors share status `503` and they must not be read as one:

- [`ledger-unreachable`](/errors/ledger-unreachable) — the call was **never
  started and no Credits were consumed**. This is only ever sent when the failure
  was provably reached before any Spend could leave.
- [`spend-indeterminate`](/errors/spend-indeterminate) — **no claim is made about
  what was consumed**, because the outcome is not known. Any Credit recorded for
  the call is returned to the Account as a Refund.

A monitor that counts every 503 as "no charge" will misread the second one; a
monitor that counts every 503 as "charged" will misread the first. Branch on the
`type`, not the status.

## The four 422s are four different things to do

Four errors share status `422`, and each asks for a different next action:

- [`ambiguous-address`](/errors/ambiguous-address) — the address matched more than
  one property. Choose one of the returned candidates, or add a city or ZIP.
- [`address-out-of-coverage`](/errors/address-out-of-coverage) — the state is not
  inside current data coverage yet. Coverage is temporary, not a product boundary;
  the body lists the states covered right now.
- [`unscorable-address`](/errors/unscorable-address) — the property cannot be
  scored. Retrying the same address returns the same answer.
- [`idempotency-key-conflict`](/errors/idempotency-key-conflict) — the
  `Idempotency-Key` was already used with a different body. Nothing was charged;
  send the request again with a new key.

All four are refusals about the request, never about our availability — and a
client branching on status alone cannot tell them apart. Branch on the `type`.

## Every error

| Status | Type | Title | Retryable | Credits |
| --- | --- | --- | --- | --- |
| `401` | [`invalid-key`](/errors/invalid-key) | Invalid API Key | No | None consumed |
| `402` | [`insufficient-credits`](/errors/insufficient-credits) | Insufficient Credits | No | None consumed |
| `429` | [`rate-limited`](/errors/rate-limited) | Rate limit exceeded | Yes | None consumed |
| `400` | [`invalid-request`](/errors/invalid-request) | Malformed request | No | None consumed |
| `413` | [`payload-too-large`](/errors/payload-too-large) | Batch too large | No | None consumed |
| `503` | [`ledger-unreachable`](/errors/ledger-unreachable) | Ledger unreachable | Yes | None consumed |
| `503` | [`spend-indeterminate`](/errors/spend-indeterminate) | Spend outcome indeterminate | Yes | Returned as a Refund if recorded |
| `504` | [`upstream-timeout`](/errors/upstream-timeout) | Upstream service timed out | Yes | Refunded |
| `502` | [`upstream-unavailable`](/errors/upstream-unavailable) | Upstream service unavailable | Yes | Refunded |
| `422` | [`ambiguous-address`](/errors/ambiguous-address) | Address is ambiguous | No | Refunded |
| `422` | [`address-out-of-coverage`](/errors/address-out-of-coverage) | Address outside current data coverage | No | Refunded |
| `422` | [`unscorable-address`](/errors/unscorable-address) | Address cannot be scored | No | Refunded |
| `422` | [`idempotency-key-conflict`](/errors/idempotency-key-conflict) | Idempotency-Key conflict | No | None consumed |
| `409` | [`duplicate-request-in-flight`](/errors/duplicate-request-in-flight) | Duplicate request in flight | Yes | None consumed |
| `404` | [`unknown-endpoint`](/errors/unknown-endpoint) | No such endpoint | No | None consumed |
| `503` | [`call-not-started`](/errors/call-not-started) | Call never started | Yes | None consumed |

The Credits column is a summary; each page states the full outcome. "Refunded"
means the response itself says whether the Refund is applied or pending, and a
Refund is visible in the Portal's Ledger history like any other entry.
