Esta página es el diccionario global de error codes del API. Cada respuesta de error lleva un code estable, machine-readable, que tu cliente debe usar para ramificar lógica. El detail es legible y se traduce; el code nunca cambia ni se traduce.

Para la introducción suave al envelope de errores, ver Errores. Para los flujos relacionados, ver Idempotencia, Límites de uso y Arquitectura de webhooks.

Forma de la respuesta

Toda respuesta de error sigue el envelope JSON:API estándar — un array errors y un objeto meta. Una sola respuesta puede llevar varios errores cuando aplica (típicamente en validación de campos).

{
  "errors": [
    {
      "status": "422",
      "code": "phone_not_verified",
      "detail": "El teléfono no está verificado.",
      "source": { "pointer": "/data/attributes/phone" },
      "meta": { "masked_phone": "+52 55 ••••1234" }
    }
  ],
  "meta": {
    "version": "1.47.0",
    "api_version": "v1",
    "request_id": "a1b2c3d4e5f6",
    "datetime": { "timezone": "UTC", "format": "ISO 8601" }
  }
}

Reglas globales

  • code es estable, snake_case ASCII, y nunca se traduce. Ramifica lógica de cliente por este campo.
  • detail es legible para humanos y se traduce según Accept-Language (es / en).
  • status es el código HTTP como string (mismo número que el response status).
  • source.pointer (opcional) apunta al campo del request body que falló (JSON Pointer, RFC 6901).
  • meta por-error es opcional — algunos códigos incluyen contexto (ej. masked_phone, retry_after_seconds).
  • Una respuesta 422 puede llevar varios errores — uno por cada campo inválido.
  • meta.request_id correla con los logs del servidor — inclúyelo siempre que reportes un bug.

Códigos HTTP comunes

StatusSignificado en este API
400 Bad RequestEl request está malformado — JSON inválido, query param ausente, formato incorrecto. No vale reintentar sin corregir.
401 UnauthorizedFalta autenticación, token expirado, o credenciales inválidas. El cliente debe re-autenticar antes de reintentar.
403 ForbiddenAutenticado pero sin permiso para ese recurso o acción. No vale reintentar — el cliente no tiene el rol o el método de auth requerido.
404 Not FoundEl recurso no existe o no es visible para el caller.
405 Method Not AllowedPath correcto pero método HTTP equivocado.
409 ConflictEstado en conflicto — típicamente idempotencia en vuelo, recurso ya en estado terminal, o race condition. Puede tener sentido reintentar después de Retry-After.
410 GoneRecurso existió pero fue eliminado.
413 Payload Too LargeEl body o el upload supera el tope del endpoint.
422 Unprocessable EntityEl request fue parseado pero falló la validación de negocio. Una sola respuesta puede listar varios errores.
429 Too Many RequestsRate limit excedido. Esperá Retry-After segundos antes de reintentar.
500 Internal Server ErrorFalla inesperada del servidor. Reintentá con backoff exponencial.
502 Bad GatewayServicio upstream (Banxico, Stripe) no responde o devuelve algo malformado. Reintentá con backoff.
503 Service UnavailableSubsistema temporalmente desactivado o sobrecargado. Reintentá tras Retry-After.

Taxonomía por categoría

Autenticación y sesión

codeStatusCuándo se disparaEndpointsCliente debe
unauthorized401Credenciales ausentes, inválidas o token expirado.Todos los protegidosRe-autenticar (relogin o renovar API key)
invalid_credentials401Email o contraseña incorrectos.POST /v1/auth/login, POST /v1/auth/request-verification-otpMostrar mensaje genérico al usuario — no revelar cuál falló
auth_header_empty401El header Authorization está vacío.Todos los protegidosAdjuntar Authorization: Bearer ...
unrecognized_auth_format401El header Authorization no parsea como Bearer <token>.Todos los protegidosUsar Bearer mxcep_... (API key) o cookie JWT
invalid_api_key401El prefijo o el formato de la API key es inválido.Endpoints M2MRegenerar la key desde /uso o POST /v1/users/me/api-key/regenerate
invalid_encrypted_api_key401La API key no descifra contra el secret server-side (rotación de claves o key falsificada).Endpoints M2MRegenerar la key
api_key_decryption_failed401Falla criptográfica al descifrar la API key.Endpoints M2MRegenerar la key
auth_method_denied403El endpoint exige cookie (UI) pero llegaste con API key, o viceversa.Endpoints con audience restringidoUsar el método de auth correcto — ver Autenticación
dashboard_token_misuse401Usaste un token de dashboard contra un endpoint M2M./v1/* M2MUsar API key, no cookie
token_expired401El JWT venció.Endpoints con cookieRenovar (re-login) o limpiar cookie
token_lifetime_exceeded401El JWT supera el lifetime máximo absoluto del servidor.Endpoints con cookieRe-login
invalid_token_format401El JWT no tiene 3 segmentos.Endpoints con cookieRe-login
invalid_token_encoding401El JWT no decodifica como base64url.Endpoints con cookieRe-login
invalid_token_signature401La firma del JWT no valida.Endpoints con cookieRe-login
invalid_token_payload401El payload del JWT no parsea como JSON.Endpoints con cookieRe-login
invalid_token_issuer401El iss del JWT no es el esperado.Endpoints con cookieRe-login
invalid_token_audience401El aud del JWT no es el esperado.Endpoints con cookieRe-login
unsupported_token_algorithm401El JWT usa un alg fuera de la whitelist.Endpoints con cookieRe-login
session_invalidated401La sesión fue invalidada manualmente (force-logout, reset 2FA).Endpoints con cookieRe-login
csrf_missing401El header X-CSRF-Token no está presente en una mutación cookie-only.Mutaciones UI cookieRefrescar la cookie y reenviar
csrf_mismatch401El token CSRF no coincide con la cookie.Mutaciones UI cookieRefrescar la cookie y reenviar
forbidden403Permiso denegado por RBAC.CualquieraPedir el permiso al admin de tu cuenta
permission_denied403Variante de forbidden para endpoints admin./v1/admin/*Verificar el rol del usuario
account_suspended403La cuenta del caller está suspendida.Todos los autenticadosContactar soporte
account_deleted403La cuenta fue soft-deleted.Todos los autenticadosContactar soporte
registration_disabled403El flag global registration.enabled está OFF.POST /v1/auth/registerEsperar a que se reactive

OTP, 2FA y verificación

codeStatusCuándo se disparaEndpointsCliente debe
phone_not_verified403El teléfono no fue verificado vía OTP todavía.POST /v1/auth/login, mutacionesDisparar POST /v1/auth/request-verification-otp
phone_already_verified409El teléfono ya está verificado — no hay nada que hacer.POST /v1/auth/request-verification-otpContinuar al flujo normal
otp_not_found404No hay OTP activo para esa combinación user+purpose.POST /v1/auth/verify-phone, GET /v1/auth/otp-statusRe-solicitar OTP
otp_invalid_code422El código OTP enviado es incorrecto.POST /v1/auth/verify-phone, POST /v1/auth/verify-password-resetReingresarlo (máximo N intentos)
otp_expired422El OTP venció antes de ser usado.POST /v1/auth/verify-phone, password-resetRe-solicitar OTP
otp_max_attempts422Se agotaron los intentos para ese OTP.POST /v1/auth/verify-phone, password-resetRe-solicitar un OTP nuevo
otp_already_used422El OTP ya fue consumido.Confirmación OTPSolicitar otro
otp_cooldown429Estás pidiendo OTPs muy rápido — espera Retry-After.POST /v1/auth/resend-otpEsperar el cooldown
invalid_otp_id422El otp_id enviado no tiene formato UUID.Confirmación OTPRe-solicitar OTP y usar el otp_id del response
invalid_otp_parameters422El payload de OTP está incompleto.Confirmación OTPRevisar los campos requeridos
missing_otp_id422Falta el otp_id en el body.Confirmación OTPAgregar otp_id
invalid_verification_token422El token de un flujo de verificación es inválido o malformado.POST /v1/auth/reset-passwordReiniciar el flujo de verificación
invalid_reset_context422El contexto del reset (purpose, audience, expiry) no coincide.POST /v1/auth/reset-passwordReiniciar el flujo
purpose_mismatch422El OTP fue generado para otro propósito (ej. login vs. password reset).POST /v1/auth/verify-password-reset, reset-passwordSolicitar OTP con el purpose correcto
confirmation_token_missing422Falta el confirmation_token en una operación de step-up.POST /v1/auth/* step-upAgregar confirmation_token
confirmation_token_invalid422Token de confirmación malformado.Step-upRe-solicitar el token
confirmation_token_malformed422Variante: el token no tiene la estructura esperada.Step-upRe-solicitar
confirmation_token_mismatch422El token corresponde a otra acción distinta.Step-upRe-solicitar para la acción correcta
confirmation_token_already_used409El token ya fue consumido (single-use).Step-upRe-solicitar uno nuevo
confirmation_token_slug_mismatch422El token fue emitido para otro plan/slug.Step-up de billing/plansRe-emitir para el slug correcto
twofa_required401El usuario tiene 2FA activo — necesitas resolver el challenge.POST /v1/auth/loginDisparar POST /v1/auth/2fa/verify-challenge
twofa_invalid_challenge422El código del challenge 2FA es incorrecto.POST /v1/auth/2fa/verify-challengeReingresarlo
twofa_invalid_context422El contexto 2FA (purpose / audience) no matchea.2FA endpointsReiniciar el flujo
twofa_not_enabled422Intentaste verificar 2FA pero el usuario no lo tiene activo.2FA endpointsHabilitar 2FA primero
twofa_already_disabled422Se pidió disable de 2FA pero ya está disabled.POST /v1/auth/2fa/confirm-disableIgnorar — estado correcto
twofa_already_enabled422Se pidió enable de 2FA pero ya está enabled.POST /v1/auth/2fa/confirm-enableIgnorar — estado correcto
twofa_method_same422Se pidió cambiar a un método 2FA igual al actual.POST /v1/auth/2fa/confirm-method-changeElegir un método distinto
twofa_method_unsupported422El método 2FA pedido no está soportado.2FA endpointsUsar sms o email
twofa_action_mismatch422El challenge resuelto no corresponde a la acción solicitada.2FA step-upRe-iniciar el step-up

Registro y cuenta

codeStatusCuándo se disparaEndpointsCliente debe
email_already_registered422El email ya tiene cuenta verificada.POST /v1/auth/registerMostrar mensaje genérico anti-enum
email_already_taken422Variante: el email no está libre.Cambio de emailPedir otro email
email_already_verified409El email ya está verificado.POST /v1/auth/email/request-verifyContinuar al flujo normal
email_same_as_current422El email nuevo coincide con el actual.POST /v1/auth/email/request-changeIngresar uno distinto
email_delivery_failed502El proveedor de email rechazó el envío.Cambio/verify de emailReintentar; si persiste, soporte
phone_taken422El teléfono ya está en otra cuenta verificada.Registro / cambio de phonePedir otro teléfono
phone_required_for_email_change422Necesitás teléfono verificado antes de cambiar email.POST /v1/auth/email/request-changeVerificar phone primero
password_mismatch422password y password_confirmation no coinciden.Registro / resetReingresar coincidentes
password_too_short422La contraseña no cumple el largo mínimo.Registro / reset / cambioUsar contraseña más larga
password_too_weak422La contraseña no cumple las reglas de complejidad.Registro / reset / cambioReforzar la contraseña
new_password_too_short422Variante: en cambio de contraseña, la nueva es muy corta.Cambio de contraseñaUsar más caracteres
current_password_required422Falta current_password en un cambio de contraseña.Cambio de contraseñaAgregar el campo
current_password_incorrect422El current_password no matchea.Cambio de contraseñaReingresar correctamente
invalid_email_change_context422El contexto del cambio de email no es válido (purpose mismatch).Email change applyReiniciar el flujo
sms_delivery_failed502El proveedor SMS rechazó el envío del OTP.Re-OTP / registerReintentar; si persiste, soporte
unsupported_locale422El locale enviado no está en la whitelist.PUT /v1/users/meUsar es o en
language_unsupported422Variante de unsupported_locale.PUT /v1/users/meUsar es o en

Validación general de campos

Estos códigos los emite Support\Validator y pueden aparecer en cualquier endpoint con body.

codeStatusCuándo se disparaCliente debe
required422Campo obligatorio ausente.Incluir el campo
missing_field422Variante de required para campos concretos.Incluir el campo
invalid_format422El campo no matchea el formato esperado.Corregir el formato
invalid_value422El valor está fuera del set permitido.Usar un valor del enum
invalid_type422El tipo PHP/JSON no coincide.Ajustar el tipo
invalid_email422El email no parsea.Corregir
invalid_phone422El phone no parsea como E.164.Usar formato +52...
invalid_uuid422No es un UUID v4.Pasar UUID válido
invalid_url422La URL es malformada.Corregir
invalid_url_scheme422Solo https aceptado.Usar https://
url_ssrf_blocked422La URL apunta a una IP privada / DNS rebind.Usar host público
url_dns_failed422DNS no resolvió el host.Verificar el host
max_length_exceeded422Supera el max length del campo.Acortar
invalid_amount422Monto no parsea como decimal positivo.Corregir
invalid_date422Fecha malformada o fuera de rango.Usar ISO 8601
invalid_account_format422El número de cuenta no es CLABE 18 / tarjeta 16 / phone E.164.Corregir según account_type
invalid_clabe_checksum422El dígito verificador de la CLABE falla.Verificar la CLABE
invalid_card_luhn422El check Luhn de la tarjeta falla.Verificar el PAN
invalid_account_length422Largo incorrecto para el tipo (18 CLABE / 16 tarjeta / 10 phone).Ajustar largo
invalid_bank_code422El código de banco no existe en el catálogo.Usar GET /v1/public/banks
invalid_image422La imagen no decodifica.Reenviar
invalid_image_format422Formato fuera de JPEG/PNG/WEBP.Convertir a JPEG/PNG
image_too_large422Imagen supera el tope.Reducir tamaño
validation_error422Error de validación genérico.Revisar source.pointer y meta
validation_failed422Variante para fallas combinadas.Revisar el detalle
invalid_request_body400El JSON no parsea.Enviar JSON válido
invalid_payload400El shape del payload no coincide con el contrato.Revisar la spec del endpoint
payload_too_large413Body completo supera el tope.Reducir
payload_corrupt422El payload llegó truncado o malformado.Reenviar
message_build_failed422El server no pudo armar el mensaje a despachar.Reintentar

Idempotencia

Ver Idempotencia para el contrato completo.

codeStatusCuándo se disparaCliente debe
invalid_idempotency_key400El header Idempotency-Key no cumple [A-Za-z0-9_-]{1,255}.Generar key nueva con caracteres válidos
idempotency_key_in_progress409Hay otra request en vuelo con la misma key.Esperar Retry-After segundos y reintentar
idempotency_key_reused422La misma key se usó antes con un body distinto.Generar key nueva o reusar el body exacto

Validación de transferencias SPEI

Estos códigos aplican a POST /v1/validate, POST /v1/validate-ocr, y al pipeline de validación masiva.

codeStatusCuándo se disparaCliente debe
clabe_prefix_not_recognized422Los primeros 3 dígitos de la CLABE no mapean a ningún banco.Verificar la CLABE — puede no ser SPEI
bank_code_required_for_phone422Para account_type=phone se requiere bank_code explícito.Agregar bank_code
bank_code_unresolvable_for_phoneterminalAsync: no se pudo resolver el banco del teléfono via DiMo.Esperar — el estado final es error
intra_bank_no_cepterminalAsync: la transferencia es intra-banco y Banxico no emite CEP.Buscar el comprobante interno del banco
clave_or_ref_required422Se requiere clave_rastreo o referencia_numerica.Incluir uno
image_or_image_url_required422Para OCR: ni image ni image_url.Enviar uno
image_not_readable422OCR no pudo leer la imagen.Adjuntar imagen más clara
image_not_readable_receipt422OCR leyó pero no parece un comprobante SPEI.Adjuntar el comprobante correcto
image_not_spei_receipt422El recibo no es SPEI (otro tipo de transferencia).Adjuntar comprobante SPEI

Códigos terminales async de validaciones

Estos códigos aparecen en validations.error_code cuando una validación async termina en estado error o failed. Ver Validaciones async y Política de reintentos.

codeCuándo se disparaDispara webhook validation.error
networkBanxico inaccesible tras agotar reintentos de red.
captchaBanxico devolvió captcha activo.
max_retries_exceededSe agotó el tope de reintentos del plan.
ttl_expiredTTL del job venció antes de transicionar a terminal.No
preflight_failedFalló la validación previa al despacho.No
rate_limit_exhaustedSe agotaron los slots de proxy/rate.No
dispatch_failedEl handler no pudo despachar el job.No
bank_code_unresolvable_for_phonePhone account_type sin banco resoluble.No
intra_bank_no_cepIntra-banco — Banxico no emite CEP.No
banxico_rate_limitBanxico devolvió rate-limit puntual.(interno, reintenta)
banxico_rate_limit_exhaustedSe agotaron los retries por rate-limit.(interno)
banxico_captcha_activeBanxico tiene captcha global activo.(interno, reintenta)
rate_limit_batchLote de batch chocó con rate-limit.No
ocr_errorOCR upstream (Gemini) falló.No
banxico_errorError genérico Banxico.No

Beneficiarios

codeStatusCuándo se disparaEndpointsCliente debe
query_param_account_required400Falta ?account= en la query.GET /v1/beneficiaries/lookup, /validate-accountAgregar el param
query_param_last_digits_required400Falta ?last_digits= en la query.GET /v1/account-directory/lookupAgregar el param
invalid_last_digits_length422last_digits no tiene 4 dígitos.GET /v1/account-directory/lookupPasar 4 dígitos
account_number_required422Falta account_number en el body.POST /v1/beneficiariesAgregar el campo
beneficiary_already_registered422La cuenta ya está en tus beneficiarios.POST /v1/beneficiariesReutilizar el existente
beneficiary_not_found_for_account404No hay beneficiario asociado a esa cuenta.GET /v1/beneficiaries/lookupCrearlo
account_not_in_catalog404La cuenta no aparece en el directorio cross-tenant.GET /v1/account-directory/lookupComportarse como "sin info"

Importes masivos (validations + beneficiaries)

codeStatusCuándo se disparaEndpointsCliente debe
file_required422El upload no incluye archivo.POST /v1/{validations,beneficiaries}/importsAdjuntar el archivo
multi_upload_not_allowed_for_text422Multi-select pero los archivos son texto plano.POST /v1/validations/importsSubir uno por uno o usar imágenes/ZIP
parse_failed422El parser no pudo extraer filas.Imports (preview)Revisar el formato del archivo
commit_failed422El commit del import falló a mitad.POST /v1/{validations,beneficiaries}/imports/{id}/commitRevisar el detalle; reintentar si idempotent
job_not_editable422Querés editar un job en estado terminal.PATCH /v1/validations/imports/{id}/rows/{row_id}El job ya fue committed
job_not_cancellable409Cancel pedido sobre un job en estado no cancelable.Imports adminEl job ya terminó
no_valid_fields422El payload de edit no tiene campos válidos.PATCH de import rowIncluir al menos un campo
zip_pack_failed422Falló el repacking de un ZIP de imágenes.POST /v1/validations/imports con ZIPReintentar con ZIP estándar
no_valid_test_files422Ningún archivo del upload es procesable.Tests adminRevisar el set
duplicate_clave_rastreo(row)Mismo clave_rastreo en filas distintas del mismo import.preview rowsEditar o descartar la fila duplicada
duplicate_tuple(row)Tupla (emisor, receptor, fecha, monto) duplicada.preview rowsEditar o descartar
account_duplicate(row)Beneficiary import: el account_number repite.preview rowsEditar/descartar
alias_duplicate(row)Beneficiary import: el alias repite.preview rowsEditar/descartar
alias_missing(row)Beneficiary import: falta alias.preview rowsAgregarlo
clabe_checksum_failed(row)CLABE de la fila falla checksum.preview rowsCorregir
card_luhn_failed(row)Tarjeta de la fila falla Luhn.preview rowsCorregir
bin_unknown(row)El BIN de la tarjeta no mapea a banco.preview rowsVerificar el PAN
masked_account_unresolved(row)La cuenta venía enmascarada y no resolvió.preview rowsEditar con la cuenta completa
no_match(row)El free-form parser no detectó campos.preview rowsEditar manualmente
no_usable_data(row)La fila no tiene datos suficientes.preview rowsEditar o descartar
tracking_missing(row)Falta clave_rastreo.preview rowsAgregar
clabe_missing(row)Falta CLABE/cuenta.preview rowsAgregar
fecha_missing(row)Falta fecha.preview rowsAgregar
fecha_invalid(row)Fecha no parsea.preview rowsCorregir
monto_missing(row)Falta monto.preview rowsAgregar
monto_invalid(row)Monto no parsea.preview rowsCorregir

Plan y facturación

codeStatusCuándo se disparaEndpointsCliente debe
plan_not_found404El plan referenciado no existe./v1/billing/*, /v1/plans/{slug}Listar planes con GET /v1/plans/public
billing_plan_not_found422Variante: el slug no resuelve a un plan activo.POST /v1/billing/checkout-sessionRevisar el slug
billing_plan_is_free422Intentas subscribir a un plan free vía Stripe checkout.CheckoutEl plan free se asigna sin Stripe
billing_plan_not_self_service422Plan no asignable vía self-service.CheckoutContactar soporte
billing_plan_slug_required422Falta plan_slug en el body.CheckoutAgregar el campo
billing_plan_slug_too_long422El slug supera el max.Checkout / adminAcortar
billing_plan_slug_invalid422El slug no cumple ^[a-z0-9-]+$.Checkout / adminCorregir
billing_intent_invalid_shape422La cookie app_checkout_intent está corrupta.CheckoutLimpiar la cookie y reiniciar
billing_invalid_interval422El interval no es month ni year.Checkout / admin pricesUsar uno permitido
billing_invalid_kind422El kind del precio no es base ni metered.Admin pricesUsar uno permitido
billing_disabled503El módulo de billing está desactivado en este deploy./v1/billing/*Esperar a que se active
no_active_subscription404El usuario no tiene suscripción activa./v1/billing/subscription/*Iniciar checkout
subscription_race_retry409Race condition mutando la subscripción — el cliente debe reintentar./v1/billing/subscription/*Reintentar tras 1-2s
subscription_not_found404La suscripción no existe.Admin subsVerificar el user_id
stripe_cancel_failed502Stripe rechazó el cancel./v1/billing/subscription/cancelReintentar
stripe_checkout_failed502Stripe rechazó la creación de session.CheckoutReintentar
stripe_unreachable502Stripe API timeout/connection error.Cualquier billingReintentar
stripe_invoice_malformed422El invoice de Stripe llegó incompleto en el webhook.(interno)(logged y resync)
stripe_subscription_malformed422El subscription de Stripe llegó incompleto.(interno)(logged y resync)
stripe_meter_lookup_failed502Stripe meter lookup falló.Billing meteredReintentar
stripe_meter_missing422El meter esperado no existe en Stripe.Billing meteredCrear el meter o desactivar metered
stripe_product_create_failed502Falló creación de Product en Stripe.Admin plansReintentar
stripe_price_not_found404El stripe_price_id no existe en Stripe.Admin pricesVerificar el ID
stripe_price_archive_failed502Stripe rechazó archivar el precio.Admin pricesReintentar
stripe_price_id_required422Falta stripe_price_id.Admin pricesAgregar
stripe_price_id_format_invalid422El stripe_price_id no matchea price_*.Admin pricesCorregir
price_not_found404El precio local no existe.Admin pricesVerificar el ID
price_local_id_required422Falta price_local_id.Admin pricesAgregar
price_not_active422El precio está archived.Checkout / adminActivar primero
price_already_in_catalog422El stripe_price_id ya está usado por otro precio.Admin pricesReutilizar el existente
price_combo_already_exists422Combinación (plan, interval, currency, kind) duplicada.Admin pricesEditar el existente
price_plan_mismatch422El precio referenciado no pertenece a ese plan.Admin pricesUsar el plan correcto
source_price_id_required422Falta source_price_id en migrate.Admin price migrateAgregar
unit_amount_required422Falta unit_amount.Admin pricesAgregar
overage_update_failed422Falló el toggle de overage./v1/billing/overage/{enable,disable}Reintentar
overage_not_applicable422El plan actual no soporta overage.Overage toggleUpgradear plan
refund_amount_invalid422Monto de refund inválido (negativo o > invoice).Admin refundCorregir
refund_invoice_not_found404El invoice referenciado no existe en Stripe.Admin refundVerificar el invoice_id
admin_grant_failed422Falló el grant de plan admin-side.Admin grant-planRevisar el detalle
comp_amount_invalid422Monto de compensación inválido.Admin compCorregir
comp_user_missing422Falta target user en comp.Admin compAgregar
comp_user_not_found404El user de comp no existe.Admin compVerificar

Finanzas

codeStatusCuándo se disparaEndpointsCliente debe
invalid_month400Param month ausente o no YYYY-MM./v1/finance/*, /v1/api-usage/*Pasar YYYY-MM
invalid_period400Param period no matchea convención.Finance / usageCorregir
invalid_range400Range from/to incoherente.Finance / usageCorregir
range_required400Falta range o from/to.Finance / usagePasar uno
pdf_render_failed500dompdf falló al renderizar.Finance PDFReintentar; reportar si persiste
xlsx_render_failed500PhpSpreadsheet falló.Finance XLSXReintentar
csv_stream_failed500El stream CSV falló.Finance / exports CSVReintentar
invalid_export_format422Formato pedido fuera de json/csv/xlsx/pdf.ExportsElegir uno soportado
no_ceps404No hay CEPs disponibles en el rango.GET /v1/finance/cepsAjustar rango

Webhooks y notificaciones

codeStatusCuándo se disparaEndpointsCliente debe
webhook_url_required422Falta url.POST /v1/webhooksAgregar
webhook_url_empty422url enviado pero vacío.PATCH /v1/webhooks/{id}Agregar URL real
webhook_url_too_long422url supera 2048 chars.Webhooks CRUDAcortar
webhook_url_invalid_format422url no parsea.Webhooks CRUDCorregir
webhook_url_not_https422El scheme no es https.Webhooks CRUDUsar HTTPS
webhook_events_required422Falta el array events.Webhooks CRUDAgregar al menos uno
webhook_events_too_many422Más eventos que el max.Webhooks CRUDReducir
webhook_event_invalid422Evento fuera del registry.Webhooks CRUDVer eventos en docs
webhook_status_invalid422status no es active/disabled.Webhooks CRUDCorregir
webhook_limit_reached422Tope de webhooks del plan alcanzado.POST /v1/webhooksUpgradear plan o borrar uno
signature_invalid401El webhook entrante no firma — Stripe ingress.POST /v1/webhooks/stripeVerificar el secret y timestamp
push_subscription_invalid_shape422El objeto PushSubscription es inválido.POST /v1/notifications/push/subscribeRe-suscribir desde el SW
push_subscription_endpoint_required422Falta endpoint.POST /v1/notifications/push/testAgregar
push_subscription_endpoint_not_https422Endpoint no es HTTPS.Push subscribeVerificar el provider
push_subscription_endpoint_too_long422Endpoint excede el max.Push subscribe(problema del provider)
push_subscription_none_active422No tienes suscripciones push activas.POST /v1/notifications/push/testSuscribirse primero
push_not_configured503El servidor no tiene VAPID configurado.Push endpointsSoporte
notifications_event_unknown422Evento fuera del registry./v1/notifications/preferencesRevisar eventos válidos
notifications_channel_unknown422Canal fuera del registry.PreferencesUsar email/sms/push/in_app/telegram
notifications_preference_invalid422Shape de la preferencia inválido.PreferencesRevisar el body
notifications_preference_locked422La preferencia es forzada por el server (broadcast).PreferencesNo editable por el user
notifications_preferences_empty422El body no trae preferencias.PreferencesAgregar al menos una
notification_not_found404Notificación referenciada no existe.GET /v1/notifications/{id}Verificar el id
invalid_notification_id422El id no es UUID.NotificationsCorregir
telegram_bot_not_configured503El bot de Telegram no está configurado server-side./v1/notifications/telegram/linkSoporte
quiet_hours_invalid_timezone422El timezone no existe.PUT /v1/notifications/quiet-hoursUsar IANA TZ
quiet_hours_minutes_out_of_range422Minutos fuera de [0, 1440].Quiet hoursCorregir

Rate limit

Ver Límites de uso para la convención completa de headers + buckets.

codeStatusCuándo se disparaCliente debe
rate_limited429Bucket genérico de rate limit excedido.Esperar Retry-After segundos
rate_limit_exceeded429Variante para buckets internos (e.g. login).Esperar y reintentar
too_many_requests429Variante semántica del 429 estándar.Esperar

Recursos genéricos

codeStatusCuándo se disparaCliente debe
not_found404El recurso pedido no existe o no es visible.Verificar el id
user_not_found404El user referenciado no existe.Verificar el id
key_not_available404La API key del user no está disponible para mostrar.Regenerar
cep_not_available404El CEP de la validación todavía no está disponible.Reintentar más tarde
image_not_available404La imagen original no está accesible.Re-uploadear (si aplica)
changelog_not_found404La versión solicitada no existe.Listar con GET /v1/public/changelog
changelog_empty404No hay changelog publicado.Esperar publicación
method_not_allowed405Método HTTP no soportado para ese path.Usar uno de los permitidos
internal_error500Falla inesperada.Reintentar con backoff
dispatch_failed500/503El job no pudo despacharse al worker.Reintentar

Admin (operación interna)

Estos códigos son emitidos por endpoints /v1/admin/* y requieren rol con permiso. La lista completa abarca panels de queues, scheduled tasks, services, migrations, seeders, tests, plans, security, i18n. Mostramos los más recurrentes; el resto sigue la convención <dominio>_<accion>_failed para 5xx y <dominio>_<accion>_invalid para 4xx.

codeStatusDominio
permission_denied403Cualquier admin
admin_self_target_forbidden403Acciones sobre el propio user (force-logout, reset-2fa)
cannot_delete_self / cannot_suspend_self / cannot_change_own_role / cannot_change_own_status / cannot_force_logout_self / cannot_reset_own_2fa403Guardrails para no dispararse en el pie
cannot_suspend_owner / cannot_suspend_admin / only_owner_can_*403RBAC role hierarchy
cannot_deactivate_default_plan / cannot_set_inactive_as_default / plan_cannot_delete_default422Default plan invariants
queues_*_failed500Familia /admin/queues — overview, states, stats, pause, resume, start, stop, restart, cancel, retry, discard, dlq, batches, jobs, workers, config. Cada uno tiene su _failed y, donde aplica, su _prepare_failed (paso 1 de step-up).
scheduled_task_*_failed500Familia /admin/scheduled-tasks — create, update, delete, detail, run_now, executions, drift, list.
migration_*422 / 404migration_not_found, migration_file_missing, migration_filename_required, migration_filename_format, migration_target_version_format, migration_target_invalid_type, migration_mark_bulk_limit.
seeder_*422 / 404seeder_not_found, seeder_invalid, seeder_bulk_limit, seeder_filename_format, seeder_filename_required.
test_*422 / 404test_file_not_found, test_filename_format, test_files_limit, test_files_must_be_array, test_name_invalid, test_suite_empty, test_suite_invalid, compare_runs_must_differ.
worker_not_found / instance_not_found / scheduled_task_not_found / dlq_entry_not_found / execution_not_found / run_not_found404Queues subresources
worker_not_running / job_not_cancellable / run_not_cancellable409Conflict — estado terminal
dlq_entry_unreadable422Entrada DLQ malformada
payload_corrupt / payload_too_large / invalid_payload400 / 413Admin step-up payloads
invalid_action / invalid_instance / invalid_service / invalid_stream / invalid_user_id / invalid_audit_id / invalid_event_id / invalid_delivery_id / invalid_otp_id / invalid_run_id / invalid_id / invalid_param / invalid_status_filter / invalid_source_filter / invalid_target_user_id / invalid_bucket_target / invalid_version / missing_version400Param validation en admin paneles
bulk_action_invalid / bulk_slugs_required / bulk_slugs_too_many422Admin bulk endpoints
name_already_exists422Naming collision (broadcasts, plans)
broadcast_not_found / broadcast_empty_audience404 / 422/admin/notifications/broadcasts
logs_read_failed / heartbeat_persist_failed / execution_failed503/admin/services
openapi_spec_missing / openapi_spec_invalid_yaml500/admin/i18n bundle generator
target_required / probe_label_required422/admin/banxico probes
retry_policy_invalid422Per-plan retry caps
permissions_must_be_object422/admin/roles editor
plan_*422 / 404Plan CRUD: plan_name_required, plan_name_too_long, plan_slug_required, plan_slug_format_invalid, plan_duplicate_same_slug, plan_currency_invalid, plan_features_invalid_shape, plan_included_validations_negative, plan_limit_negative, plan_sort_order_negative, plan_trial_days_out_of_range, plan_tax_behavior_invalid, plan_free_cannot_have_initial_prices, plan_stripe_product_missing, plan_price_* (migrate, archive, range).
initial_price_base_required / initial_price_metered_required422Plan create con prices iniciales
out_of_range / invalid_type422/admin/queues worker config validator
worker_failed / run (queues)500Genéricos
recent_executions_failed / scheduled_tasks_drift_failed / scheduled_tasks_list_failed500Scheduler
i18nplaceholder_parity_drift, icu_malformed, html_unsafe, brand_removed422/admin/i18n lint

Cómo reportar un error

Cuando algo falle de manera inesperada:

  1. Captura meta.request_id de la respuesta.
  2. Anota el code y el status.
  3. Si es 5xx repetible, abre ticket de soporte adjuntando ambos.

El request_id correla con los logs server-side y permite rastrear la causa exacta sin que tu equipo tenga que reproducirlo.