404 record_not_found si el ID no es un UUID, y 404 environment_key_mismatch si el recurso es del otro ambiente. La excepción es la sesión de cliente, donde un cargo que no existe responde 404 sin código.
Endpoints: Cobros · Plantillas · Cargos · Links de captura · Nequi y Daviplata · Intentos de pago · Sesión de cliente · Campañas
Un cargo que el banco rechaza no es un error HTTP: el cargo se crea (
200) y queda failed con
el motivo en remarks. Los motivos posibles están en Motivos de rechazo de
cargos.Cobros
Listar cobros
GET /payments · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 400 | Requested filter(s) `…` are not allowed. Allowed filter(s) are `id, status, reference, external_id`. | Enviaste un filtro que no existe. | Usa solo los filtros de la lista. | Sí, tras corregir |
| Sin código | 400 | Requested sort(s) `…` is not allowed. Allowed sort(s) are `created_at, paid_at`. | Enviaste un orden que no existe. | Ordena por created_at o paid_at. | Sí, tras corregir |
filter[id] o filter[status] con un valor inválido no da error: devuelve una lista vacía.
Detalle de un cobro
GET /payments/{payment_id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El cobro no existe, se eliminó o es de otra empresa. | Revisa el payment_id. | No |
Crear un cobro
POST /payments · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El campo título es obligatorio. | Falta title o amount, o un campo no cumple su formato (title de 4 a 255, description de 4 a 2.000, reference de 6 a 30, external_id de 4 a 100, currency de 3 letras en mayúscula). | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10001validation_error | 422 | El monto mínimo es COP $1.000 | amount está por debajo del mínimo de la moneda (COP 1.000, USD 1, MXN 5). | Envía un monto igual o mayor al mínimo. | Sí, tras corregir |
10001validation_error | 422 | El monto máximo por transacción no puede ser mayor a $500.000.000 | amount supera el límite por transacción de tu empresa. | Divide el cobro o pídele a soporte revisar tu límite. | No |
10001validation_error | 422 | El numero de teléfono no es valido, debe ser un numero en formato E.164 | phone no es un celular válido. | Envía el celular en formato E.164, por ejemplo +573001234567. | Sí, tras corregir |
10001validation_error | 422 | La plantilla seleccionada no existe, no está aprobada, no es una plantilla de cobro o no está disponible para esta empresa. | template_id no es una plantilla de cobro que puedas usar. | Usa un id con selectable: true de listar plantillas. | Sí, tras corregir |
10001validation_error | 422 | El campo metadata.template id está prohibido. | Enviaste template_id dentro de metadata. | Envía template_id como campo de primer nivel. | Sí, tras corregir |
10001validation_error | 422 | El balance destino no existe o no pertenece a la empresa. | target_wallet_id no es un balance tuyo en este ambiente, o es de una moneda que no puede recibir este cobro. | Usa un balance tuyo del mismo ambiente y moneda compatible. | Sí, tras corregir |
10001validation_error | 422 | The partial payment feature is not enabled for this company. | Enviaste partial_payment_config y tu empresa no tiene pagos parciales. | Quita partial_payment_config o pídele a soporte activar pagos parciales. | No |
10001validation_error | 422 | The Bre-B key is only available for payments in COP. | Pediste options.breb_key en un cobro que no es en COP, que acepta pagos parciales o que no tiene Bre-B habilitado. | Quita options.breb_key o ajusta el cobro. | Sí, tras corregir |
10001validation_error | 422 | The total percentage splits cannot exceed 100%. | Un split supera el total del cobro o apunta a una cuenta, un cliente o una billetera inválidos. El detalle llega en errors.splits.N.*. | Corrige el split indicado. | Sí, tras corregir |
10001validation_error | 422 | Los splits solo se pueden repartir sobre un cobro que liquide en pesos. | Enviaste splits con un target_wallet_id que no es COP. | Liquida en un balance COP o quita los splits. | Sí, tras corregir |
10001validation_error | 422 | El campo document url no puede apuntar al almacenamiento interno de OnePay. | document_url apunta al almacenamiento de OnePay. | Aloja el documento en tu propio almacenamiento. | Sí, tras corregir |
| Sin código | 500 | Server Error | Un error inesperado. En algunos casos el cobro alcanza a crearse antes del error. | Antes de reintentar, busca el cobro por external_id con listar cobros. | Solo si no se creó |
Actualizar un cobro
PUT /payments/{payment_id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El cobro no existe, se eliminó o es de otra empresa. | Revisa el payment_id. | No |
10001validation_error | 422 | El campo título debe contener al menos 4 caracteres. | Un campo enviado no cumple su formato (mismas reglas que al crear). | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10001validation_error | 422 | El monto mínimo es COP $1.000 | amount está por debajo del mínimo o por encima de tu límite por transacción. | Ajusta el monto. | Sí, tras corregir |
15007cant_update_payment | 422 | Este pago ya no se puede actualizar por su estado actual. | El cobro ya está aprobado, pagado por fuera, cancelado, vencido, reembolsado o en disputa. | Crea un cobro nuevo. | No |
15004payment_charge_in_progress | 422 | Este pago tiene una transacción activa en proceso. Por favor espera a que expire e intenta nuevamente. | Quieres cambiar amount o tax mientras hay un intento de pago en curso. | Espera a que el intento termine o venza. | Sí, con espera |
15003payment_already_paid | 422 | Este pago ya fue pagado. | El cobro se terminó de pagar mientras lo actualizabas. | Consulta el cobro: ya está pagado. | No |
Reenviar un cobro
POST /payments/{payment_id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El cobro no existe, se eliminó o es de otra empresa. | Revisa el payment_id. | No |
10001validation_error | 422 | La plantilla seleccionada no existe, no está aprobada, no es una plantilla de cobro o no está disponible para esta empresa. | template_id no es una plantilla de cobro que puedas usar, o viene dentro de metadata. | Usa una plantilla seleccionable como campo de primer nivel. | Sí, tras corregir |
15002cant_retry_payment | 422 | Este pago fue aprobado, no se puede reintentar | El cobro no está en un estado que se pueda reenviar. Sale también si está cancelado, vencido o reembolsado, aunque el texto diga «aprobado». | No reenvíes cobros cerrados; crea uno nuevo. | No |
Cancelar un cobro
DELETE /payments/{payment_id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El cobro no existe, se eliminó o es de otra empresa. | Revisa el payment_id. | No |
10001validation_error | 422 | El campo notify debe tener un valor verdadero o falso. | notify no es booleano. | Envía true o false, o no lo envíes. | Sí, tras corregir |
15003payment_already_paid | 422 | Este pago ya fue pagado. | El cobro ya está pagado. | No se puede cancelar; gestiona un reembolso si aplica. | No |
15004payment_cancelled | 422 | El pago fue cancelado | El cobro ya estaba cancelado. | Nada: trátalo como éxito. | No |
15001cant_cancel_payment | 422 | El pago no puede ser cancelado | El cobro es de una factura de servicio y se gestiona desde la factura. | Cancélalo desde la factura. | No |
15004payment_charge_in_progress | 422 | Este pago tiene una transacción activa en proceso. Por favor espera a que expire e intenta nuevamente. | Hay un intento de pago en curso (PSE, Bre-B u otro) que todavía puede pagarse. | Espera a que el intento termine o venza. | Sí, con espera |
payment_cancelled y payment_charge_in_progress comparten el código 15004. Distínguelos por
code_name: el primero no se reintenta, el segundo sí.Intentos de un cobro
GET /payments/{payment_id}/intents · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El cobro no existe, se eliminó o es de otra empresa. | Revisa el payment_id. | No |
Resolver un cobro de prueba
POST /payments/{payment_id}/resolve · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El cobro no existe, se eliminó o es de otra empresa. | Revisa el payment_id. | No |
10001validation_error | 422 | El campo remarks es obligatorio cuando action es reject. | Falta action o no es approve/reject, o falta remarks en un reject, o no es un motivo válido. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
| Sin código | 403 | This endpoint is only available for test payments. | Usaste la llave de producción sobre un cobro real. | Usa la llave de pruebas (sk_test_) y un cobro de prueba. | No |
| Sin código | 422 | Only payments in pending, in_progress or declined status can be resolved. | El cobro de prueba ya no está abierto. | Crea otro cobro de prueba. | No |
15003payment_already_paid | 422 | Este pago ya fue pagado. | El cobro ya tiene un intento pagado. | Consulta el cobro. | No |
Listar plantillas
GET /templates · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 400 | Requested filter(s) `…` are not allowed. Allowed filter(s) are `status, stage, provider, predefined, selectable`. | Enviaste un filtro que no existe. | Usa solo los filtros de la lista. | Sí, tras corregir |
| Sin código | 400 | Requested sort(s) `…` is not allowed. Allowed sort(s) are `name, created_at, updated_at`. | Enviaste un orden que no existe. | Ordena por name, created_at o updated_at. | Sí, tras corregir |
| Sin código | 500 | Server Error | filter[predefined] no es true ni false. | Envía filter[predefined]=true o false. | Sí, tras corregir |
Cargos
GET /charges/{id} usa el id que devuelve POST /charges. cancel y resolve usan el charge_id; refund acepta los dos.
Listar cargos
GET /charges · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 400 | Requested filter(s) `…` are not allowed. Allowed filter(s) are `id, status, created_at, currency, amount, title, payment_method_type, external_id, customer_id, key`. | Enviaste un filtro que no existe. | Usa solo los filtros de la lista. | Sí, tras corregir |
| Sin código | 400 | Requested sort(s) `…` is not allowed. Allowed sort(s) are `created_at, paid_at`. | Enviaste un orden que no existe. | Ordena por created_at o paid_at. | Sí, tras corregir |
| Sin código | 500 | Server Error | Usaste filter[amount] o filter[created_at]. Hoy esos dos filtros fallan. | Filtra por external_id, status o customer_id. | No |
Detalle de un cargo
GET /charges/{id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Pago no existe | El id no existe o es de otra empresa. Este endpoint busca por el id que devuelve POST /charges, no por charge_id. | Usa el id de la respuesta de creación. | No |
Crear un cargo
POST /charges · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El customer id seleccionado es inválido. | Un campo falta o no es válido: amount, title (5 a 100), customer_id (un cliente tuyo, y con llave de producción no de prueba), account_id o card_id (uno de los dos, del mismo cliente), splits o test_scenario. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10001validation_error | 422 | El monto máximo por transacción no puede ser mayor a $500.000.000 | amount supera el límite por transacción de tu empresa. | Divide el cargo o pídele a soporte revisar tu límite. | No |
10001validation_error | 422 | Los splits solo se pueden repartir sobre un cobro que liquide en pesos. | Enviaste splits con un target_wallet_id que no es COP. | Liquida en un balance COP o quita los splits. | Sí, tras corregir |
90005charge_persistence_lost | 503 | Charge could not be confirmed, please retry. | El cargo se procesó pero OnePay no pudo confirmar que quedó guardado. Es raro. | Busca el cargo por external_id; si no aparece, reintenta con un x-idempotency nuevo. | Sí, tras verificar |
| Sin código | 500 | Server Error | currency llegó como null, u otro error inesperado. | Omite currency o envía COP, USD o MXN. Antes de reintentar, busca el cargo por external_id. | Sí, tras verificar |
200 con el cargo en failed y el motivo en remarks. Mira Motivos de rechazo de cargos.
Crear un cargo PSE
POST /charges/pse · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El tamaño de cantidad debe ser de al menos 1000. | amount falta o es menor que 1.000, bank_id no existe, customer_id no es un cliente tuyo o redirect_url no es una URL. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
15005pse_payment_duplicate | 429 | Ya existe un pago PSE en proceso para esta misma operación. Espera a que el cliente complete el flujo actual o a que expire antes de reintentar. | Ya creaste un PSE con el mismo cliente, banco y monto hace menos de 2 minutos. La respuesta trae previous_payment_id, previous_payment_created_at y time_elapsed_seconds. | Reusa el link de previous_payment_id o espera a que pase la ventana. Cambiar external_id o reference no lo evita. | Sí, tras la ventana |
Crear un cargo Bre-B
POST /charges/bre-b · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El tamaño de cantidad debe ser de al menos 1000. | amount falta o es menor que 1.000, customer_id no es un cliente tuyo, o expires_in está fuera de 5 a 64.800 minutos. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
90100qr_generation_failed | 400 | No se pudo generar el código QR. Intente nuevamente. | No se pudo registrar la llave dinámica en Bre-B o generar el QR. No queda ningún cargo creado. | Reintenta en unos segundos con un x-idempotency nuevo. Si persiste, ofrece otro medio de pago. | Sí, con espera |
Reembolsar un cargo
POST /charges/{charge_id}/refund · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Cargo no existe | No hay un cargo tuyo con ese ID. | Usa el charge_id o el id de creación. | No |
10805charge_refunded | 422 | El cargo ya ha sido reembolsado, no se puede volver a reembolsar | El cargo ya está reembolsado, o hay otro reembolso del mismo cargo en curso. | Consulta el cargo antes de reintentar. | No |
10806charge_is_test | 422 | El cargo es de prueba, no se puede reembolsar | El cargo es de pruebas. | Los reembolsos solo aplican a cargos reales. | No |
10807charge_is_not_paid | 422 | El cargo no ha sido pagado, no se puede reembolsar | El cargo todavía no está pagado. | Espera a que quede pagado, o cancélalo si sigue en proceso. | Sí, cuando esté pagado |
| Sin código | 500 | Server Error | Falló la devolución del saldo después de marcar el cargo. | No reintentes a ciegas: consulta el cargo y escribe a soporte con el x-request-id. | No, sin verificar |
Cancelar un cargo
POST /charges/{charge_id}/cancel · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Cargo no existe | El ID no es un charge_id (por ejemplo, enviaste el id del cobro) o el cargo es de otra empresa. | Usa el charge_id. | No |
10808charge_not_cancellable | 422 | El cargo no se puede cancelar, solo cargos en estado creado o procesando pueden ser cancelados | El cargo ya está pagado, fallido o reembolsado. | Consulta el cargo; si está pagado, usa el reembolso. | No |
Resolver un cargo de prueba
POST /charges/{charge_id}/resolve · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El campo remarks es obligatorio cuando action es reject. | Falta action o no es approve/reject, o falta remarks en un reject, o no es un motivo válido. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10002record_not_found | 404 | Registro no encontrado | El cargo no existe o es de otra empresa. | Usa el charge_id de un cargo tuyo. | No |
| Sin código | 403 | This endpoint is only available for test charges. | El cargo es real. | Usa este endpoint solo con cargos de prueba. | No |
| Sin código | 422 | Only charges in processing or created status can be resolved. | El cargo ya no está en created ni processing, o enviaste el id del cobro en vez del charge_id. | Usa el charge_id de un cargo abierto. | No |
Links de captura
Crear un link de captura
POST /connect-links · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El customer id seleccionado es inválido. | Falta customer_id o single_use, customer_id no es un cliente tuyo del mismo ambiente, o redirect_url no es una URL https. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
| Sin código | 500 | Server Error | redirect_url tiene más de 255 caracteres. | Usa una redirect_url de máximo 255 caracteres. | Sí, tras corregir |
Eliminar un link de captura
DELETE /connect-links/{connect_link_id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, ConnectLink no existe | El link no existe, ya se eliminó o es de otra empresa. | Si era un reintento, trátalo como eliminado. | No |
Solicitudes de pago Nequi y Daviplata
Solicitar pago por Nequi
POST /request-to-pay/nequi · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El tamaño de cantidad debe ser de al menos 500. | amount falta, es menor que 500 o supera tu límite por transacción, customer_id no es un cliente tuyo, o phone no es un celular colombiano válido (+57). | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10141request_to_pay_in_progress | 422 | Una solicitud de pago ya se encuentra en proceso. | Llegó otra solicitud con el mismo external_id para la misma cuenta Nequi y todavía se está procesando. | Espera unos segundos y busca la solicitud por external_id en intentos de pago. | Sí, con espera |
90005charge_persistence_lost | 503 | Charge could not be confirmed, please retry. | OnePay no pudo confirmar que el cargo quedó guardado. Es raro. | Busca por external_id antes de reintentar. | Sí, tras verificar |
Confirmar pago por Nequi
POST /request-to-pay/nequi/{id}/confirm · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Cargo no existe | El ID no es de una solicitud tuya. | Usa el id que devolvió la solicitud. | No |
| Sin código | 500 | Server Error | Nequi no respondió al consultar el estado. | Reintenta más tarde; el estado también se actualiza solo. | Sí, con espera |
x-idempotency.
Solicitar pago por Daviplata
POST /request-to-pay/daviplata · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El tamaño de cantidad debe ser de al menos 500. | Falta o no es válido amount (mínimo 500 y tu límite), document (7 a 11), document_type, customer_id o phone (+57). | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10141request_to_pay_in_progress | 422 | Una solicitud de pago ya se encuentra en proceso. | La cuenta Daviplata de ese cliente ya tiene una solicitud abierta. | Confirma o espera la solicitud abierta (vence a los 10 minutos). | Sí, cuando termine |
10126customer_data_invalid | 422 | Datos del cliente inválidos. | El documento, su tipo o el celular no corresponden a una cuenta Daviplata. | Revisa los datos del pagador. | Sí, tras corregir |
| Sin código | 500 | Server Error | Daviplata no respondió. | Reintenta con espera. | Sí, con espera |
Confirmar pago por Daviplata
POST /request-to-pay/daviplata/{id}/confirm · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El campo otp debe contener 6 caracteres. | Falta otp o no tiene 6 caracteres. | Envía el OTP de 6 dígitos que recibió el pagador. | Sí, tras corregir |
10002record_not_found | 404 | Registro no encontrado, Cargo no existe | El ID no es de una solicitud tuya. | Usa el id que devolvió la solicitud. | No |
10140request_to_pay_not_available | 422 | La cuenta no se encuentra disponible para realizar transacciones por solicitud de pago. | El ID no es de una solicitud Daviplata. | Confirma solo solicitudes creadas con POST /request-to-pay/daviplata. | No |
10136transaction_otp_invalid | 422 | El OTP de la transacción es inválido, por favor intente nuevamente. | El OTP no es correcto. La solicitud queda fallida. | Crea una solicitud nueva; esta ya no acepta otro OTP. | No, crea otra |
10148transaction_otp_expired | 422 | El OTP de la transacción ha expirado, por favor inicie nuevamente el proceso. | El OTP venció o Daviplata respondió con un error. La solicitud queda fallida. | Crea una solicitud nueva. | No, crea otra |
90005charge_persistence_lost | 503 | Charge could not be confirmed, please retry. | OnePay no pudo confirmar que el pago quedó guardado. Es raro. | Consulta el intento de pago antes de reintentar. | Sí, tras verificar |
| Sin código | 500 | Server Error | Daviplata no respondió. | Consulta la solicitud y reintenta con espera. | Sí, con espera |
Intentos de pago
Listar intentos de pago
GET /payment-intents · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 400 | Requested filter(s) `…` are not allowed. Allowed filter(s) are `id, status, external_id, network_id`. | Enviaste un filtro que no existe. | Usa solo los filtros de la lista. | Sí, tras corregir |
| Sin código | 400 | Requested sort(s) `…` is not allowed. Allowed sort(s) are `created_at, paid_at`. | Enviaste un orden que no existe. | Ordena por created_at o paid_at. | Sí, tras corregir |
Detalle de un intento de pago
GET /payment-intents/{id} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10002record_not_found | 404 | Registro no encontrado, Cargo no existe | El ID no es de un intento de pago tuyo (por ejemplo, enviaste el id del cobro). | Usa el charge_id o un id del listado de intentos. | No |
Sesión de cliente
Los errores propios de la sesión (los401, el 418, el 404 de cargo y los 422 de negocio) no traen
code ni code_name: para esos decide por el HTTP y el endpoint. Los de validación sí traen 10001
validation_error; cuando venga code_name, úsalo. Los de sesión (/customers/session/*) exigen el header X-Customer-Token.
Tienen límites propios de peticiones, además del general:
| Endpoint | Límite |
|---|---|
POST /customers/login/request y POST /customers/login/verify | 1 cada 30 segundos y 3 por hora, por teléfono |
GET /customers/session/* | 30 por minuto, por cliente |
POST /customers/session/* | 5 por minuto, por cliente (compartido entre los dos POST) |
Solicitar código de acceso
POST /customers/login/request · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El numero de teléfono no es valido, debe ser un numero en formato E.164 | Falta phone o no está en formato E.164. | Envía el teléfono con indicativo, por ejemplo +573001234567. | Sí, tras corregir |
| Sin código | 418 | Ya se envió un código recientemente | Ya se envió un código a ese cliente hace menos de un minuto. | Espera al menos 60 segundos antes de pedir otro. | Sí, tras esperar |
| Sin código | 429 | Too Many Attempts. | Superaste 1 solicitud cada 30 segundos o 3 por hora para ese teléfono. | Espera lo que indique Retry-After. | Sí, tras esperar |
Verificar código de acceso
POST /customers/login/verify · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
10001validation_error | 422 | El campo otp debe tener 6 dígitos. | phone no está en formato E.164 u otp no es un número de 6 dígitos. | Corrige phone u otp. | Sí, tras corregir |
| Sin código | 422 | Las credenciales proporcionadas no son válidas. | El código no coincide o venció (dura una hora). | Pide al cliente revisar el código o solicita uno nuevo. Cada intento fallido cuenta. | Sí, con el código correcto |
| Sin código | 429 | Too Many Attempts. | Superaste 1 intento cada 30 segundos o 3 por hora para ese teléfono. | Espera lo que indique Retry-After. | Sí, tras esperar |
Varios intentos fallidos seguidos sobre el mismo código bloquean al cliente en OnePay. No
reintentes la verificación en un bucle: pide el código de nuevo al cliente.
Listar métodos de pago del cliente
GET /customers/session/payment-methods · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 401 | Token de sesión del cliente requerido. | Falta el header X-Customer-Token. | Envía el token que devolvió la verificación. | Sí, con el header |
| Sin código | 401 | Token de sesión inválido o expirado. | El token no existe, venció (dura 7 días) o se emitió con la llave de otra empresa. | Inicia sesión de nuevo. | Sí, tras renovar la sesión |
Agregar método de pago del cliente
POST /customers/session/payment-methods · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 401 | Token de sesión del cliente requerido. | Falta el header X-Customer-Token. | Envía el token de la sesión. | Sí, con el header |
| Sin código | 401 | Token de sesión inválido o expirado. | El token no existe, venció o es de otra empresa. | Inicia sesión de nuevo. | Sí, tras renovar la sesión |
10001validation_error | 422 | El campo token es obligatorio. | Falta token. | Envía el token temporal de la tarjeta. | Sí, tras corregir |
10104card_number | 422 | Número de tarjeta inválido. | La tarjeta fue rechazada al tokenizarla. | Pide otra tarjeta o que revise el número, y genera un token nuevo. | Sí, con otro token |
10122card_expired | 422 | Tarjeta expirada, Pídele al usuario que actualice su tarjeta. | La fecha de vencimiento no es válida. | Pide la fecha correcta o una tarjeta vigente. | Sí, tras corregir |
10102card_cvv | 422 | CVV inválido. | El código de seguridad no es válido. | Pide que vuelva a ingresar el CVV. | Sí, tras corregir |
10002record_not_found | 404 | Registro no encontrado | No se pudo leer el token temporal de la tarjeta (venció o falló la conexión con la bóveda). | Genera un token nuevo y reintenta. | Sí, con otro token |
| Sin código | 500 | Server Error | Falló la tokenización de la tarjeta. | Reintenta con un token nuevo. | Sí, con espera |
Crear cargo desde la sesión
POST /customers/session/charges · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 401 | Token de sesión del cliente requerido. | Falta el header X-Customer-Token. | Envía el token de la sesión. | Sí, con el header |
| Sin código | 401 | Token de sesión inválido o expirado. | El token no existe, venció o es de otra empresa. | Inicia sesión de nuevo. | Sí, tras renovar la sesión |
10001validation_error | 422 | El tamaño de cantidad debe ser de al menos 100. | Falta o no es válido payment_method_id, amount (entero en centavos, mínimo 100), currency o description. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
| Sin código | 422 | Método de pago no encontrado. | payment_method_id no es una tarjeta del cliente de la sesión. | Usa un id de listar métodos de pago. | Sí, tras corregir |
| Sin código | 422 | El método de pago no pertenece al cliente. | La tarjeta es del otro ambiente. | Usa una tarjeta del mismo ambiente que tu llave. | Sí, tras corregir |
| Sin código | 422 | El método de pago está expirado. | La tarjeta venció. | Pide al cliente una tarjeta vigente. | No |
| Sin código | 422 | Ya existe un cobro pendiente para este método de pago. | Hay un cargo en esa tarjeta esperando la aprobación del cliente (vence a los 5 minutos). | Consulta el cargo pendiente y espera a que se apruebe o venza. | Sí, cuando termine |
Consultar cargo de la sesión
GET /customers/session/charges/{chargeId} · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 401 | Token de sesión del cliente requerido. | Falta el header X-Customer-Token. | Envía el token de la sesión. | Sí, con el header |
| Sin código | 401 | Token de sesión inválido o expirado. | El token no existe, venció o es de otra empresa. | Inicia sesión de nuevo. | Sí, tras renovar la sesión |
| Sin código | 404 | Cargo no encontrado. | El cargo no existe o no es del cliente de la sesión. | Usa el charge_id que devolvió la creación. | No |
Importar mensajes de campaña
POST /campaigns/import-messages · Referencia
| Código | HTTP | Mensaje | Causa probable | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|---|
| Sin código | 403 | Company does not have this feature. | Tu empresa no tiene activas las campañas. | Pídele a soporte que las active. | No |
10001validation_error | 422 | El campo phones es obligatorio. | Falta template, phones, image_url (o video_url si type es video), o un teléfono no está en formato E.164. | Revisa errors y corrige el cuerpo. | Sí, tras corregir |
10001validation_error | 422 | La plantilla «…» no existe en la cuenta de WhatsApp de la empresa. | La plantilla no existe, no está aprobada, su encabezado no coincide con type, o el número de variables no coincide con los optional_* enviados. | Usa una plantilla aprobada y llena optional_1 a optional_3 según sus variables. | Sí, tras corregir |
10001validation_error | 422 | Dejaste «optional_1» vacío y llenaste un campo posterior. Los campos optional_1…optional_3 son las variables de la plantilla en orden: llénalos desde el primero, sin saltarte ninguno. | Hay un optional_N vacío antes de uno lleno. | Llena los optional_* en orden. | Sí, tras corregir |
10001validation_error | 422 | Las dimensiones de la imagen no son válidas. | La imagen no se pudo descargar o no cumple: máximo 2 MB, JPEG o PNG, lado corto de 600 px o más, lado largo de 2.048 px o menos, proporción 4:3, 9:16, 2:3 o 1:1. | Ajusta la imagen. | Sí, tras corregir |
10001validation_error | 422 | El video no debe superar los 16 MB. | El video no se pudo descargar, pesa más de 16 MB o no es MP4. | Usa un MP4 público de 16 MB o menos. | Sí, tras corregir |
| Sin código | 500 | Server Error | La URL de image_url no respondió. | Usa una URL pública que responda rápido. | Sí, tras corregir |