{
"error": "insufficient_funds",
"message": "account balance is not enough for this operation"
}
error: código estable ensnake_case— úsalo en tu lógica.message: explicación legible — puede cambiar, no lo parsees.
Mensajes de error saneados. El
message de un error nunca expone nombres de proveedores, detalles de infraestructura, URLs, bodies crudos del proveedor (JSON/HTML) ni configuración interna — ni en respuestas de la API, ni en webhooks, ni en los campos de estado persistidos. Los rechazos de negocio del procesador conservan su motivo accionable (por ejemplo, por qué se rechazó un documento o una cuenta); las fallas de infraestructura se reemplazan por el mensaje genérico fijo "the payment provider could not process the request" — reintenta esas operaciones con la misma idempotency_key.payin_corridor_unsupported | El corredor solicitado no tiene un proveedor de payin activo — vuelve a leer GET /v1/payins/methods |
| 502 | deposit_account_failed | No se pudo aprovisionar la cuenta receptora dedicada; lee la lista antes de reintentar |
Códigos por categoría
Autenticación y permisos
| HTTP | error | Significado |
|---|---|---|
| 401 | unauthorized | Credencial ausente o inválida |
| 401 | invalid_credentials | Email o contraseña incorrectos (login) |
| 401 | invalid_refresh_token | Refresh token inválido, expirado, ya usado o revocado — vuelve al login |
| 403 | account_required | El endpoint exige credencial de cuenta |
| 403 | org_admin_required | El endpoint exige credencial de administrador |
| 403 | forbidden | Nivel de credencial no permitido |
| 403 | account_blocked | La cuenta no está activa; también bloquea POST /v1/me/verification/link — pide al administrador que la restaure |
| 403 | verification_rejected_requires_admin | Compliance rechazó el KYC/KYB de la cuenta; el onboarding self-service está deshabilitado — contacta al administrador para reabrir la verificación |
| 403 | service_disabled | El servicio no está habilitado para tu cuenta (consulta GET /v1/services) |
| 403 | org_suspended | El servicio está suspendido; contacta al equipo de CBPay |
| 403 | company_only | Función solo para cuentas empresa |
| 403 | company_required | Función solo para cuentas empresa (ej. banking para terceros) |
| 403 | human_session_required | La operación maneja llave privada (import/export de wallet segregada) y exige sesión de usuario con 2FA — las API keys no se permiten |
| 403 | member_disabled | El usuario está bloqueado para iniciar sesión; contacta al administrador de tu organización |
| 403 | passkey_rejected | La verificación de la passkey falló; reintenta o entra con contraseña |
| 403 | owner_required | Solo el miembro owner de la cuenta puede ejecutar esa acción |
OTP / 2FA
Detalle y flujo completo en seguridad y 2FA.| HTTP | error | Significado |
|---|---|---|
| 403 | otp_required | La acción exige OTP: verifica un desafío y reintenta con X-OTP-Token |
| 403 | otp_invalid | Token OTP inválido, expirado o ya usado |
| 403 | session_required | Los desafíos OTP requieren sesión de usuario, no API key |
| 403 | phone_binding_cooldown | Teléfono enlazado hace menos de 24 h sin verificación y sin factor alternativo (app autenticadora o email verificado) |
| 409 | phone_verification_required | Verifica tu teléfono (desafío OTP) antes de activar el 2FA de login por SMS/WhatsApp |
| 401 | invalid_code | El código no coincide |
| 401 | invalid_pending_token | El token intermedio del login expiró; vuelve a iniciar sesión |
| 400 | invalid_action / invalid_channel | Acción o canal fuera de catálogo (el channel del desafío debe ser sms, whatsapp, email o totp) |
| 409 | phone_required | La cuenta no tiene teléfono (PATCH /v1/me) |
| 409 | otp_phone_missing | El login exige OTP y la cuenta no tiene teléfono; contacta a tu operador |
| 409 | challenge_not_pending | El desafío expiró o ya se usó; crea uno nuevo |
| 429 | too_many_attempts | Límite de envíos o verificaciones; espera unos minutos |
| 503 | otp_unavailable | Servicio de verificación no disponible (la acción queda bloqueada, nunca se salta el OTP) |
| 409 | otp_disabled_for_org | Tu organización no tiene habilitado el 2FA por acción; contacta a tu operador |
| 409 | totp_not_started | No hay enrolamiento TOTP en curso; parte con POST /v1/me/totp/enroll |
Login social (OAuth)
Detalle y flujo completo en login social.| HTTP | error | Significado |
|---|---|---|
| 400 | invalid_provider | Proveedor fuera de google/apple/microsoft/facebook |
| 400 | provider_not_configured | Tu organización no tiene ese proveedor habilitado |
| 401 | invalid_credential | La credencial del proveedor es inválida, expiró o es de otra app |
| 409 | email_conflict | Ya existe una cuenta con ese email; entra con tu método actual y vincula el proveedor |
| 409 | identity_taken | Ese proveedor ya está vinculado a otra cuenta |
| 409 | last_login_method | No puedes desvincular tu único método de acceso |
Panel de administración de organización
Estos códigos provienen de superficies de administración de organización (el panel CBPay Admin), no de la API a nivel cuenta documentada arriba — nunca aparecen en los endpoints/v1/* de cuenta.
| HTTP | error | Significado |
|---|---|---|
| 403 | global_treasury_access_disabled | La organización no tiene habilitada la visibilidad de tesorería global en su panel admin; pide a un administrador de plataforma que habilite global_treasury_read en los settings de la organización |
| 503 | core_admin_credential_missing | Un catálogo de administrador de plataforma requiere una credencial del core configurada; contacta al administrador de plataforma |
| 400 | invalid_value | Un setting de la organización se envió con el tipo incorrecto (ej. global_treasury_read debe ser booleano, no un string) |
| 409 | approval_in_progress | Otro administrador está aplicando este ajuste; espera a que termine antes de intentarlo de nuevo |
Validación (400)
error | Significado |
|---|---|
invalid_json | Body no es JSON válido o tiene campos desconocidos |
invalid_lang | lang debe ser es, en o zh |
invalid_settings | Los settings de la organización no son un objeto JSON válido o no pudieron normalizarse; corrige el payload y reintenta |
invalid_type | type debe ser person o company |
invalid_email / invalid_display_name | Campo requerido inválido |
weak_password | Contraseña menor a 8 caracteres |
invalid_role | Rol de miembro inválido |
unknown_org | Slug de organización incorrecto (usa cbpay) |
invalid_request | Faltan country/currency |
invalid_purpose | purpose debe ser fondeo o banking; elige un corredor Banking soportado |
idempotency_key_required | Falta la clave de idempotencia |
reserved_idempotency_key | La clave usa un prefijo reservado del sistema (payin-convert: o checkout-swap:, propios de las auto-conversiones) — usa otra clave |
beneficiary_required | Falta el beneficiario del payout |
invalid_cuit | Los payouts de Argentina (AR) exigen que beneficiary.tax_id sea un CUIT o CUIL de 11 dígitos — envía el identificador de 11 dígitos del beneficiario; consulta la guía de payouts |
invalid_cbu | Los payouts de Argentina (AR) exigen que beneficiary.account_number sea un CBU o CVU de 22 dígitos; los payouts en USD aceptan solo CBU — envía un CBU/CVU válido de 22 dígitos (CBU para USD); consulta la guía de payouts |
invalid_amount | Monto no es un decimal positivo válido |
recipient_required / self_transfer | Destino de transferencia inválido |
invalid_chain / invalid_asset | Red o activo no soportado |
to_address_required | Falta dirección destino del retiro |
invalid_payload | Falta un campo requerido (ej. enabled en monitoreo AML, external_customer_id en verificaciones) |
invalid_iban | El IBAN del payout SEPA es inválido, no es compatible con la ruta EU o pertenece a GB en SEPA Instant V1; corrígelo y reintenta con una clave de idempotencia nueva |
invalid_qr_payload | QR de payout ilegible o no soportado (BR Code corrupto, checksum inválido o QR PIX dinámico); el message explica la razón exacta |
liveness_already_completed | La prueba de vida de esa verificación ya fue superada |
invalid_event_type / weak_secret / invalid_callback_url | Suscripción de webhook inválida |
invalid_phone | Teléfono no normalizable a E.164 (contactos y to_phone) |
invalid_language | lang del informe PDF no es en, es ni zh (informe AML e informe de verificación) |
invalid_locale | PATCH /v1/me (o el registro) envió un locale no vacío fuera de en / es / zh. El string vacío guarda inglés. Distinto de invalid_language (lang de informe PDF) y del invalid_value de org-admin en default_locale |
invalid_format | format del informe de verificación no es pdf ni json |
batch_too_large | Import de contactos con más de 1.000 entradas (pagina la subida) |
invalid_body | No se pudo leer el body del request (subidas binarias, webhooks) |
invalid_image | El body del avatar está vacío o no es una imagen soportada (PNG/JPEG/WebP, máx 512 KB) |
invalid_interval | El interval de la suscripción debe ser daily, weekly, monthly o yearly |
query_required | GET /v1/resolve necesita alias= o qr= |
same_email | El nuevo email de login es el actual; usa POST /v1/me/email/verify para verificarlo |
invalid_status / invalid_kyc_status / invalid_direction / reason_required / account_id_required / invalid_service / invalid_fee | Validaciones de administración |
invalid_settlement_hours | settlement_hours solo se acepta en el servicio de comisión payin_card y debe ser un entero no negativo (0 = acreditación inmediata) — ver comisiones |
invalid_country | Código de país mal formado o ausente — ISO 3166-1 alpha-2 (ej. GET /v1/aml/catalogs/cities?country=); también un filtro de país válido pero no soportado (ej. un country distinto de US en el lookup del directorio bancario) |
Idempotencia de payins QR
EnPOST /v1/payins con method: "qr", idempotency_key es opcional.
Puedes enviarla en el body JSON o como Idempotency-Key; si envías ambas,
gana la del body. La clave admite hasta 256 caracteres y no puede contener
CR/LF. La plataforma la scopea por cuenta del lado servidor; el integrador
envía su clave sin modificarla.
400 invalid_idempotency_key: la clave supera 256 caracteres o contiene CR/LF. Acórtala o elimina esos caracteres y reintenta el mismo request corregido.409 idempotency_conflict: la misma clave se usó con otro país, moneda, método o monto numérico. Conserva el payload original para replay o usa una clave nueva para crear otro cobro.
idempotency_hit: true y no crea otro. Los montos se comparan por valor
(100 equivale a 100.00); glosa es texto de presentación y no forma parte
de la identidad del replay. Consulta el estado vivo con
GET /v1/payins/{payinID}.
Dinero y estado (402 / 404 / 409 / 422 / 429)
| HTTP | error | Significado |
|---|---|---|
| 402 | insufficient_funds | Saldo disponible insuficiente — en transferencias banking salientes el chequeo incluye la comisión del riel (saldo >= monto + comisión); la operación no se crea si no se cumple |
| 404 | not_found | Recurso inexistente (o de otra cuenta) |
| 404 | not_available | El documento no existe en el idioma pedido |
| 404 | country_not_found | Código de país ISO 3166-1 alpha-2 desconocido (catálogo de ciudades) |
| 404 | bank_not_found | El routing number o SWIFT/BIC no está en el directorio bancario embebido — el formulario de payout/contraparte sigue manual |
| 404 | postal_code_not_found | Código postal desconocido, o un país sin dataset (lookup por código postal) — los campos de dirección siguen manuales |
| 404 | recipient_not_found | Destino de transferencia inexistente |
| 404 | verification_not_found | La cuenta aún no tiene ninguna verificación enviada (GET /v1/me/verification/report antes del onboarding) |
| 409 | duplicate | El recurso ya existe |
| 409 | receipt_not_available | El comprobante del payout no está disponible mientras espera el screening técnico o después de un fallo antes del débito; espera un estado financiero final |
| 403 | verification_requires_2fa | Un link nuevo de KYC/KYB self-service exige un TOTP confirmado o un passkey registrado; un link abierto se re-sirve antes de este gate. Solución: enrola un factor y reintenta POST /v1/me/verification/link |
| 403 | verification_required | Tu cuenta aún no aprobó su verificación de identidad (persona=KYC, empresa=KYB); hasta entonces se bloquean la creación autenticada de payins, collect, cuentas de depósito dedicadas, cobros con tarjeta guardada y suscripciones — pide tu link en POST /v1/me/verification/link; los abonos pasivos y las lecturas siguen disponibles |
| 422 | verification_required | La operación exige el verification_id de una verificación aprobada del tercero (alta banking de terceros, tarjeta designada) |
| 422 | verification_not_approved | La verificación referenciada aún no está aprobada |
| 422 | verification_kind_mismatch | El kind de la verificación no calza con el producto (KYC ⇒ persona/INDIVIDUAL, KYB ⇒ empresa/COMPANY) |
| 422 | verification_invalid | Referenciaste una verificación de onboarding propio donde se exige la de un tercero |
| 403 | company_account_required | La verificación de terceros (links/submissions KYC-KYB) es solo para cuentas empresa |
| 409 | already_verified | Pediste link de onboarding con la cuenta ya verificada |
| 409 | identity_locked | Con la verificación aprobada, display_name, tax_id y country vienen de la identidad verificada y no se cambian por PATCH /v1/me; contacta al soporte |
| 409 | no_screening | Rescreen/monitoreo AML sin un screening previo |
| 409 | no_banking_customer | Operación Banking clásica sin perfil bancario genérico (POST /v1/banking/customer primero); EUR Banking usa un vIBAN directo |
| 400 | banking_eur_requires_viban | Las cuentas Banking EUR se abren como vIBAN. Solicita purpose: "banking_eur" desde Operar EUR en vez de crear un customer Banking genérico |
| 409 | banking_customer_exists | La cuenta ya tiene perfil bancario (es uno por cuenta) |
| 409 | idempotency_conflict | El claim del mismo perfil banking sigue pendiente o cambió el payload — conserva la misma solicitud y espera la reconciliación |
| 503 | banking_recovery_pending | El resultado del alta es ambiguo — operaciones debe reconciliar el claim durable antes de reintentar con una clave nueva |
| 409 | bank_ref_conflict | La referencia bancaria ya fue reclamada por otra operación (la respuesta la nombra con claimed_by/claimed_kind cuando pertenece a tu tenant) — corrige la evidencia en vez de reintentar con otra referencia |
| 503 | bank_ref_recovery_pending | Una confirmación anterior dejó la referencia en estado ambiguo y la plataforma está reconciliando el claim durable — reintenta la misma confirmación (misma referencia e idempotency key); el reintento reanuda en vez de duplicar |
| 400 | unsupported_document_type | El tipo de documento bancario no está admitido. Usa uno de los tipos incluidos en la allowlist de documentos bancarios. |
| 400 | invalid_document_file | El archivo del documento bancario está vacío, no se puede leer, está corrupto o no es PDF, JPEG ni PNG. Sube un archivo válido. |
| 422 | currency_not_supported | Sin tasa FX para esa moneda |
| 422 | core_rejected | El procesador rechazó la operación — cuando el mensaje reporta una dirección de facturación incompleta (o estado/región faltante), la tarjeta guardada no tiene una dirección utilizable en archivo: pide al pagador guardarla de nuevo con save_card: true ; el procesador también puede rechazar un payout argentino antes del débito si el alias no resuelve o si un alias USD resuelve a CVU; corrige el beneficiario y reintenta con una clave de idempotencia nueva. |
| 400 | invalid_payload | En method: "card", expires_at debe ser RFC3339, quedar al menos 5 minutos hacia adelante y no superar 48 horas |
| 422 | checkout_expiring_soon | El link de checkout vence en menos de 5 minutos. Pide al comercio un link nuevo antes de pagar con tarjeta |
| 429 | too_many_open_card_sessions | La cuenta tiene 50 sesiones de tarjeta abiertas y no hay una sesión pending sin intentos que se pueda desalojar — completa o espera que venza una sesión existente antes de crear otra |
| 503 | card_recovery_pending | La plataforma está reconciliando un cobro con tarjeta ambiguo. Reintenta con la misma clave de idempotencia; no generes una nueva ni un segundo cobro |
| 409 | core_charge_terminal | El cobro de tarjeta subyacente ya tiene un estado final, por lo que la plataforma no lo volverá a acreditar — lee el estado actual del payin/cobro y no crees un segundo cobro |
| 503 | card_reuse_unavailable | La plataforma no pudo verificar un cobro con tarjeta abierto existente. Reintenta la solicitud original con la misma clave de idempotencia; no crees un segundo cobro |
| 503 | core_reuse_unavailable | El core no devolvió una sesión de tarjeta completa y recuperable. Reintenta la solicitud original con la misma clave de idempotencia |
| 422 | recipient_unavailable | La cuenta destino no puede recibir |
| 422 | recipient_ambiguous | Más de una cuenta comparte el teléfono de to_phone (usa to_account_id o to_email) |
| 422 | contact_not_linked | El contacto no tiene cuenta CBPay asociada para transferirle |
| 422 | no_saved_destination | El contacto no tiene destino guardado para ese corredor/chain |
| 422 | wallet_limit_reached | La cuenta ya tiene su wallet de esa combinación red+activo (depósito: todas las cuentas; segregadas: personas) |
| 422 | insufficient_gas | La wallet segregada no tiene gas nativo (TRX/ETH) para el fee de red; fondea la dirección y reintenta |
| 409 | idempotency_conflict | Otra creación/envío de wallet con la misma clave sigue en curso; reintenta con la misma clave |
| 400 | physical_temporarily_unavailable | La emisión de tarjetas físicas nuevas está pausada temporalmente; solicita una tarjeta digital. Las físicas existentes siguen operativas. |
| 409 | card_limit_reached | La cuenta persona ya tiene una tarjeta viva o una solicitud de tarjeta abierta; resuelve la solicitud existente antes de pedir otra |
| 409 | card_cancelled | La tarjeta ya está cancelada y no se puede modificar |
| 409 | card_not_pending | Solo tarjetas en pending_activation se pueden activar |
| 409 | cardholder_kyc_pending | El titular designado requiere documentos de identidad |
| 400 | invalid_occupation | occupation no es un código del catálogo (GET /v1/cards/catalog/occupations) |
| 400 | invalid_kind_of_business | kind_of_business no es un código del catálogo (GET /v1/cards/catalog/business-activities) |
| 422 | issuer_data_incomplete | Faltan o son inválidos los campos del emisor después de ensamblar el request, el autofill de verificación y los datos KYB; corrige las claves indicadas en message y reintenta |
| 422 | screening_required | La cuenta no tiene un screening AML de verificación para derivar el PEP del titular; completa el screening y reintenta el mismo request de tarjeta |
| 422 | cardholder_name_too_long | first_name y last_name de la persona superan juntos el límite de 22 caracteres impresos por el emisor; acorta el nombre y reintenta |
| 400 | invalid_settlement_asset | settlement_asset no es USDT, USDC, BTC ni GOLD |
| 400 | settlement_asset_disabled | Tu organización tiene deshabilitado ese asset como origen de settlement |
| 422 | settlement_limit_exceeded | La operación supera el límite por operación de los assets volátiles (BTC/GOLD/SILVER/PLATINUM); usa USDT/USDC o divide la operación |
| 422 | settlement_daily_limit_exceeded | La cuenta superó su volumen de 24 h en assets volátiles (BTC/GOLD/SILVER/PLATINUM); usa USDT/USDC o reintenta más tarde |
| 422 | guard_diverged | La referencia de precio BTC divergió más allá del price guard pre-trade; espera convergencia o divide la operación y reintenta con la misma clave de idempotencia |
| 400 | invalid_pair | Swap con la misma moneda de origen y destino |
| 400 | amount_too_small | El monto del swap no alcanza la unidad mínima de la moneda destino |
| 400 | swap_asset_disabled | Una de las monedas del swap está deshabilitada para tu organización |
| 409 | already_paid | El link de cobro universal ya se pagó por otro método |
| 409 | checkout_not_pending | Un intento de collect del checkout ya no acepta datos porque otro intento decidió el payin; lee el estado y no crees otro link |
| 410 | checkout_expired | El link de cobro universal venció sin pago |
| 422 | method_unavailable | El método elegido en el link de cobro no está disponible para ese link o país |
| 400 | country_required | Materialización fiat del link de cobro sin ?country=XX |
| 400 | currency_required | El país ofrece el método del link de cobro en varias monedas; falta ?currency=YYY |
| 422 | country_unavailable | Ese país no tiene métodos de pago disponibles en el link de cobro |
| 422 | collect_otp_failed | El rail rechazó el envío de la clave OTP del cobro pull del link |
| 422 | collect_rejected | El rail rechazó el cobro pull del link (OTP inválida o datos incorrectos); el link sigue pendiente |
| 422 | provider_rejected | Para VE/VES/c2p, no llames a /collect/otp; el pagador entrega la claveDinamica generada por su banco en el campo otp del collect. La señal interna del adapter es collect_otp_unsupported. |
| 422 | settlement_asset_disabled | El settlement_asset del link de cobro está deshabilitado para tu organización |
| 422 | checkout_amount_mismatch | La transferencia CBPay no cubre el monto vigente del link de cobro; el mensaje trae el monto actualizado |
| 503 | checkout_recovery_pending | La opción de pago elegida en el checkout está en reconciliación. Reintenta la misma solicitud de materialización; no crees una segunda opción de pago |
| 422 | stored_card_revoked | La tarjeta guardada está revocada; no acepta más cobros |
| 422 | verification_required | QR Crypto POS: registra al merchant con el verification_id de su KYC/KYB de terceros aprobado |
| 422 | merchant_disabled | El merchant QR Crypto POS está deshabilitado; reactívalo antes de generar cobros |
| 422 | nothing_received | El cobro QR Crypto POS no ha recibido ningún pago on-chain: no hay nada que devolver |
| 422 | refund_exceeds_received | La devolución supera lo recibido menos lo ya devuelto del cobro QR Crypto POS |
| 503 | refund_recovery_pending | El vínculo de la devolución está temporalmente no disponible; reintenta con la misma clave de idempotencia y no origines otro retiro |
| 400 | to_address_required | La devolución QR Crypto POS (y el retiro crypto) exige la dirección destino explícita |
| 422 | deposit_account_limit_reached | Las cuentas persona y los corredores no soportados o existentes conservan una cuenta por corredor; una empresa admite hasta 50 cuentas banking por corredor habilitado |
| 400 | invalid_label | El apodo local de la cuenta supera 60 caracteres; acórtalo y reintenta |
| 409 | alias_pending | La CVU banking empresa AR/ARS aún no tiene alias; asígnalo con el PUT de bank-alias antes de leer saldo o movimientos |
| 422 | purpose_not_supported | Saldo y movimientos solo están disponibles para instrumentos con purpose: "banking" |
| 422 | ambiguous_source_instrument | Hay varias fuentes banking BO/BOB activas; envía el UUID elegido en source_instrument_id |
| 422 | invalid_source_instrument | La fuente elegida no es un instrumento banking BO/BOB activo; selecciona un destino válido |
| 409 | intent_abandoned | La verificación del tercero fue rechazada; crea un nuevo vínculo de verificación antes de pedir banking |
| 409 | deposit_account_conflict | El core devolvió un destino de depósito ya asignado a otra organización — reconcilia antes de reintentar |
deposit_account_not_recoverable | El destino pendiente no es un instrumento MX/MXN/bank_transfer recuperable |
| 422 | export_rejected | El procesador rechazó el export de la llave de la wallet segregada |
| 422 | stored_card_corridor_mismatch | La tarjeta guardada pertenece a otro corredor país/moneda distinto del cobro |
| 409 | subscription_state | La suscripción no está en un estado que permita esa acción (ej. pausar un plan cancelado) |
| 409 | email_required | El login no tiene un email real; configura uno con POST /v1/me/email/change |
| 422 | payin_not_refundable | El cobro no está acreditado o no tiene credencial del procesador; no se puede devolver |
| 422 | refund_not_supported | Ese rail no admite devoluciones (QR, transferencia anunciada, cuenta dedicada, collect). Los cobros POS se devuelven por el riel crypto |
| 422 | refund_exceeds_payin | La devolución supera lo que queda por devolver del cobro; tu saldo no se tocó |
| 422 | settlement_pending | El saldo del cobro sigue programado para settlement y no se puede devolver hasta liberarse (a settle_at o por liberación del admin de la organización) |
| 400 | invalid_amount | El amount de la devolución debe ser un decimal positivo en la moneda del cobro |
| 503 | refund_event_pending | El resultado de la devolución quedó guardado, pero todavía se está persistiendo su evento final. Reintenta con la misma clave de idempotencia; no envíes otra devolución |
| 503 | payin_event_pending | El payin quedó acreditado, pero su evento final todavía se está reconciliando. Reintenta con la misma clave de idempotencia; no crees un nuevo payin |
Cumplimiento (403 / 503)
| HTTP | error | Significado |
|---|---|---|
| 403 | compliance_hold | La operación fue retenida por los controles de cumplimiento de la plataforma. No es un error de tu request: contacta a soporte con el timestamp — por política no se informa la razón exacta |
| 403 | geo_restricted | El servicio o la operación no están disponibles para la jurisdicción de origen o de la contraparte |
| 503 | compliance_check_unavailable | No se pudo evaluar compliance y el payout no pudo guardarse en su cola técnica de screening; reintenta con la misma idempotency key. Cuando la cola está disponible, POST /v1/payouts devuelve 202 con status: pending. Los demás errores de validación y seguridad conservan sus códigos |
| 422 | travel_rule_required | Retiro on-chain sobre el umbral Travel Rule sin datos del beneficiario — agrega travel_address o wallet_type: "self_hosted" + beneficiary_name (guía crypto) |
| 422 | travel_rule_beneficiary_required | Falta beneficiary_name en un retiro sujeto a Travel Rule |
| 422 | travel_rule_address_mismatch | Tu to_address no coincide con la dirección de pago aprobada por la institución receptora — omítela o usa la del intercambio |
| 422 | travel_rule_rejected | La institución receptora rechazó la transferencia; verifica los datos del beneficiario |
| 422 | travel_rule_pending | La institución receptora aún no resuelve el intercambio; reintenta con la misma clave de idempotencia |
| 422 | travel_rule_incomplete_approval | La institución receptora aprobó sin entregar dirección de pago; contacta a soporte |
| 503 | travel_rule_unavailable | Intercambio Travel Rule temporalmente no disponible; reintenta con la misma clave de idempotencia |
Qscore
Errores de los endpoints del buró de crédito (guía).| HTTP | error | Significado |
|---|---|---|
| 400 | purpose_required | Falta purpose al crear un informe — la ley de protección de datos exige declararlo (credit_evaluation, tenant_screening, hiring, supplier_onboarding u other) |
| 400 | invalid_purpose | El purpose no es uno de los valores permitidos (credit_evaluation, tenant_screening, hiring, supplier_onboarding, other) — corrige el valor. self_access se rechaza aquí: tu propio informe solo va por POST /v1/qscore/my-report |
| 400 | invalid_doc_id | El doc_id no es válido para el country indicado (ej. dígito verificador de RUT incorrecto en Chile) — corrige el formato del documento |
| 400 | invalid_subject_type | subject_type no es person/company y no se pudo inferir del documento — envíalo explícito |
| 400 | invalid_tax_id | El tax_id verificado de la cuenta no es válido para su país (informe self) — contacta a soporte para corregir tus datos verificados |
| 403 | kyc_required | Generar tu propio informe exige un KYC/KYB aprobado — completa primero la verificación de identidad |
| 403 | report_required | Activar el monitoreo exige un informe comprado de ese sujeto — compra uno primero (guía); por privacidad, un sujeto inexistente recibe esta misma respuesta |
| 404 | no_score | El sujeto aún no tiene un score calculado — compra un informe primero |
| 404 | pdf_not_ready | El PDF del informe aún no está disponible — consulta el detalle hasta status=ready (el webhook risk_report_ready te avisa) |
| 409 | no_tax_id | La cuenta verificada no tiene tax_id registrado, así que el informe self no puede resolver su sujeto — completa primero tus datos verificados |
| 409 | identity_mismatch | El tax_id de la cuenta no calza con el documento de identidad verificado (informe self) — contacta a soporte; tus datos verificados deben ser consistentes |
| 422 | unsupported_country | Este flujo de fraude/identidad de Qscore no está disponible para el país seleccionado — usa un país compatible o contacta a soporte |
| 503 | recovery_pending | El informe de fraude todavía se está finalizando — consulta el informe con las mismas credenciales y reintenta el PDF cuando llegue a ready |
| 400 | no_valid_items | Todas las filas del lote fueron rechazadas (invalid_doc_id / duplicate_in_batch) y no se creó ningún lote — valida el archivo localmente (cada doc_id debe pasar el dígito verificador del país y ser único) y reenvía con una clave de idempotencia nueva |
| 400 | too_many_items | Un lote acepta a lo más 5.000 sujetos — parte la cartera en varios lotes, cada uno con su propia clave de idempotencia |
| 409 | already_decided | El link de consentimiento ya fue decidido (granted, revoked o expired) y no puede transicionar de nuevo — crea un link nuevo si necesitas otra autorización |
| 409 | link_inactive | La conexión bancaria detrás del consentimiento no está active (la sesión del widget expiró o el vínculo se revocó) — el titular debe reconectar desde el mismo link |
| 409 | holder_mismatch | El documento verificado por el banco no calza con el doc_id del sujeto — una cuenta de OTRO documento jamás otorga el consentimiento; verifica que creaste el link para el documento correcto |
| 409 | seal_companies_only | El sello público Qscore es solo para cuentas empresa — las cuentas persona no tienen sello (guía) |
| 409 | seal_not_eligible | El Qscore de la cuenta no califica ahora para un sello público (banda A o B con una evaluación de no más de 90 días) — compra un informe fresco (guía) y, si la banda sigue bajo B, el sello no estará disponible hasta que el score mejore |
| 404 | no_active_seal | La cuenta no tiene un sello activo que revocar — activa uno primero con POST /v1/qscore/my-seal; un sello revocado queda revocado permanentemente (crea uno nuevo) |
Firewall transaccional
Errores de la revisión de operaciones retenidas por el firewall transaccional (guía). La retención en sí no es un error: el create responde202 Accepted con status: in_review y review_id.
| HTTP | error | Significado |
|---|---|---|
| 400 | invalid_status | El filtro status no es válido — usa in_review, info_requested, released, rejected o all |
| 400 | invalid_range | Fechas from/to inválidas — formato YYYY-MM-DD (zona horaria de tu organización) |
| 400 | invalid_name | Falta el nombre del archivo en el query param name (máx. 200 caracteres, sin separadores de ruta) |
| 400 | empty_file | El body del archivo llegó vacío |
| 404 | not_found | La revisión o el archivo no pertenecen a tu cuenta — por diseño nunca se responde 403 |
| 409 | not_awaiting_info | La revisión no está esperando información (ya volvió a in_review o tiene decisión final) — consulta su estado actual |
| 413 | file_too_large | El archivo supera el límite de 50 MB — comprímelo o divídelo |
| 415 | unsupported_file_type | Tipo no permitido — usa PDF, PNG, JPEG, WEBP, TXT, CSV, DOC(X) o XLS(X) con el header Content-Type correcto |
| 422 | file_limit_reached | La revisión ya tiene 20 archivos |
| 503 | firewall_unavailable | No se pudo evaluar la política o persistir la revisión — reintenta con la misma clave de idempotencia |
| 503 | storage_unavailable | El almacenamiento de archivos no está disponible — reintenta en unos segundos |
Eventos en tiempo real (SSE)
Códigos deGET /v1/events y su historial.
| HTTP | error | Significado |
|---|---|---|
| 400 | invalid_event_type | Un valor de ?types= no está en el catálogo — el message lista los válidos |
| 429 | too_many_streams | Se alcanzó el límite de streams simultáneos (por cuenta o por organización) — cierra uno antes de abrir otro |
| 429 | rate_limited | Demasiadas aperturas de stream desde esta IP (600 por hora) — la cuota cuenta intentos, no conexiones vivas: corta el bucle de reconexión y aplica backoff |
| 500 | streaming_unsupported | La conexión no soporta streaming (un proxy intermedio está bufferizando) — quita el buffering o usa webhooks |
| 503 | stream_unavailable | No se pudo abrir el stream; reintenta con backoff conservando tu Last-Event-ID |
Firma de mensajes y vinculación de wallets
Códigos de la firma de mensajes con wallets (EIP-191 en EVM, TIP-191 en TRON): firma server-side con wallets segregadas (POST /v1/segregated-wallets/{id}/signatures, que emite un comprobante de firma verificable públicamente) y vinculación de wallets externas por desafío (POST /v1/wallet-links/challenges → firmas el desafío con tu wallet → POST /v1/wallet-links/verify).
| HTTP | error | Significado |
|---|---|---|
| 400 | unsupported_chain | La chain debe ser tron o eth |
| 400 | invalid_statement | El statement supera los 280 caracteres — acórtalo (ojo: el sobre firmado acepta máximo 140) |
| 409 | proof_not_signable | El comprobante ya no está en un estado firmable (ya firmado, expirado o cancelado) — solicita uno nuevo |
| 409 | custody_transferred | La custodia de la wallet fue transferida al cliente, así que la firma server-side ya no es posible — firma con tu propia clave |
| 409 | challenge_consumed | Este desafío ya fue usado o ya no es válido — solicita uno nuevo |
| 410 | challenge_expired | Este desafío expiró — solicita uno nuevo y fírmalo dentro de su ventana de validez |
| 422 | signature_mismatch | La firma no corresponde a la dirección del desafío — firma el mensaje exacto del desafío con la wallet que estás vinculando |
| 422 | sign_rejected | El firmante rechazó la solicitud — el message trae la razón saneada. Un statement de 141–280 caracteres también cae aquí (el sobre acepta máximo 140) |
Servicio (5xx)
| HTTP | error | Significado |
|---|---|---|
| 500 | internal_error | Error inesperado; reintenta con la misma clave de idempotencia |
| 500 | fee_config_invalid | La configuración de comisiones de la cuenta es inválida; contacta al soporte (la operación no se ejecutó) |
| 502 | rates_unavailable | Tasas FX temporalmente no disponibles |
| 502 | core_unavailable | Procesador temporalmente no disponible |
| 502 | core_invalid_response | El procesador devolvió una respuesta inesperada; reintenta con la misma clave de idempotencia |
| 502 | compliance_unavailable | Screening AML temporalmente no disponible |
| 503 | verifications_unavailable | Verificación de identidad temporalmente no disponible |
| 503 | org_credential_missing | Servicio en configuración; contacta al soporte de CBPay |
| 503 | withdrawals_unavailable | Retiros on-chain no habilitados para el corredor |
| 503 | pricing_unavailable | Precio de ejecución de BTC/GOLD/SILVER/PLATINUM no disponible o desactualizado; reintenta más tarde o liquida en USDT/USDC |
| 503 | channel_unavailable | El canal de payout está temporalmente no disponible; reintenta más tarde con la misma clave de idempotencia |
| 503 | webhook_processing_pending | Un evento webhook entrante ya está siendo procesado; reintenta la misma entrega después de un backoff corto y no crees una operación nueva |
| 503 | export_unavailable | El export de llaves privadas de wallets segregadas no está habilitado en este entorno |
Cómo manejarlos
- 4xx de validación: corrige el request. No reintentes igual.
- 402: fondea la cuenta y reintenta (clave de idempotencia nueva solo si la operación nunca se creó).
- 5xx / timeouts: reintenta con la misma clave de idempotencia; la operación nunca se duplicará.
Qscore fraude e Index
| HTTP | code | Significado y solución |
|---|---|---|
| 400 | invalid_period | El período del Index no es YYYY-Q1 a YYYY-Q4 — usa un trimestre cerrado |
| 429 | too_many_attempts | La verificación pública de fraude está rate-limited — espera y reintenta |
| 502 | generation_failed | Falló la generación después del cargo — el fee se reembolsa; usa una nueva idempotency key |
Ciclo de vida del corredor
| HTTP | Código | Significado y solución |
|---|---|---|
| 409 | corridor_disabled | El corredor seleccionado está deshabilitado administrativamente. Usa otro método habilitado o contacta al operador de la organización. |
Banking creation recovery errors
| Code | HTTP | Meaning and action |
|---|---|---|
idempotency_key_mismatch | 400 | Header/body keys differ or the same key is reused with a different request hash. Correct the request or use a new key. |
idempotency_conflict | 409 | The same key is already claimed with a conflicting payload. Do not resend with a new payload. |
idempotency_failed | 409 | The claim is terminally failed. Start a new operation with a new key after reviewing the failure. |
claim_not_pending | 409 | The requested human recovery is no longer pending. Read the claim and use the terminal result. |
claim_customer_owned_elsewhere | 409 | The provider customer is already linked to another account. Stop and investigate ownership. |
banking_customer_creation_in_progress | 409 | A lock is held by another banking operation. Retry the read/recovery flow later. |
banking_recovery_pending | 503 | The result or refund remains ambiguous. Do not originate a second provider request; use the recovery endpoint. |
banking_invalid_response | 422 | Provider account ownership did not match the claimed customer’s ProviderID. |
Errores de recuperación de creaciones banking
| Código | HTTP | Significado y acción |
|---|---|---|
claim_identity_mismatch | 422 | La identidad del cliente del proveedor no coincide con la solicitud banking original. Detén la recuperación y revisa el claim. |
claim_not_pending | 409 | El claim ya no está pendiente. Lee el resultado terminal en vez de repetir la recuperación. |
claim_customer_owned_elsewhere | 409 | El cliente del proveedor pertenece a otra cuenta. Detén el proceso y revisa la titularidad. |
banking_recovery_pending | 503 | El resultado del proveedor sigue ambiguo. Usa la ruta administrativa; no origines otra creación. |
Errores de Banking EUR y vIBAN
| Code | Meaning and action | ||
|---|---|---|---|
banking_customer_incomplete | The banking customer lacks the provider identity required for the operation. Complete the customer/KYC/KYB data, then retry with the same idempotency key. | ||
registrant_incomplete | 422 | Solicitud de vIBAN | Al perfil KYC/KYB verificado le faltan campos obligatorios del registrant; completa los datos de documento o incorporación indicados y reintenta la misma solicitud. |
provider_rejected | The upstream banking operation was rejected. Do not create a new money operation automatically; inspect the resource and follow its retry/reconciliation state. | ||
customer_id_required | A banking operation requires an explicit customer identifier. Provide the customer ID from the account-owned resource. | ||
iban_required | The operation requires the IBAN associated with the owned virtual account. | ||
operation_in_progress | The same banking operation is still being reconciled. Poll the resource and retry with the original idempotency key. | ||
ownership_required | The resource belongs to another organization or account. Use only an owned resource; never guess or substitute an ID. |
Códigos de mensajería masiva
Estos códigos provienen de los endpoints de administración de organización. Se incluyen aquí para que los SDK compartidos mantengan un solo catálogo.| HTTP | error | Causa | Solución |
|---|---|---|---|
| 400 | invalid_channels | No se seleccionó un canal válido | Envía email, notification o ambos |
| 400 | invalid_content | Subject/body vacío o demasiado largo | Usa subject de 1–160 runas y body de 1–4000 runas |
| 400 | invalid_reason | Falta la razón de rechazo o es demasiado larga | Envía una razón auditada de 1–500 runas |
| 400 | invalid_audience | Modo, filtros o IDs inválidos | Usa filters o 1–5000 IDs de cuentas de la organización |
| 403 | named_admin_required | El actor no es un administrador nombrado | Usa un administrador nombrado god o super_admin |
| 403 | partner_forbidden | Un bank partner intentó usar un broadcast de organización | Usa un administrador permitido |
| 409 | empty_audience | Ninguna cuenta coincidió al enviar/aprobar | Corrige la audiencia y vuelve a enviar |
| 409 | audience_too_large | Los filtros coinciden con más de 20000 cuentas | Acota los filtros y vuelve a enviar |
| 409 | second_approver_required | El creador intentó aprobar su campaña | Pide aprobación a otro God nombrado |
Errores de Banking EUR y wallets de empresa
| HTTP | Código | Qué hacer |
|---|---|---|
| 409 | virtual_iban_limit_reached | La persona ya tiene un IBAN virtual para ese propósito. Reúsalo; el límite no aplica así a empresas. |
| 409 | no_fee_charged | Este IBAN virtual no tuvo cobro (el primer fondeo es gratis). Nada que devolver. |
| 409 | wallet_not_ready | La wallet sigue pending/provisioning. Consulta el detalle hasta que quede active. |
| 422 | virtual_iban_limit_reached | Se alcanzó el límite persona-por-propósito al reservar. No crees una segunda clave. |
| 422 | registrant_incomplete | Completa los datos KYC/KYB o de incorporación indicados en message y repite la misma solicitud durable. |
| 502 | wallet_reservation_failed | La reserva no devolvió una referencia utilizable. Concilia antes de reintentar. |
| 502 | wallet_reservation_status_failed | Falló la lectura de estado. Conserva order_reference o client_order. |
| 502 | wallet_read_failed | No se pudo leer la respuesta live o el monto EUR. Reintenta la lectura después de revisar el estado. |
| 502 | wallet_statement_failed | No se pudo leer el statement. Usa una ventana válida de días completos y reintenta la lectura. |
Política de integraciones de cuenta
| HTTP | error | Significado y solución |
|---|---|---|
| 400 | email_domain_blocked | El dominio está bloqueado para registro o cambio de email; usa otro dominio permitido. |
| 400 | invalid_secret | El secreto del webhook debe tener entre 16 y 256 caracteres. |
| 403 | session_required | Crear API keys y webhooks de cuenta exige JWT humano, no API key. |
| 403 | integration_company_only | Una persona necesita grant vigente; una empresa necesita KYB aprobado. |
| 403 | integration_kyb_required | Aprueba el KYC/KYB antes de crear o reactivar la integración. |
| 403 | account_blocked | La cuenta no está activa; solicita restaurarla. |
| 403 | otp_required | Completa el OTP api_key_create o webhook_manage y reintenta. |
| 403 | integration_forbidden | La cuenta no puede usar integraciones; consulta GET /v1/integration-status y resuelve el motivo. |
Disputas y fraude
| HTTP | Código | Resolución |
|---|---|---|
| 400 | idempotency_key_required | Envía la clave en body o header para una acción financiera. |
| 400 | invalid_payload | Corrige monto, fecha, UUID, archivo multipart o campo requerido. |
| 404 | not_found | El caso, importación, fila, evidencia o cuenta está fuera del scope. |
| 409 | case_already_open | Revisa el caso abierto del payin; no abras otra clave. |
| 409 | payin_not_credited | El payin no está credited, por lo que no hay saldo que retener; espera la acreditación antes de abrir un caso o vincular una fila importada. |
| 409 | second_approver_required | Otro admin nombrado debe cerrar el caso. |
| 409 | invalid_state | La transición solicitada no aplica al estado actual. |
| 409 | bind_failed | La fila ya no está unmatched o el payin no puede asociarse. |
| 409 | import_in_progress | Una importación con esta clave sigue en curso; espera y repite con la misma clave. |
| 503 | pack_unavailable | Reintenta cuando se recupere storage/render. |
| 503 | storage_unavailable | Recupera storage privado y reintenta la evidencia. |
Errores de cuenta de fondeo SEPA
Estos errores se devuelven antes de debitar o despachar un payout cliente o una operación Banking EUR:| HTTP | error | Significado y solución |
|---|---|---|
| 400 | invalid_request | source_virtual_iban_id debe ser un UUID válido. |
| 404 | not_found | El IBAN virtual explícito no pertenece a la cuenta. |
| 422 | funding_account_required | No existe un IBAN virtual asignado y activo para el propósito requerido. Usa una fuente activa para este flujo. |
| 422 | ambiguous_source_viban | Hay más de una cuenta EUR activa. Envía el source_virtual_iban_id elegido. |
| 503 | funding_account_unavailable | La consulta del origen está temporalmente no disponible. Reintenta con la misma clave de idempotencia; no se debitó ni despachó nada. |
Errores de límites money-out
| HTTP | error | Significado |
|---|---|---|
| 422 | amount_below_minimum | El monto está bajo el mínimo efectivo; consulta GET /v1/org/txn-firewall/limits/effective. |
| 422 | amount_above_maximum | El monto supera el máximo efectivo; revisa la política antes de reintentar. |
| 422 | velocity_limit_exceeded | Una transferencia interna superó un tope móvil de monto o cantidad. Payouts y retiros entran a review con reason=velocity_limit. |
| 503 | limits_unavailable | No se pudieron evaluar los límites antes del débito; reintenta con la misma clave de idempotencia. |
dispute_fiat_unsupported
No se puede abrir una controversia para un payin acreditado en BOB, MXN o ARS retenidos. Usa un crédito USDT soportado o espera soporte para controversias fiat.
Aliases bancarios argentinos y alias del perfil
| HTTP | error | Significado / acción |
|---|---|---|
| 400 | missing_alias | La creación de una cuenta de depósito AR/ARS en la plataforma debe incluir el bank_alias elegido por el caller |
| 400 | invalid_alias | bank_alias debe tener 6–20 caracteres ASCII de [A-Za-z0-9.-] y al menos una letra |
| 400 | invalid_account | El core no pudo resolver el número de cuenta de depósito enviado |
| 400 | invalid_request | El valor del body del alias de perfil no coincide con un candidato derivado del nombre verificado, o se envió bank_alias a un corredor no compatible |
| 409 | alias_already_set | El alias del perfil es permanente y ya fue fijado |
| 409 | alias_taken | Alias del perfil: todos los candidatos derivados del nombre verificado están ocupados; contacta soporte. No se resuelve inventando un valor |
| 422 | alias_taken | Alias bancario: el sistema bancario argentino ya usa ese valor; elige otro |
| 422 | alias_unsupported | El riel de la cuenta de depósito no admite aliases bancarios |
Ceremonia del Contrato Marco Grupo CB
Estos errores aplican aPOST /v1/me/contracts/envelopes/{envelopeID}/sign y
a los recursos de sobres. El mensaje puede generalizarse por privacidad; el
código es el contrato estable para la integración.
| HTTP | Código | Causa y solución |
|---|---|---|
| 400 | idempotency_key_required | La emisión admin exige key en body o Idempotency-Key; repite con una key estable. |
| 400 | invalid_idempotency_key | La key es inválida o demasiado larga; usa una key más corta. |
| 400 | invalid_reason | Void exige un motivo no vacío; envíalo en el body. |
| 400 | invalid_content_type | La biblioteca acepta image/png, image/jpeg o image/jpg. |
| 400 | empty_file | La carga no tiene bytes; envía el archivo original. |
| 400 | invalid_image | El archivo no es PNG/JPG válido; expórtalo nuevamente. |
| 403 | contract_counsel_required | La emisión en inglés exige aprobación de counsel; apruébala o usa español. |
| 403 | human_session_required | Firmar exige sesión humana; las API keys no pueden firmar. |
| 403 | account_blocked | La cuenta no está activa; pide al admin restaurarla. |
| 401 | invalid_otp | OTP inválido, vencido o ya usado; envía uno nuevo en X-OTP-Token. |
| 409 | contract_invalid_state | El sobre ya está completado o voided; no repitas la operación. |
| 422 | contract_template_superseded | El sobre se emitió con una versión anterior de la plantilla; pide reemisión antes de firmar. |
| 413 | file_too_large | La carga raw supera 5 MiB o la imagen normalizada supera 8 MiB. |
| 422 | invalid_lang | Usa solo es o en; los demás valores se rechazan. |
| 422 | contract_account_ineligible | El destino debe ser una empresa activa con KYB aprobado. |
| 422 | contract_unfillable | Revisa el array missing de la respuesta: puede listar datos de identidad, aprobación de counsel o pricing:<flag> cuando un servicio habilitado no tiene una fila de precio efectiva. |
| 422 | invalid_consent | El body debe llevar el booleano JSON "consent": true. |
| 422 | invalid_signer | Nombre/cargo vacíos o demasiado largos; usa owner/operator humano. |
| 422 | invalid_signature_image | signature_png no es un PNG válido o no está entintado, supera el límite de tamaño codificado/decodificado o no alcanza las dimensiones mínimas; envía una imagen válida y reintenta con un OTP nuevo. |
| 502 | storage_failed | Falló el storage privado; reconcilia el sobre antes de reintentar. |
| 502 | email_failed | Falló el email posterior a la firma; el sobre completado sigue siendo válido. |
| 503 | storage_unavailable | Storage privado no disponible; reintenta cuando se recupere. |
Handoff de ambiente
| HTTP | error | Significado y solución |
|---|---|---|
| 401 | invalid_handoff | Falta el token de handoff, expiró, ya fue consumido, o se emitió para el otro ambiente. Emite un handoff fresco y canjéalo en el mismo ambiente. |
| 401 | handoff_replayed | Este token ya fue consumido (un solo uso). Emite un handoff fresco. |
2FA y passkeys
| HTTP | error | Significado y solución |
|---|---|---|
| 403 | channel_locked_by_org | La política de la org solo permite TOTP y bloquea el registro de passkeys en esta cuenta; también rechaza desafíos cuyo channel explícito es más débil que el piso de la org. Pide a un org admin que cambie la política. |
| 409 | passkey_exists | El credential ID ya está registrado en esta cuenta. Inicia sesión con la passkey existente. |
| 409 | totp_already_enrolled | El TOTP ya está activo en esta cuenta. Autentícate con el secret existente. |
Documentos de checkout y de payouts
| HTTP | error | Significado y solución |
|---|---|---|
| 409 | materializing | Otra materialización de este link de checkout está en curso. Reintenta cuando termine. |
| 400 | invalid_file_name | El nombre de archivo está vacío, es muy largo o trae caracteres de path (/, \, ..). Envía un nombre de archivo plano. |
| 415 | unsupported_media_type | El Content-Type no es un tipo de documento aceptado. Envía PDF, JPEG o PNG. |
destination_recently_rejected
| HTTP | Código | Significado | Qué hacer |
|---|---|---|---|
| 422 | destination_recently_rejected | El banco rechazó recientemente el mismo destino normalizado para esta cuenta. No se crea el payout, no se debita saldo y la clave de idempotencia no se consume. | Primero repite la solicitud original con la misma clave. Si quieres reintentar de forma deliberada, usa una clave de idempotencia nueva y envía options.destination_retry_ack con el ID del payout rechazado más reciente. |
options diferentes devuelve idempotency_conflict
(409). Los demás métodos y los destinos sin un rechazo reciente siguen su
flujo normal de validación y despacho.
Errores de endurecimiento antiataques de autenticación
| HTTP | error | Significado y solución |
|---|---|---|
| 400 | invalid_code | El código de registro o reset no tiene 4–10 dígitos. Envíalo con la forma esperada. |
| 401 | invalid_code | La identidad o el código de confirmación/reset es inválido o vencido. Usa el último código; la respuesta es deliberadamente uniforme. |
| 401 | invalid_credentials | Falló el login, la cuenta está pendiente de verificación o quedó bloqueada temporalmente después de 8 fallos en 15 minutos. Espera o confirma el registro. |
| 502 | otp_check_failed | No se pudo consultar el servicio de verificación. Mantén el mismo flujo y reintenta después; no crees otra cuenta ni otra solicitud. |
POST /v1/auth/password/forgot siempre responde 200 para evitar enumeración. Silencia envíos reales después de 5 por cuenta por hora; POST /v1/auth/password/reset permite 8 intentos de código por cuenta cada 15 minutos.
Links de recuperación de members
| HTTP | error | Causa y acción |
|---|---|---|
| 400 | invalid_token | El token no es el valor base64url de 43 caracteres del email de recuperación. Copia lo que sigue a ?token= sin modificarlo. |
| 400 | weak_password | La nueva contraseña no cumple la política del servidor. Elige una más fuerte y usa el mismo link mientras siga vigente. |
| 401 | invalid_token | El link es inválido, venció, ya se usó o no corresponde a la org/member. Pide un link nuevo al admin de la organización. La respuesta es uniforme a propósito. |
| 502 | recovery_send_failed | No se pudo entregar el email de recuperación iniciado por el admin. Pide al admin revisar la configuración de email y disparar un link nuevo. |
| 429 | too_many_attempts | La IP superó el throttle de verificación. Espera un momento y reintenta; no automatices envíos repetidos. |
Validación de payouts US/USD
Estos errores se devuelven antes del débito en payoutsach, wire y swift:
| HTTP | error | Significado y solución |
|---|---|---|
| 400 | invalid_beneficiary | Falta un campo requerido o es inválido; revisa message, por ejemplo beneficiary.account_type. |
| 400 | invalid_amount | El monto no es un decimal positivo válido; corrígelo y crea una solicitud nueva. |
| 422 | amount_below_minimum | Un wire o swift está bajo USD 25; usa al menos 25.00. |
| 422 | prohibited_country | El país del beneficiario o banco está en el Anexo B (CU, IR, KP, SY); usa un destino permitido. |
| 400 | purpose_required | options.purpose es obligatorio en todo payout bancario US/USD; elige un valor del catálogo. |
| 400 | invalid_options | Hay una opción desconocida o enviaste purpose_detail con un propósito distinto de Other; corrige options. |
| 400 | supporting_document_required | Sube y envía la factura o recibo antes de crear el payout bancario USD. |