# Car Image API errors

Every JSON failure is an [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem document (`Content-Type: application/problem+json`) with `type`, `title`, `status`, `detail` and `request_id`. The `type` URL points at the matching section of this page. Log the `request_id`; never log API keys or delivery tokens.

Billing rule of thumb: only a `200` that delivers an image or mints signed URLs costs credits. Every error below costs nothing, and a render that fails after being charged is refunded automatically.

## 304

Not an error. You sent `If-None-Match` with the `ETag` of an image you already have and it is unchanged. Free, still counts against the rate limit. Keep the bytes you have.

## 308

Not an error. `/images/car.png` redirects non-canonical spellings (`brand=Ford` -> `brand=ford`, `format=jpeg` -> `format=jpg`) to the one canonical URL so caches hold a single copy. Follow it; `mode=cached` survives the redirect. Partner-signed requests are never redirected.

## 400

Invalid parameters or body: unknown or repeated query parameters, `make` and `brand` together, a color outside the 15 presets, a size above 1024, a malformed JSON body, an empty `query`. Fix the request; retrying unchanged will fail again. Batch problems include `index` of the offending item. `GET /api/v1/images/options` lists every valid value.

## 401

No usable credential. Send `Authorization: Bearer cimg_…` (or `x-api-key`). The key may be missing, malformed or revoked (`WWW-Authenticate: Bearer error="invalid_token"`). Get a key at `/dashboard` or run `npx @meterapp/car-image login`. Never move a key into a URL; for browsers mint signed URLs with `POST /api/v1/image-urls`.

## 402

Not enough credits. The problem carries `balance` and `required_credits`, and the response has `Link: </pricing>; rel="payment"`. Agents: stop, report the balance, and let the human decide; `POST /api/v1/billing/checkout` returns a hosted Stripe page but only a human should complete it. $1 = 1,000 credits.

## 403

One of: the key lacks the scope the endpoint needs (`required_scope` in the problem: `images:read`, `account:read` or `billing:write`); a delivery URL is invalid or expired; the API key that created the delivery URL was revoked; a partner signature on `/images/car.png` is missing, malformed, expired, more than 30 days ahead, or does not match. Create a correctly scoped key or a fresh URL.

## 404

The make/model/year is not in the catalog (`GET /api/v1/vehicles?q=…` or `POST /api/v1/images/resolve` will find the right slugs), `mode=cached` asked for a variant that has never been rendered, or feedback referenced a request that delivered no image. Do not retry unchanged.

## 410

A use-capped delivery URL (`max_uses > 0`) has been loaded `max_uses` times. Create a new URL. Unlimited URLs (`max_uses: 0`) never return 410.

## 413

The body is larger than the endpoint allows: 64 KiB for `POST /api/v1/image-urls` (split into batches of at most 50 images), 32 KiB for `/api/v1/events`, 8 KiB for feedback, 4 KiB for resolve, 1 KiB for checkout.

## 429

Rate limit exceeded: 120 requests per minute per key by default (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` are on every authenticated response), or a per-IP limit on public endpoints. Wait the integer seconds in `Retry-After`, then retry with exponential backoff and jitter. Device-login polling returns `{"error":"slow_down"}` with the same header.

## 500

Unexpected server failure. Nothing was charged. Retry with backoff; include the `request_id` when reporting.

## 502

The image could not be rendered (the image model or origin storage failed). The credit for that request was refunded; for a delivery URL, its creation credit is refunded and the problem says so. Retry later or with a different view.

## 503

A dependency (authentication, rate limiter, verification) is temporarily unavailable. Honor `Retry-After`. For a delivery URL a 503 means the URL was not consumed; simply retry it.
