# Error reference - Veezee docs

Every Veezee error is one of the 17 codes below. REST returns `application/problem+json`; MCP returns the same content as an error result. `message` is written as the next-turn instruction: read it and act on it instead of retrying blind. `is_retriable: true` means retry is safe; `false` means change something first. Every error's `doc_url` points at its entry on this page.

## INVALID_INPUT

HTTP 400, retriable: no.

A parameter failed validation: a malformed identifier or URL, an invalid section name, a limit above the allowed maximum, or a missing required field. `message` names the fix and `param` names the parameter. Fix that parameter and send the call again; retrying unchanged fails the same way.

## NOT_FOUND

HTTP 404, retriable: no.

Nothing matches what you sent: the entity does not exist on its platform, the API route is unknown, or an idempotent replay's stored response has expired. Fix or replace the identifier before calling again; retrying it unchanged will not succeed. For an expired replay, send the call again with a fresh Idempotency-Key.

## UNAUTHORIZED

HTTP 401, retriable: no.

The key or link is not usable: unrecognized key format, no matching active account, a suspended account, or a claim or recovery link that is invalid, expired, or already used. Check the key for truncation, or mint a fresh one: `POST /v1/keys/mint` (no body) returns a new key, free, no signup. For an expired claim or recovery link: `POST /v1/recover` sends a new recovery link to the claimed email (legacy trial accounts get a fresh `claim_url` from `get_usage`); anyone else, write to hello@veezee.io.

## NOT_ENTITLED

HTTP 403, retriable: no.

The key is valid but this account is not enabled for the platform the call needs. Nothing was charged. Call `get_usage`: it lists the platforms this key can call. Write to hello@veezee.io to request more.

## INSUFFICIENT_CREDITS

HTTP 402, retriable: no.

The account balance cannot cover this call's quote; `credits_required` says how many credits the call needed. Nothing was charged. Give `upgrade_url` to your human to add credits, then retry the same call with the same Idempotency-Key.

This error carries `upgrade_url` (give it to your human) and `offer`: see [errors a payment can fix](https://veezee.io/docs/errors#offer).

## QUOTE_EXCEEDS_MAX_CREDITS

HTTP 402, retriable: no.

The call quotes more credits than the `max_credits` you set. Nothing was charged. Raise `max_credits` to at least the quoted amount, or reduce `sections` or `limit` to shrink the quote.

## IDEMPOTENCY_KEY_REQUIRED

HTTP 400, retriable: no.

A metered call (GET included; metered GETs charge credits) arrived without an `Idempotency-Key` header. Send one: any unique string, a UUID is ideal. Reuse the same key only when retrying this exact call.

## IDEMPOTENCY_KEY_REUSED

HTTP 409, retriable: no.

This Idempotency-Key was already used with different arguments. Generate a fresh key for a new call; reuse a key only to retry the identical call.

## CONCURRENCY_LIMIT

HTTP 429, retriable: yes.

Another call on this account is still in flight, or the original call with this Idempotency-Key is still running. Wait for it to finish, then retry; `retry_after_seconds` says how long.

On trial accounts, this error carries `upgrade_url` (give it to your human) and `offer`: see [errors a payment can fix](https://veezee.io/docs/errors#offer).

## RATE_LIMITED

HTTP 429, retriable: yes.

Too many calls per minute for this key's plan. Recovery requests have their own per-minute limit. Slow down and retry after `retry_after_seconds`.

On trial accounts, this error carries `upgrade_url` (give it to your human) and `offer`: see [errors a payment can fix](https://veezee.io/docs/errors#offer).

## TRIAL_CAP_EXCEEDED

HTTP 403, retriable: no.

A capped tier hit its limit: a free key used up its shared per-IP daily budget, or (on a trial-plan key) a search `limit` above the trial maximum or the trial's total realtime fetches. Free key: wait for the UTC day to roll over, or buy a key at `/upgrade` (the error's `upgrade_url` points there directly); checkout credits the same key. Trial key: stay inside the cap, or upgrade the account; after upgrading, retry with a fresh Idempotency-Key.

This error carries `upgrade_url` (give it to your human) and `offer`: see [errors a payment can fix](https://veezee.io/docs/errors#offer).

## BUDGET_EXHAUSTED

HTTP 503, retriable: no.

The shared free-tier budget is exhausted or closed right now (free keys and trial-plan keys draw from the same pool); cached data still serves. Free key: the error's `upgrade_url` points straight at `/upgrade`, or retry later; checkout credits the same key. Trial key: claim or upgrade the account (`get_usage` returns `claim_url` and `upgrade_url`), or retry later. After payment, retry with a fresh Idempotency-Key.

This error carries `upgrade_url` (give it to your human) and `offer`: see [errors a payment can fix](https://veezee.io/docs/errors#offer).

## UPSTREAM_UNAVAILABLE

HTTP 502, retriable: yes.

LinkedIn data wasn't reachable, or live fetching is temporarily paused; cached data still serves. Retry the request; respect `retry_after_seconds` when present.

## PAYLOAD_TOO_LARGE

HTTP 413, retriable: no.

The request or response exceeded the size limit. Reduce the request size and send it again.

## INTERNAL

HTTP 500, retriable: yes.

Something failed on our side. Retry once; if it persists, report the receipt id to hello@veezee.io.

## AUTH_REQUIRED

HTTP 401, retriable: no.

A valid spend key reached an operation that needs the identity tier (account management). The key itself is fine; the operation wants a signed-in identity or a `vzm_` management token. Run `vz login` (mints a `vzm_` management token into ~/.veezee/config), or sign in at `/login` with a one-time emailed code, or send an existing `vzm_` token instead of the spend key. Data calls are unaffected; only management operations need this.

## KEY_REQUIRED

HTTP 401, retriable: no.

The call carried no API key at all. Every data call needs one. Mint a free key in one call: `POST /v1/keys/mint` (no body) returns a key, shown once, plus ready-made setup snippets. Retry the same call with `Authorization: Bearer <key>`. No signup, no card, no human.

## Errors a payment can fix

Errors a payment can fix add fields to this shape. INSUFFICIENT_CREDITS, TRIAL_CAP_EXCEEDED, and BUDGET_EXHAUSTED carry `upgrade_url` (give it to your human) and `offer`, its machine-readable twin; RATE_LIMITED and CONCURRENCY_LIMIT carry both on trial accounts only, where a paid plan raises the limit. `offer` holds `offer_version` (1), `reason` (the error code), `currency` ("usd"), `recommended` (which pack to lead with, currently `flex`), `packs` (pack, mode, price_usd_cents, credits or credits_per_month, and `when`, a short label for when that pack fits), `rails` (currently `stripe_checkout`), `checkout_url` (the same account-bound link as `upgrade_url`), `resume`, and `refund_policy`. Follow `offer.resume` after payment: INSUFFICIENT_CREDITS retries the same call with the same Idempotency-Key; TRIAL_CAP_EXCEEDED and BUDGET_EXHAUSTED retry with a fresh key; the two limit codes clear on their own with back-off, payment only raises the limit. INSUFFICIENT_CREDITS also sets `credits_required`: the credits the failed call needed. The failed attempt charged nothing.
