Error codes
Every error response identifies its cause with a stable code. This page is the full inventory: 830 codes, of which 722 are emitted by the API and the rest are registered for translation.
The shape of the error document, and why branching happens on code rather than detail, are covered in the error contract.
Documented codes
Admin (internal operation)
Async terminal codes for validations
code | Status | When it fires | What the client should do |
|---|---|---|---|
bank_code_unresolvable_for_phone | 422 | No. | — |
banxico_error | 502 / 503 | No. | — |
intra_bank_no_cep | 422 | No. | — |
ocr_error | 502 | No. | — |
preflight_failed | 422 | No. | — |
Authentication and session
code | Status | When it fires | What the client should do |
|---|---|---|---|
account_deleted | 401 | The account was soft-deleted. | Contact support. |
account_suspended | 401 / 403 | The caller's account is suspended. | Contact support. |
api_key_decryption_failed | 401 | Cryptographic failure decrypting the API key. | Regenerate the key. |
auth_header_empty | 401 | The Authorization header is empty. | Attach Authorization: Bearer .... |
auth_method_denied | 403 | The endpoint does not accept the authentication method you arrived with. | Use the correct auth method — see Authentication. |
forbidden | 403 | Permission denied by RBAC. | Request the permission from your account admin. |
invalid_api_key | 401 | The API key prefix or format is invalid. | Regenerate the key from /usage or POST /v1/users/me/api-key/regenerate. |
invalid_credentials | 401 | Wrong email or password. | Show a generic message to the user — don't reveal which one failed. |
invalid_encrypted_api_key | 401 | The API key doesn't decrypt against the server-side secret (key rotation or a forged key). | Regenerate the key. |
registration_disabled | 403 | The global flag registration.enabled is OFF. | Wait until it's re-enabled. |
unauthorized | 401 | Missing, invalid, or expired credentials. | Authenticate again, or renew the API key. |
unrecognized_auth_format | 401 | The Authorization header doesn't parse as Bearer <token>. | Use Bearer veriko_..., with the API key. |
Beneficiaries
code | Status | When it fires | What the client should do |
|---|---|---|---|
account_number_invalid_type | — | account_number arrives as a type other than a string (a number, an array, …). | Send account_number as a string. |
account_number_required | — | Missing account_number in the body. | Add the field. |
beneficiary_already_registered | 422 | The account is already in your beneficiaries. | Reuse the existing one. |
beneficiary_not_found_for_account | 404 | There's no beneficiary linked to that account. | Create it. |
label_invalid_type | — | label arrives as a type other than a string (a number, an array, …). | Send label as a string. |
query_param_account_required | 400 | Missing ?account= in the query. | Add the parameter. |
Bulk imports (validations + beneficiaries)
code | Status | When it fires | What the client should do |
|---|---|---|---|
fecha_invalid | — | Date doesn't parse. | Fix it. |
field_too_long | 422 | When editing a row, parsed_clave_rastreo or parsed_referencia_numerica exceed 64 characters (the column width). | Shorten the value. |
file_required | 422 | The upload doesn't include a file. | Attach the file. |
job_not_editable | 422 | You're trying to edit a job in a terminal state. | The job was already committed. |
monto_invalid | — | Amount doesn't parse. | Fix it. |
multi_upload_not_allowed_for_text | 422 | Multi-select but the files are plain text. | Upload one by one or use images/ZIP. |
no_valid_fields | 422 | The edit payload has no valid fields. | Include at least one field. |
no_valid_test_files | 422 | No file in the upload is processable. | Check the set. |
row_persist_failed | 422 | An import row has a value that didn't fit its column even row-by-row (last-resort fallback); or, on a row PATCH, a combination of individually-valid lengths still doesn't fit. | Re-enter that row's account, key, amount, and date. |
zip_pack_failed | 422 | The repacking of an image ZIP failed. | Retry with a standard ZIP. |
Finance
code | Status | When it fires | What the client should do |
|---|---|---|---|
csv_stream_failed | 500 | The CSV stream failed. | Retry. |
invalid_export_format | 400 | Requested format outside json/csv/xlsx/pdf. | Pick a supported one. |
invalid_month | 400 | month param missing or not YYYY-MM. | Pass YYYY-MM. |
invalid_period | 400 | period param doesn't match the convention. | Fix it. |
invalid_range | 400 | from/to range incoherent. | Fix it. |
no_ceps | 404 | No CEPs available in the range. | Adjust the range. |
pdf_render_failed | 500 | dompdf failed to render. | Retry; report if it persists. |
range_required | 400 | Missing range or from/to. | Pass one. |
xlsx_render_failed | 500 | PhpSpreadsheet failed. | Retry. |
Generic field validation
code | Status | When it fires | What the client should do |
|---|---|---|---|
cuenta_y_candidatas_excluyentes | 422 | The request carries both cuenta_beneficiaria and cuentas_candidatas. | Send only one of the two: the account, or the candidate list. It consumes no quota. |
cuentas_candidatas_invalidas | 422 | cuentas_candidatas is not an array of text with 2 up to the current maximum of accounts, or one of them is not a valid CLABE, card or phone, or accounts are repeated. | Send from 2 up to the maximum in meta.max valid and distinct accounts, as text; field_errors points out the position that failed. It consumes no quota. |
image_invalid_format | 422 | The receipt is not JPEG, PNG, WebP, or PDF, or PDF is disabled. | Convert to JPEG/PNG or send the original PDF. |
image_too_large | 422 | Image over the size cap. | Reduce the size. |
invalid_account_format | 400 | The account number isn't CLABE 18 / card 16 / phone E.164. | Fix it per account_type. |
invalid_account_length | 422 | Wrong length for the type (18 CLABE / 16 card / 10 phone). | Adjust the length. |
invalid_amount | — | Amount isn't valid as a positive decimal. | Fix it. |
invalid_bank_code | 422 | The bank code doesn't exist in the catalog. | Use GET /v1/public/banks. |
invalid_card_luhn | — | The card's Luhn check fails. | Verify the PAN. |
invalid_clabe_checksum | — | The CLABE check digit fails. | Verify the CLABE. |
invalid_client_ref | 422 | client_ref is not text of 1 to 64 characters, or it carries line breaks, control characters, or emoji. | Send text of 1 to 64 characters without line breaks or emoji, or remove the field. It consumes no quota. |
invalid_email | 422 | The email isn't valid. | Fix it. |
invalid_field_type | 422 | A field that must be text arrived as an array or object (e.g. emisor, receptor, referencia_numerica, or a field in a bulk-import row correction). | Send the field as a text string. |
invalid_format | 422 | The field doesn't match the expected format. | Fix the format. |
invalid_image | — | The image isn't decodable. | Resend. |
invalid_image_format | — | Format outside JPEG/PNG/WEBP/PDF. | Convert to JPEG/PNG or send the original PDF. |
invalid_receptor_participante | 422 | receptor_participante is neither 0 nor 1. | Send 0 (account holder) or 1 (payment to bank), or omit it for the default. |
invalid_request_body | 422 | The JSON isn't valid. | Send valid JSON. |
invalid_url | — | The URL is malformed. | Fix it. |
invalid_url_scheme | 422 | Only https accepted. | Use https://. |
invalid_uuid | — | Not a UUID v4. | Pass a valid UUID. |
invalid_value | 422 | The value is outside the allowed set. | Use a value from the enum. |
max_length_exceeded | — | Exceeds the field's max length. | Shorten it. |
message_build_failed | 422 | The server couldn't assemble the message to respond with. | Retry. |
missing_field | 422 | Variant of required for specific fields. | Include the field. |
pdf_active_content | 422 | The PDF carries active content: JavaScript, automatic actions, attached files, XFA forms, or annotations that are not links. | Send the original receipt from the bank, unedited. |
pdf_encrypted | 422 | The PDF is encrypted or password-protected. | Send a copy without a password. |
pdf_hidden_content | 422 | The PDF carries hidden content: optional layers, forms, or text outside the visible area of the page. | Send the original receipt from the bank, unedited. |
pdf_invalid_structure | 422 | The PDF cannot be read: it is damaged, carries data after the end of the document, or exceeds the object or nesting caps. | Download the receipt again and resend it. |
pdf_modified_after_issue | 422 | The PDF has more than one revision: it was modified after being issued. | Send the receipt as the bank issued it. |
pdf_text_layer_too_large | 422 | The PDF text layer exceeds the character cap per page or per document. | Send only the receipt page. |
pdf_too_many_pages | 422 | The PDF has no pages or more than 3. | Send only the receipt pages. |
pdf_unsupported_image | 422 | The PDF carries a JBIG2 image or an image over 60 megapixels. | Send the receipt as a JPEG or PNG image. |
spei_calendar_year_invalid | 422 | The year in the path does not have four digits. | Send the year with four digits, for example 2026. |
url_dns_failed | 400 | DNS didn't resolve the host. | Verify the host. |
url_ssrf_blocked | 400 | The URL points to a private IP / DNS rebind. | Use a public host. |
validation_error | 422 | Generic validation error. | Check source.pointer and meta. |
validation_failed | 422 | Variant for combined failures. | Check the detail. |
Generic resources
code | Status | When it fires | What the client should do |
|---|---|---|---|
cep_not_available | 404 / 409 | The validation's CEP isn't available yet. | Retry later. |
changelog_empty | — | No changelog published. | Wait for publication. |
changelog_not_found | — | The requested version doesn't exist. | List with GET /v1/public/changelog |
dispatch_failed | 424 / 500 / 503 | The job couldn't be dispatched to the worker. | Retry. |
image_not_available | 404 | The original image isn't accessible. | Re-upload (if applicable). |
internal_error | 500 | Unexpected failure. | Retry with backoff. |
key_not_available | 404 / 409 | The user's API key isn't available to display. | Regenerate. |
method_not_allowed | 405 | HTTP method not supported for that path. | Use one of the allowed ones. |
not_found | 404 | The requested resource doesn't exist or isn't visible. | Verify the id. |
spei_calendar_year_not_covered | 404 | The year has no SPEI non-business-day calendar. | Use one of the years in meta.covered_years. |
user_not_found | 401 / 404 | The referenced user doesn't exist. | Verify the id. |
Idempotency
code | Status | When it fires | What the client should do |
|---|---|---|---|
idempotency_key_in_progress | 409 | There's another in-flight request with the same key. | Wait Retry-After seconds and retry. |
idempotency_key_reused | 422 | The same key was used before with a different body. | Generate a new key or reuse the exact body. |
invalid_idempotency_key | 400 | The Idempotency-Key header doesn't meet the format [A-Za-z0-9_-]{1,255}. | Generate a new key with valid characters. |
OTP, 2FA, and verification
code | Status | When it fires | What the client should do |
|---|---|---|---|
confirmation_token_already_used | 409 | The token was already consumed (single-use). | Re-request a new one. |
confirmation_token_invalid | 422 | Malformed confirmation token. | Re-request the token. |
confirmation_token_malformed | 400 | Variant: the token doesn't have the expected structure. | Re-request. |
confirmation_token_mismatch | 422 | The token corresponds to a different action. | Re-request for the correct action. |
confirmation_token_missing | 422 | The confirmation_token is missing in a step-up operation. | Add confirmation_token. |
confirmation_token_slug_mismatch | 422 | The token was issued for a different plan/slug. | Re-issue it for the correct slug. |
free_plan_already_claimed | 409 | The free plan has already been claimed by this account. | Continue with the normal flow; there is nothing to claim. |
invalid_intent | 422 | intent on POST /v1/users/me/phone/confirm-verify is not verify or claim. | Send one of those two values, or omit the field (defaults to verify). |
invalid_otp_parameters | 422 | The OTP payload is incomplete. | Check the required fields. |
invalid_reset_context | 400 | The reset context (purpose, audience, expiry) doesn't match. | Restart the flow. |
invalid_verification_token | 400 | The token of a verification flow is invalid or malformed. | Restart the verification flow. |
missing_otp_id | 400 | The otp_id is missing from the body. | Add otp_id. |
otp_already_used | 400 | The OTP was already consumed. | Request another one. |
otp_expired | 400 | The OTP expired before being used. | Re-request an OTP. |
otp_invalid_code | 400 | The submitted OTP code is wrong. | Re-enter it (maximum N attempts). |
otp_max_attempts | 400 | Attempts for that OTP were exhausted. | Request a brand-new OTP. |
otp_not_found | 404 | There's no active OTP for that user+purpose combination. | Re-request an OTP. |
phone_already_verified | 422 | The phone is already verified — there's nothing to do. | Continue with the normal flow. |
phone_not_verified | — | The phone is not verified. No longer raised by login (v1.58.0): signing in does not require a verified phone. | Verify with POST /v1/users/me/phone/request-verify. |
phone_verification_required | 409 / 422 | The action requires a verified phone and the account has none. meta.masked_phone shows where the code will be sent (null when no phone is on file) and meta.needs_phone whether one must be collected first. | Open the verification flow (POST /v1/users/me/phone/request-verify) and retry. |
purpose_mismatch | 400 | The OTP was generated for a different purpose (e.g. login vs. password reset). | Request an OTP with the correct purpose. |
twofa_action_mismatch | 400 | The resolved challenge doesn't correspond to the requested action. | Restart the step-up. |
twofa_already_disabled | 422 | A 2FA disable was requested but it's already disabled. | Ignore — state is correct. |
twofa_already_enabled | 422 | A 2FA enable was requested but it's already enabled. | Ignore — state is correct. |
twofa_invalid_challenge | 400 | The 2FA challenge code is wrong. | Re-enter it. |
twofa_invalid_context | 400 | The 2FA context (purpose / audience) doesn't match. | Restart the flow. |
twofa_method_same | 422 | A change to a 2FA method equal to the current one was requested. | Pick a different method. |
twofa_method_unsupported | 422 | The requested 2FA method isn't supported. | Use sms or email. |
twofa_not_enabled | 422 | You tried to verify 2FA but the user doesn't have it on. | Enable 2FA first. |
twofa_required | 401 | The user has 2FA on — you need to solve the challenge. | Trigger POST /v1/auth/2fa/verify-challenge. |
Plan and billing
code | Status | When it fires | What the client should do |
|---|---|---|---|
activation_operation_mismatch | 422 | operation_id on POST /v1/users/me/phone/confirm-verify (intent=claim) belongs to another account, or to a different intent. | Generate a new operation_id (UUID) for this attempt. |
activation_prompt_not_reached | 422 | POST /v1/users/me/activation/prompts with action=presented for a level the server does not yet confirm as reached. | Check GET /v1/users/me/activation and use its pending_prompt. |
admin_grant_failed | 422 | The admin-side plan grant failed. | Check the detail. |
billing_disabled | 503 | The billing module is disabled in this deploy. | Wait until it's enabled. |
billing_invalid_interval | 422 | The interval isn't month or year. | Use an allowed one. |
billing_invalid_kind | 422 | The price kind isn't base or metered. | Use an allowed one. |
billing_plan_is_free | 422 | You're trying to subscribe to a free plan via Stripe checkout. | The free plan is assigned without Stripe. |
billing_plan_not_found | 404 | Variant: the slug doesn't resolve to an active plan. | Check the slug. |
billing_plan_not_self_service | 403 | Plan not assignable via self-service. | Contact support. |
billing_plan_slug_invalid | 422 | The slug doesn't meet ^[a-z0-9-]+$. | Fix it. |
billing_plan_slug_required | 422 | Missing plan_slug in the body. | Add the field. |
billing_plan_slug_too_long | 422 | The slug exceeds the max. | Shorten it. |
comp_amount_invalid | 422 | Invalid compensation amount. | Fix it. |
comp_user_missing | 422 | Target user missing in comp. | Add it. |
comp_user_not_found | 404 | The comp user doesn't exist. | Verify. |
invalid_activation_prompt_action | 422 | action on POST /v1/users/me/activation/prompts is not presented, dismissed, or cta. | Send one of those three values. |
invalid_activation_prompt_level | 422 | level on POST /v1/users/me/activation/prompts is not one_left, exhausted, or blocked. | Send one of those three values. |
no_active_subscription | 404 | The user has no active subscription. | Start checkout. |
overage_not_applicable | 422 | The current plan doesn't support overage. | Upgrade the plan. |
overage_update_failed | 422 | The overage toggle failed. | Retry. |
plan_not_found | 404 | The referenced plan doesn't exist. | List plans with GET /v1/plans/public. |
price_already_in_catalog | 409 | The stripe_price_id is already used by another price. | Reuse the existing one. |
price_combo_already_exists | 409 / 422 | Duplicate combination (plan, interval, currency, kind). | Edit the existing one. |
price_local_id_required | 422 | Missing price_local_id. | Add it. |
price_not_active | 422 | The price is archived. | Activate it first. |
price_not_found | 404 | The local price doesn't exist. | Verify the ID. |
price_plan_mismatch | 422 | The referenced price doesn't belong to that plan. | Use the correct plan. |
refund_amount_invalid | 422 | Invalid refund amount (negative or > invoice). | Fix it. |
refund_invoice_not_found | 404 | The referenced invoice doesn't exist in Stripe. | Verify the invoice_id. |
source_price_id_required | 422 | Missing source_price_id in migrate. | Add it. |
stripe_cancel_failed | 502 | Stripe rejected the cancel. | Retry. |
stripe_checkout_failed | 502 | Stripe rejected the session creation. | Retry. |
stripe_invoice_malformed | 500 | The Stripe invoice arrived incomplete in the webhook. | (logged and resync). |
stripe_meter_lookup_failed | 502 | Stripe meter lookup failed. | Retry. |
stripe_meter_missing | 422 / 500 | The expected meter doesn't exist in Stripe. | Create the meter or disable metered. |
stripe_price_archive_failed | 502 | Stripe rejected archiving the price. | Retry. |
stripe_price_id_format_invalid | 422 | The stripe_price_id doesn't match price_*. | Fix it. |
stripe_price_id_required | 422 | Missing stripe_price_id. | Add it. |
stripe_price_not_found | 404 | The stripe_price_id doesn't exist in Stripe. | Verify the ID. |
stripe_product_create_failed | 502 | Product creation in Stripe failed. | Retry. |
stripe_subscription_malformed | 500 | The Stripe subscription arrived incomplete. | (logged and resync). |
stripe_unreachable | 502 | Stripe API timeout/connection error. | Retry. |
subscription_not_found | 409 | The subscription doesn't exist. | Verify the user_id. |
subscription_race_retry | 409 | Race condition mutating the subscription — the client must retry. | Retry after 1-2s. |
unit_amount_required | 422 | Missing unit_amount. | Add it. |
Profile
code | Status | When it fires | What the client should do |
|---|---|---|---|
language_invalid_type | — | language arrives as a type other than a string. | Send language as a string. |
name_empty | — | name is empty after sanitization (strip_tags + trim). | Send a non-empty name. |
name_invalid_type | — | name arrives as a type other than a string. | Send name as a string. |
name_too_long | — | name exceeds the 100-character column limit. | Shorten the name. |
timezone_invalid_type | — | timezone arrives as a type other than a string. | Send timezone as a string. |
timezone_unsupported | — | timezone is not a supported IANA identifier. | Send a supported IANA identifier. |
Rate limit
code | Status | When it fires | What the client should do |
|---|---|---|---|
rate_limit_exceeded | 429 | Variant for internal buckets (e.g. login). | Wait and retry. |
Registration and account
code | Status | When it fires | What the client should do |
|---|---|---|---|
current_password_incorrect | 422 | The current_password doesn't match. | Re-enter it correctly. |
current_password_required | 422 | The current_password is missing in a password change. | Add the field. |
email_already_registered | 422 | The email already has a verified account. | Show a generic anti-enum message. |
email_already_taken | 422 | Variant: the email isn't free. | Ask for another email. |
email_already_verified | 422 | The email is already verified. | Continue with the normal flow. |
email_delivery_failed | — | The email provider rejected the send. | Retry; if it persists, support. |
email_same_as_current | 422 | The new email matches the current one. | Enter a different one. |
invalid_email_change_context | 400 | The email-change context isn't valid (purpose mismatch). | Restart the flow. |
language_unsupported | — | Variant of unsupported_locale. | Use es or en. |
new_password_too_short | 422 | Variant: on a password change, the new one is too short. | Use more characters. |
password_mismatch | 422 | password and password_confirmation don't match. | Re-enter matching values. |
password_too_short | — | The password doesn't meet the minimum length. | Use a longer password. |
password_too_weak | 422 | The password doesn't meet the complexity rules. | Strengthen the password. |
phone_required_for_email_change | 422 | You need a verified phone before changing email. | Verify the phone first. |
phone_taken | — | The phone is already on another verified account. | Ask for another phone. |
sms_delivery_failed | — | The SMS provider rejected the OTP send. | Retry; if it persists, support. |
turnstile_failed | 422 | With the captcha active, turnstile_token is missing or Cloudflare Turnstile did not confirm it. | Solve the captcha again and resend with the new token. |
unsupported_locale | 422 | The submitted locale isn't on the whitelist. | Use es or en. |
SPEI transfer validation
code | Status | When it fires | What the client should do |
|---|---|---|---|
bank_code_required_for_phone | 422 | For account_type=phone an explicit bank_code is required. | Add bank_code. |
clabe_prefix_not_recognized | — | The first 3 digits of the CLABE don't match any SPEI participant bank. | Verify the CLABE — it may not be SPEI. |
clave_or_ref_required | 422 | Either clave_rastreo or referencia_numerica is required. | Include one. |
image_not_readable | 422 | For image validations (OCR): OCR couldn't read the image. | Attach a clearer image. |
image_not_readable_receipt | 422 | For image validations (OCR): OCR read it but it doesn't look like an SPEI receipt. | Attach the correct receipt. |
image_not_retained | 410 | GET /v1/validations/{id}/image on a validation created with retain_image=false: the receipt file is deleted when the validation ends and is never served. | Do not retry: the file does not exist by the client's decision. Keep the receipt in your own system before sending it, or send retain_image=true (the default) if it needs to be retrieved. |
image_not_spei_receipt | 422 | For image validations (OCR): the receipt isn't SPEI (another transfer type). | Attach an SPEI receipt. |
image_or_image_url_required | 422 | For image validations (OCR): neither image nor image_url was provided. | Send one. |
invalid_retain_image | 422 | POST /v1/validate-ocr with a retain_image that is not a boolean. It is rejected before any quota is consumed. | Send true or false (0, 1, and the strings "true" and "false" are also accepted). An ambiguous value is never read as true. |
pdf_multiple_receipts | 422 | The PDF contains more than one receipt. It is charged: the file was already read. | Send each receipt separately. |
purge_token_mismatch | 422 | POST /v1/validations/{id}/purge/execute with a token that is not for this validation or that was issued for another account. | Prepare the deletion again with POST /v1/validations/{id}/purge/prepare for this validation and use the token it returns. The wrong token is not spent. |
purge_validation_in_progress | 409 | A purge was requested for a validation that is still in progress (queued or processing); meta.status carries the status. | Wait for the validation to reach a terminal status (GET /v1/validations/{id}) and prepare the deletion again. An open retry cycle does not prevent it: the deletion cancels it. |
recheck_not_eligible | 422 | POST /v1/validations/{id}/recheck on a validation whose status is neither valid nor returned; meta.status carries the status. A returned one does not give this error: it answers its current state with 200. | There is nothing to query again: only a valid is rechecked. Read the current state with GET /v1/validations/{id}. It consumes no quota. |
recheck_rate_limited | 429 | The same validation was queried with POST /v1/validations/{id}/recheck less than 10 minutes ago; Retry-After and meta.retry_after carry the seconds left. | Wait Retry-After seconds. The result of the previous query is already in GET /v1/validations/{id}. It consumes no quota. |
recheck_unavailable | 503 | Banxico did not return a readable payment status (captcha, query cap, network, or an unrecognized response), or the status query is switched off. It says nothing about the transfer. | Retry after Retry-After seconds; the validation's interval was not spent. It consumes no quota. |
recheck_window_expired | 422 | POST /v1/validations/{id}/recheck on a valid validation older than the window; meta.window_hours carries the current window (72 by default). | Its payment status can no longer be queried again; to confirm an old payment, create a new validation, which does consume quota. The rejection consumes no quota. |
validation_purged | 410 | The image, the CEP, the retries, the follow-up check, or the deletion was requested for a validation that was already purged. GET /v1/validations/{id} does respond: it returns the tombstone with purged_at. | Do not retry: what was purged does not exist. For the verdict, the dates, and the amount, read the tombstone with GET /v1/validations/{id}. |
Webhooks and notifications
code | Status | When it fires | What the client should do |
|---|---|---|---|
invalid_notification_id | 422 | The id isn't a UUID. | Fix it. |
notification_not_found | 404 | Referenced notification doesn't exist. | Verify the id. |
notifications_preferences_empty | 422 | The body carries no preferences. | Add at least one. |
push_fcm_token_invalid | 422 | The FCM token isn't a valid format. | Fetch the token again from the Firebase SDK. |
push_fcm_token_required | 422 | Missing token (FCM) in the body. | Add it. |
push_not_configured | 503 | The server has neither VAPID nor FCM configured. | Support. |
push_subscription_endpoint_not_https | 422 | Endpoint isn't HTTPS. | Verify the provider. |
push_subscription_endpoint_required | 422 | Missing endpoint. | Add it. |
push_subscription_endpoint_too_long | 422 | Endpoint exceeds the max. | (provider issue). |
push_subscription_invalid_shape | 422 | The PushSubscription object is invalid. | Re-subscribe from the SW. |
push_subscription_none_active | 422 | You have no active push subscriptions. | Subscribe first. |
quiet_hours_invalid_timezone | 422 | The timezone doesn't exist. | Use an IANA TZ. |
quiet_hours_minutes_out_of_range | 422 | Minutes outside [0, 1440]. | Fix it. |
telegram_bot_not_configured | 503 | The Telegram bot isn't configured server-side. | Support. |
webhook_description_invalid_type | — | description arrives as a type other than a string. | Send description as a string. |
webhook_description_too_long | — | description exceeds 255 characters. It used to be silently truncated. | Shorten the description. |
webhook_event_invalid | 422 | Event outside the registry. | See events in the docs. |
webhook_events_required | — | Missing the events array. | Add at least one. |
webhook_events_too_many | — | More events than the max. | Reduce them. |
webhook_limit_reached | 422 | Plan webhook cap reached. | Upgrade the plan or delete one. |
webhook_status_invalid | — | status isn't active/disabled. | Fix it. |
webhook_url_empty | — | url sent but empty. | Add a real URL. |
webhook_url_invalid_format | — | url doesn't parse. | Fix it. |
webhook_url_invalid_type | — | url arrives as a type other than a string. | Send url as a string. |
webhook_url_not_https | — | The scheme isn't https. | Use HTTPS. |
webhook_url_required | 422 | Missing url. | Add it. |
webhook_url_too_long | — | url exceeds 2048 chars. | Shorten it. |
Codes without a description
The API can emit these 445 codes, and they have no description yet. They are listed with their HTTP status so an integration can at least classify them.
code | Status |
|---|---|
admin_self_delete_not_allowed | 403 |
admin_self_restore_not_allowed | 403 |
already_blocked | 409 |
already_canceling | 409 |
analytics_not_configured | 409 |
analytics_tabla_not_found | 404 |
analytics_upstream_error | 502 |
audience_required | 422 |
audience_too_many | 422 |
audience_value_too_long | 422 |
bank_conflicts_with_confirmed | 422 |
banxico_check_cooldown | 429 |
banxico_sync_failed | 502 |
beneficiary_already_exists | 409 |
billing_already_on_plan | 409 |
billing_already_subscribed | 409 |
billing_change_not_applicable | 422 |
billing_interval_invalid | 422 |
billing_invalid_currency | 422 |
billing_no_customer | 422 |
billing_orphan_customer | 500 |
billing_overage_price_missing | 500 |
billing_plan_change_failed | 502 |
billing_plan_unresolvable | 500 |
billing_price_not_found | 422 |
billing_schedule_malformed | 502 |
billing_use_cancel_for_free | 422 |
bin_invalid | 422 |
bin_not_found | 404 |
body_empty | 400 |
body_too_large | 413 |
bot_custom_command_too_many | 422 |
bot_custom_command_trigger_reserved | 409 |
bot_custom_command_trigger_taken | 409 |
bot_system_command_trigger_reserved | 409 |
broadcast_already_active | 409 |
broadcast_audience_empty | 422 |
broadcast_audience_too_large | 422 |
broadcast_invalid_user_ids | 422 |
broadcast_message_empty | 422 |
broadcast_message_too_long | 422 |
broadcast_not_cancelable | 409 |
broadcast_not_dispatchable | 409 |
broadcast_rate_limited | 429 |
bulk_too_many | 400 |
campaign_not_found | 404 |
campaign_test_owner_only | 403 |
cannot_cancel | 409 |
cannot_modify_role_permissions | 422 |
cannot_remove_critical_permission | 422 |
cannot_restore_self | 422 |
category_too_many | 422 |
category_value_too_long | 422 |
changelog_registry_error | 500 |
channels_required | 422 |
checkout_recovery_unavailable | 404 |
ci_key_invalid | 401 |
ci_webhook_not_stored | 503 |
ci_webhook_signature_invalid | 401 |
ci_webhook_unavailable | 503 |
cloudflare_not_configured | 409 |
comp_cap_not_configured | 500 |
comp_currency_invalid | 422 |
comp_daily_cap_exceeded | 429 |
comp_lock_contention | 503 |
comp_reason_invalid | 422 |
comp_user_no_customer | 422 |
compare_runs_must_differ | 422 |
confirm_required | 422 |
control_unavailable | 409 |
create_rate_limited | 429 |
date_range_too_large | 422 |
delivery_content_not_stored | 404 |
deploy_key_already_revoked | 409 |
deploy_key_input_invalid | 422 |
deploy_key_invalid | 401 |
deploy_key_issue_failed | 500 |
deploy_key_not_found | 404 |
deploy_key_not_revealable | 409 |
deploy_key_reveal_forbidden | 403 |
deploy_scope_denied | 403 |
device_credential_id_required | 422 |
device_credential_not_found | 404 |
device_credential_reauth_required | 422 |
docs_site_missing | 503 |
email_change_confirm_mismatch | 422 |
email_change_confirm_taken | 422 |
email_change_confirm_token_invalid | 422 |
email_change_confirm_token_required | 422 |
email_change_confirm_token_used | 422 |
email_change_no_pending | 422 |
email_taken | 422 |
email_verify_email_mismatch | 422 |
email_verify_token_invalid | 422 |
email_verify_token_required | 422 |
email_verify_token_used | 422 |
email_verify_unavailable_for_placeholder | 422 |
entry_ids_required | 422 |
event_not_broadcast_safe | 422 |
event_type_required | 422 |
event_type_too_long | 422 |
filter_invalid | 422 |
github_app_not_configured | 503 |
golden_case_not_found | 422 |
golden_not_available | 422 |
health_check_not_found | 404 |
hop_not_found | 404 |
identity_not_found | 404 |
image_decompression_bomb | 422 |
image_dimensions_too_large | 422 |
image_invalid | 422 |
image_mime_mismatch | 422 |
image_polyglot_detected | 422 |
image_strip_failed | 422 |
image_too_small | 422 |
import_failed | 500 |
invalid_account | 422 |
invalid_account_type | 422 |
invalid_audience | 400 / 422 |
invalid_audience_filter | 422 |
invalid_audience_kind | 422 |
invalid_audience_override | 422 |
invalid_audience_value | 422 |
invalid_block_reason | 422 |
invalid_bot_user_id | 422 |
invalid_broadcast_id | 422 |
invalid_broadcast_language | 422 |
invalid_broadcast_segment | 422 |
invalid_campaign_step | 422 |
invalid_campaign_toggle | 422 |
invalid_category | 400 |
invalid_category_value | 422 |
invalid_channel | 422 |
invalid_channel_value | 422 |
invalid_channels | 422 |
invalid_channels_override | 422 |
invalid_custom_command_id | 422 |
invalid_custom_command_response | 422 |
invalid_custom_command_trigger | 422 |
invalid_date_filter | 422 |
invalid_date_format | 422 |
invalid_date_range | 422 |
invalid_datetime | 422 |
invalid_device_credential | 401 |
invalid_enabled | 422 |
invalid_event_type | 422 |
invalid_except_value | 422 |
invalid_expected_banxico_status | 422 |
invalid_filter | 422 |
invalid_identity | 422 |
invalid_identity_value | 422 |
invalid_impact_level | 422 |
invalid_include | 400 |
invalid_json | 400 |
invalid_lang | 400 |
invalid_limit | 400 |
invalid_page_by | 400 |
invalid_path | 422 |
invalid_payload_value | 422 |
invalid_permission_action | 422 |
invalid_plan | 422 |
invalid_proxy_request | 422 |
invalid_remember | 422 |
invalid_reorder | 422 |
invalid_role | 422 |
invalid_session_id | 422 |
invalid_setting_value | 422 |
invalid_settings | 422 |
invalid_severity | 422 |
invalid_status | 400 / 422 |
invalid_system_command_description | 422 |
invalid_system_command_id | 422 |
invalid_system_command_trigger | 422 |
invalid_telegram_token | 422 |
invalid_timestamp | 400 |
invalid_user_id_filter | 422 |
invalid_webhook_url | 422 |
last_auth_method | 409 |
legal_consent_required | 422 |
lockout_unavailable | 503 |
malformed_payload | 400 |
migration_bootstrap_missing | 500 |
migration_drift_conflict | 409 |
migration_file_missing | 404 |
migration_filename_format | 422 |
migration_filename_required | 422 |
migration_filenames_must_be_array | 422 |
migration_lock_held | 409 |
migration_mark_bulk_limit | 422 |
migration_not_found | 404 |
migration_target_invalid_type | 422 |
migration_target_version_format | 422 |
missing_jti | 401 |
missing_param | 400 |
missing_required_payload_var | 422 |
missing_required_var | 422 |
no_active_grant | 409 |
no_api_key | 404 |
no_failed_files | 404 |
no_matching_entries | 422 |
not_blocked | 409 |
not_canceling | 409 |
not_linked | 409 |
not_stripe_subscription | 422 |
notifications_preferences_invalid | 422 |
oauth_missing_handoff | 400 |
oauth_no_pending_flow | 404 |
oauth_provider_unavailable | 404 |
ocr_not_configured | 502 / 503 |
ocr_settings_acknowledge_required | 422 |
ocr_settings_revision_not_found | 404 |
only_owner_can_assign_owner | 422 |
only_owner_can_create_owner | 422 |
only_owner_can_delete_owner | 422 |
only_owner_can_modify_owner | 422 |
only_owner_can_restore_owner | 422 |
only_owner_can_suspend_admin | 422 |
openapi_spec_parse_failed | 500 |
owner_only_action | 403 |
password_already_set | 409 |
password_not_set | 422 |
path_not_allowed | 403 |
permission_actions_must_be_array | 422 |
phone_required | 422 |
phone_unavailable | 409 |
plan_api_rate_per_min_invalid | 422 |
plan_beneficiaries_max_invalid | 422 |
plan_billing_model_change_blocked | 422 |
plan_billing_model_invalid | 422 |
plan_bulk_validations_max_negative | 422 |
plan_cap_exceeded | 422 |
plan_comparison_invalid_shape | 422 |
plan_create_post_commit_inconsistent | 500 |
plan_create_stripe_price_failed | 502 |
plan_create_stripe_product_failed | 502 |
plan_currency_invalid | 422 |
plan_delete_has_active_subs | 409 |
plan_duplicate_same_slug | 422 |
plan_feature_icon_invalid | 422 |
plan_feature_text_required | 422 |
plan_feature_text_too_long | 422 |
plan_features_invalid_shape | 422 |
plan_features_too_many | 422 |
plan_free_cannot_have_initial_prices | 422 |
plan_free_cannot_have_stripe_product | 422 |
plan_included_exceeds_limit | 422 |
plan_included_validations_negative | 422 |
plan_limit_negative | 422 |
plan_name_required | 422 |
plan_name_too_long | 422 |
plan_price_edit_noop | 422 |
plan_price_migrate_invalid_proration | 422 |
plan_price_migrate_source_format_invalid | 422 |
plan_price_migrate_source_not_archived | 422 |
plan_price_migrate_source_not_found | 404 |
plan_price_migrate_source_product_mismatch | 422 |
plan_price_migrate_source_retrieve_failed | 502 |
plan_price_migrate_source_same_as_target | 422 |
plan_price_not_active | 422 |
plan_price_not_found | 404 |
plan_price_out_of_range | 422 |
plan_price_slug_mismatch | 422 |
plan_retry_max_dispatched_out_of_range | 422 |
plan_retry_max_pending_out_of_range | 422 |
plan_retry_max_retries_out_of_range | 422 |
plan_slug_already_exists | 422 |
plan_slug_format_invalid | 422 |
plan_slug_invalid | 422 |
plan_slug_required | 422 |
plan_sms_2fa_monthly_cap_negative | 422 |
plan_sort_order_negative | 422 |
plan_stale_prepare | 422 |
plan_stripe_product_missing | 422 |
plan_tax_behavior_invalid | 422 |
plan_trial_days_out_of_range | 422 |
plan_update_post_commit_inconsistent | 500 |
plan_update_stripe_price_failed | 502 |
plan_update_stripe_product_failed | 502 |
plan_webhook_per_host_per_min_invalid | 422 |
platform_disabled | 404 |
png_missing | 404 |
preview_unavailable | 404 |
price_archive_has_active_subs | 409 |
price_create_race_unrecoverable | 500 |
processing_failed | 500 |
proxy_upstream_error | 502 |
push_subscription_endpoint_conflict | 409 |
queue_unavailable | 503 |
queues_batch_failed | 500 |
queues_batches_failed | 500 |
queues_cancel_failed | 500 |
queues_cancel_prepare_failed | 500 |
queues_config_failed | 500 |
queues_config_reset_failed | 500 |
queues_config_update_failed | 500 |
queues_discard_failed | 500 |
queues_discard_prepare_failed | 500 |
queues_dlq_entry_failed | 500 |
queues_dlq_failed | 500 |
queues_job_failed | 500 |
queues_jobs_failed | 500 |
queues_overview_failed | 500 |
queues_pause_failed | 500 |
queues_restart_failed | 500 |
queues_restart_prepare_failed | 500 |
queues_resume_failed | 500 |
queues_retry_failed | 500 |
queues_retry_prepare_failed | 500 |
queues_start_failed | 500 |
queues_states_failed | 500 |
queues_stats_failed | 500 |
queues_stop_failed | 500 |
queues_worker_failed | 500 |
queues_workers_failed | 500 |
rate_limited_billing_portal | 429 |
rate_limited_email_flow | 429 |
rate_limited_login | 429 |
rate_limited_oauth | 429 |
rate_limited_otp | 429 |
rate_limited_password_reset | 429 |
rate_limited_register | 429 |
rate_limited_twofa | 429 |
reactivation_cap_exceeded | 422 |
rebuild_request_failed | 503 |
refund_amount_exceeds_refundable | 422 |
refund_cap_not_configured | 500 |
refund_currency_mismatch | 422 |
refund_daily_cap_exceeded | 429 |
refund_invoice_not_paid | 422 |
refund_lock_contention | 503 |
refund_no_charge | 422 |
release_not_found | 404 |
restore_token_expired | 422 |
restore_token_invalid | 422 |
restore_token_required | 422 |
restore_token_used | 422 |
retry_age_exceeded | 422 |
retry_already_resolved | 422 |
retry_not_active | 422 |
retry_not_applicable | 422 |
retry_not_supported_for_bulk | 422 |
retry_pending_cap_exceeded | 422 |
role_has_no_permissions | 403 |
rollback_no_down | 400 |
rotate_rate_limited | 429 |
scheduled_for_required | 422 |
scheduled_task_create_failed | 500 |
scheduled_task_delete_failed | 500 |
scheduled_task_delete_prepare_failed | 500 |
scheduled_task_detail_failed | 500 |
scheduled_task_execution_detail_failed | 500 |
scheduled_task_executions_failed | 500 |
scheduled_task_run_now_failed | 500 |
scheduled_task_update_failed | 500 |
scheduled_too_far | 422 |
scheduled_too_soon | 422 |
search_too_long | 422 |
seeder_bulk_limit | 422 |
seeder_filename_format | 422 |
seeder_filename_required | 422 |
seeder_invalid | 500 |
seeder_not_found | 404 |
service_unavailable | 503 |
session_expired | 401 |
session_not_found_or_already_revoked | 404 |
session_revoked | 401 |
session_unknown | 401 |
simulation_failed | 500 |
stale_draft | 409 |
stripe_account_check_misconfigured | 500 |
stripe_comp_failed | 502 |
stripe_customer_create_failed | 502 |
stripe_customer_persist_failed | 500 |
stripe_customer_update_failed | 502 |
stripe_event_malformed | 400 |
stripe_foreign_account | 400 |
stripe_invalid_mode | 500 |
stripe_portal_failed | 502 |
stripe_price_archive_divergent | 502 |
stripe_price_create_failed | 502 |
stripe_price_orphaned_post_create | 500 |
stripe_price_orphaned_post_edit | 500 |
stripe_price_product_mismatch | 422 |
stripe_price_shape_incompatible | 422 |
stripe_refresh_failed | 502 |
stripe_refund_failed | 502 |
stripe_resume_failed | 502 |
stripe_secret_missing | 500 |
stripe_secret_placeholder | 500 |
stripe_secret_too_short | 500 |
stripe_signature_invalid | 401 |
stripe_signature_malformed | 401 |
stripe_signature_missing | 401 |
stripe_signature_no_secrets | 500 |
stripe_signature_timestamp_skew | 401 |
stripe_subs_list_failed | 502 |
stripe_subscription_fetch_failed | 502 |
stripe_unavailable | 503 |
stripe_upcoming_failed | 502 |
stripe_webhook_endpoint_ambiguous | 409 |
stripe_webhook_endpoint_not_found | 404 |
subject_override_invalid | 422 |
subject_override_too_long | 422 |
subscriber_limit_reached | 422 |
subscription_not_cancelable | 422 |
subscription_not_resumable | 422 |
subscription_sync_failed | 500 |
sync_too_many_prices | 422 |
telegram_bot_token_missing | 422 |
telegram_identity_update_failed | 502 |
telegram_not_linked | 409 |
telegram_test_send_failed | 502 |
telegram_token_persist_failed | 500 |
telegram_token_verification_failed | 422 |
telegram_user_not_linked | 422 |
telegram_webhook_secret_missing | 422 |
telegram_webhook_set_failed | 502 |
telegram_webhook_url_not_https | 422 |
telegram_webhook_url_unresolvable | 422 |
test_file_not_found | 404 |
test_filename_format | 422 |
test_files_limit | 422 |
test_files_must_be_array | 422 |
test_name_invalid | 422 |
test_source_case_required | 422 |
test_source_image_required | 422 |
test_source_validation_id_required | 422 |
test_source_validation_image_unreadable | 422 |
test_source_validation_no_image | 422 |
test_suite_empty | 404 |
test_suite_invalid | 422 |
tests_lock_held | 409 |
twofa_method_not_verified | 422 |
twofa_setup_required | 401 |
unknown_event_type | 422 |
unknown_permission_resource | 422 |
unknown_platform | 404 |
unknown_setting_key | 422 |
unknown_slug | 404 / 422 |
unknown_test_source | 422 |
unsupported_channel | 422 |
user_not_restorable | 404 |
var_too_long | 422 |
vars_must_be_object | 422 |
version_not_found | 400 |
Without translation
These 314 codes are emitted with no entry in the translation catalogue, so their detail arrives in the language it was written in, untranslated.
Registered with no detected emission
These 69 codes are present in the translation catalogue, but source analysis finds no place where they are emitted. They may be retired codes, or codes assembled at run time. They are listed so the inventory is complete; an integration should not count on receiving them.