API errors

Every error response carries a stable code and a docs_url that brings you to that code on this page, in your language. The message is short technical English, for machines; this page is for people. Quote the request_id when something does not add up.

Request errors

What the API answers when the request does not go through.

invalid_api_key

HTTP 401type: authentication

The key is missing, does not exist or has been revoked. It goes in X-Api-Key or in Authorization: Bearer; when both arrive, the first one wins.

invalid_token

HTTP 401type: authentication

The person's ID token is missing, expired or does not verify. It only concerns /admin, which is for people, not keys.

impersonation_ended

HTTP 401type: authentication

The X-Lince-Impersonation token no longer works: it expired (they last 60 minutes), it was ended, another impersonation by the same person replaced it, or it belongs to someone else. Only the Spock team gets it, from /api/admin; start a new impersonation from the internal console.

account_suspended

HTTP 403type: permission

The account is suspended. What is already there can still be read; new readings are not accepted.

payment_required

HTTP 402type: payment_required

The subscription is not active or the trial has ended, so live keys are refused. test keys keep working. Not the same as insufficient_credit: that one is running out of trial readings or balance; this one is a subscription that does not entitle the account to read.

insufficient_scope

HTTP 403type: permission

The API key does not have the scope this call needs: read for the GET calls, write to create readings and send feedback, delete to delete a reading. Nothing was done. The scopes of a key are chosen when it is created in the console; to change them, create another key.

forbidden_role

HTTP 403type: permission

Your role in the account does not allow this action.

admin_role_required

HTTP 403type: permission

Only an admin of the internal console can make changes there; viewers can only look.

second_factor_required

HTTP 403type: permission

This area requires two-step verification: set it up in the console and sign in again with the code from your authenticator app.

recent_sign_in_required

HTTP 403type: permission

This action asks for a sign-in in the last 15 minutes: sign in again and repeat it.

no_account

HTTP 403type: permission

The identity is valid but is not a member of any account. The link is made on the first sign-in with a verified email.

insufficient_credit

HTTP 402type: insufficient_credit

There is no balance to pay for the reading. Only affects live mode.

concurrency_exceeded

HTTP 429type: quota

Too many readings in progress at once for this account. It is the limit that protects the real cost: wait for some of them to finish and retry.

quota_exceeded

HTTP 429type: quota

The readings included for the month have run out.

daily_limit_exceeded

HTTP 429type: quota

The account has reached its daily spending cap. It resets at midnight, Madrid time.

rate_limit_exceeded

HTTP 429type: rate_limit

Too many requests per minute. The response carries Retry-After and the X-RateLimit-* headers.

api_key_limit_reached

HTTP 422type: invalid_request

The account already has the maximum number of active keys. Revoke one before creating another.

member_limit_reached

HTTP 422type: invalid_request

The account already has the maximum number of people with access to /admin.

account_name_taken

HTTP 422type: invalid_request

There is already an account with that name. Pick another one; param is account_name.

email_not_allowed

HTTP 422type: invalid_request

An account cannot be created with that email: it belongs to a disposable domain or to another identity. The message is generic on purpose and does not say which.

email_not_verified

HTTP 403type: permission

The identity's email is not verified yet, and signing up requires it. Only POST /console/signup returns it. It is not no_account: that one is not being a member of any account, while here it is enough to open the link we sent and repeat the call. Beware of a cached ID token: the email_verified claim does not change until a new one is requested.

invitation_unavailable

HTTP 422type: invalid_request

The invitation code is not valid: it does not exist, has expired, has been used up, was revoked or is not for that email. The reason, when it can be told, comes from GET /console/invitations/{code}.

last_owner

HTTP 422type: invalid_request

The operation would leave the account without any owner. Appoint another one before demoting or removing the last.

subscription_exists

HTTP 422type: invalid_request

The account already has an active Stripe subscription: changing plan is POST /api/admin/billing/plan, and the card or a cancellation go through the Portal. Only POST /api/admin/billing/checkout returns it.

no_subscription

HTTP 422type: invalid_request

There is no Stripe subscription to do that with. Usually the account has not subscribed yet: it has to go through POST /api/admin/billing/checkout first. It also comes up on a plan change when the Stripe subscription does not have the shape of one of our plans or could not be synchronised after the change; in that case, write to us. The Portal and the plan change return it.

plan_not_billable

HTTP 422type: invalid_request

That plan cannot be subscribed to online (it is not public), or it is the one the account already has. param is plan.

idempotency_key_reused

HTTP 422type: invalid_request

The same Idempotency-Key was used with a different body. Reusing it with the same body returns the original reading; with another one it is an error.

reading_not_completed

HTTP 422type: invalid_request

Feedback can only be given on a completed reading.

reading_not_settled

HTTP 422type: invalid_request

The reading cannot be deleted yet: it is still being read, or what it costs has not been settled. Try again in a few minutes; nothing was deleted.

review_already_resolved

HTTP 422type: invalid_request

Somebody already resolved that review. The resolution says who and when.

export_not_ready

HTTP 409type: invalid_request

The export is still being built, or it failed. Poll GET /api/admin/exports/{id} until its status is ready; a failed one has to be asked for again.

not_impersonating

HTTP 409type: invalid_request

DELETE /api/admin/impersonation arrived without the X-Lince-Impersonation header, so there was no impersonation to end. Nothing was done.

access_request_closed

HTTP 409type: invalid_request

The access request is already registered or dismissed, so it can no longer be invited or dismissed. Nothing was done.

invitations_disabled

HTTP 409type: invalid_request

Invitations are turned off in this environment, so the link would not work. Nothing was sent.

email_already_member

HTTP 409type: invalid_request

The email of the access request already belongs to an account: add the person from that account instead. Nothing was sent.

export_expired

HTTP 410type: invalid_request

The export file is gone: exports are kept for 24 hours after they are ready. Ask for it again.

validation_failed

HTTP 422type: invalid_request

The body or the parameters do not meet the contract. param says which one.

payload_too_large

HTTP 413type: invalid_request

The whole request exceeds the service's size cap, which is fixed and the same for every account. It is not your profile's limit: a file above your profile's per-file size is accepted as a failed reading with file_too_large, and going over the number of files per request is validation_failed.

malformed_request

HTTP 400type: invalid_request

The request could not be parsed: broken JSON, malformed multipart or inconsistent headers.

method_not_allowed

HTTP 405type: invalid_request

The method does not exist on that path. The response carries Allow.

resource_not_found

HTTP 404type: not_found

There is no such resource, or it is not your account's. Both answer the same on purpose: who owns which id is not disclosed.

http_error

HTTP 4xx / 5xxtype: invalid_request

An HTTP error without a code of its own. It keeps the original status instead of passing for a 500.

identity_provider_unavailable

HTTP 503type: api

The identity could not be verified against Google. It is our side or theirs, never yours: retry after Retry-After.

payment_provider_unavailable

HTTP 503type: api

Stripe did not answer or refused the operation. It is our side or theirs, never yours: retry after Retry-After. If it persists, the console keeps showing the last known state.

internal_error

HTTP 500type: api

Something broke on our side. It carries request_id: quote it if you write to support.

Of a failed reading

These are not HTTP errors: the request was accepted and the reading is what failed. They travel in Reading.error.code, and type is always processing.

unsupported_file_type

The file is not a PDF. It is the only format accepted, and it is recognised by its content, not by its name or extension.

file_too_large

The file exceeds the per-file size of the account's profile.

too_many_pages

The document has more pages than the profile allows to read.

unreadable_document

There is no invoice to read: either the PDF is damaged and could not be opened, or it opened and there is no legible invoice inside.

model_unavailable

The model provider did not answer. It is our side: the file can be uploaded again.

engine_error

The engine tried and failed. Ours, not yours.

never_started

No worker ever picked it up: it waited in the queue for too long and was given up before it started. It is capacity, not the engine.