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
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
The person's ID token is missing, expired or does not verify. It only concerns /admin, which is for people, not keys.
impersonation_ended
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
The account is suspended. What is already there can still be read; new readings are not accepted.
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
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
Your role in the account does not allow this action.
admin_role_required
Only an admin of the internal console can make changes there; viewers can only look.
second_factor_required
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
This action asks for a sign-in in the last 15 minutes: sign in again and repeat it.
no_account
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
There is no balance to pay for the reading. Only affects live mode.
concurrency_exceeded
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
The readings included for the month have run out.
daily_limit_exceeded
The account has reached its daily spending cap. It resets at midnight, Madrid time.
rate_limit_exceeded
Too many requests per minute. The response carries Retry-After and the X-RateLimit-* headers.
api_key_limit_reached
The account already has the maximum number of active keys. Revoke one before creating another.
member_limit_reached
The account already has the maximum number of people with access to /admin.
account_name_taken
There is already an account with that name. Pick another one; param is account_name.
email_not_allowed
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
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.
last_owner
The operation would leave the account without any owner. Appoint another one before demoting or removing the last.
subscription_exists
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
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
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
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
Feedback can only be given on a completed reading.
reading_not_settled
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
Somebody already resolved that review. The resolution says who and when.
export_not_ready
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
DELETE /api/admin/impersonation arrived without the X-Lince-Impersonation header, so there was no impersonation to end. Nothing was done.
access_request_closed
The access request is already registered or dismissed, so it can no longer be invited or dismissed. Nothing was done.
invitations_disabled
Invitations are turned off in this environment, so the link would not work. Nothing was sent.
email_already_member
The email of the access request already belongs to an account: add the person from that account instead. Nothing was sent.
export_expired
The export file is gone: exports are kept for 24 hours after they are ready. Ask for it again.
validation_failed
The body or the parameters do not meet the contract. param says which one.
payload_too_large
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
The request could not be parsed: broken JSON, malformed multipart or inconsistent headers.
method_not_allowed
The method does not exist on that path. The response carries Allow.
resource_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
An HTTP error without a code of its own. It keeps the original status instead of passing for a 500.
internal_error
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.
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.