Plataforma tecnológica de pagos

Integración centralizada de pagos

PagoDirecto centraliza operaciones de pago mediante una API REST. Comprende dos servicios: Payins para ingresos y Payouts para transferencias.

Flujo transaccional, en 9 etapas

¿Cómo funciona PagoDirecto?

Visión de alto nivel del flujo transaccional: así se mueve el dinero desde que el usuario final inicia el pago hasta que tu sistema confirma la operación.

Cliente
Quiere pagar en tu plataforma
↓
Mi Plataforma
Tu backend arma la solicitud de pago
↓
POST /payins
Una llamada a la API de PagoDirecto
↓
PagoDirecto
Genera el voucher y te devuelve un token
↓
Banco / Wallet
Muestra el QR, CIP o solicitud de débito
↓
Cliente paga
Desde su app bancaria o billetera
↓
PagoDirecto recibe confirmación
El banco notifica que el dinero llegó
↓
Webhook
PagoDirecto te avisa automáticamente
↓
Mi sistema confirma el pedido
Acreditas, entregas o activas el servicio
💡

Este mismo patrón aplica a los 6 métodos de la plataforma (3 de cobro, 3 de desembolso). Solo cambia quién paga a quién y qué canal usa el dinero para moverse.

Para Dev & QA

Guía rápida de integración

Cuatro componentes son suficientes para completar una primera transacción de prueba, sin recorrer toda la referencia técnica:

✓

API Key

Tu llave pública y privada de Sandbox, provistas en el onboarding.

Ver autenticación →
✓

Crear pago

Un POST con el monto y el canal que quieras probar.

Ver endpoint →
✓

Mostrar voucher

Incrusta el payment_token en un iframe para que el cliente pague.

Ver cómo mostrarlo →
✓

Escuchar webhook

Expone un endpoint que reciba el POST con el resultado final.

Ver callbacks →
Paso 1 de tu integración
Primer paso: conecta con PagoDirecto

Cada solicitud se autentica con un Bearer token en el header Authorization. PagoDirecto te entrega tus llaves durante el onboarding.

Dos llaves, dos alcances
Public Key
Operaciones públicas
Solo permite crear pagos (POST). Puede vivir en código cliente (JS/HTML).
Private Key
Operaciones privadas
Permite consultar (GET), eliminar (DELETE) y crear. Úsala solo en tu backend.
🌐
Ambientes disponibles
Las pruebas y ejemplos de esta guía utilizan el ambiente de Staging. Los dominios y credenciales de Producción serán proporcionados una vez finalizado el proceso de Certificación.
Header de autenticación
HTTP Header
Authorization: Bearer <tu-api-key>
Content-Type:  application/json
Base URLs
Endpoints
# Certificación (pruebas)
Payins:           https://stg-payins-api.pagodirecto.pe
Payouts CCI:      https://payouts-api-functionapp-stg.azurewebsites.net/api/payouts
Payouts Wallet:   https://stg-payouts-api-wallet.azurewebsites.net/api/payouts

Los ejemplos de esta guía usan URLs de nuestro ambiente de staging. Recibirás los dominios definitivos de producción junto con tus credenciales una vez finalizado el proceso de certificación.

API Payins · Recaudo

Métodos de pago disponibles

Payins genera un voucher de pago que el usuario final completa desde su banco o billetera. El mismo endpoint soporta tres métodos de integración; el valor de deposit_channel determina el canal utilizado.

Tu Backend
Crea el pago con el monto y el canal
POST
→
CIP Bancariobcp · bbva · ibk · banbif · yape
QR Dinámicoqr
Yape On Fileyapeof
🏦
CIP Bancario
deposit_channel: bcp · bbva · ibk · banbif · yape

El cliente recibe un código de pago y lo abona desde su app bancaria, agente o cajero. Confirmación en minutos.

✓ Funciona con los principales bancos del Perú
✓ El cliente no necesita tarjeta
📱
QR Dinámico
deposit_channel: qr

Se muestra un QR en tu checkout o app que el cliente escanea con la app de su banco o billetera. Confirmación casi instantánea, 100% online.

✓ Compatible con Yape, Plin y apps bancarias
✓ Pago sin tarjeta desde el móvil del cliente
⚡
Yape On File
deposit_channel: yapeof

Débito automático desde Yape. Si el cliente no está afiliado, PagoDirecto gestiona la suscripción y luego cobra - todo con una sola llamada.

✓ Un endpoint gestiona afiliación + cobro
✓ Perfecto para cobros recurrentes
⚠️

Los bancos y billeteras mostrados en el CIP corresponden a las plantillas internas que manejamos. Cada opción permite generar las instrucciones o frame específico para el banco o billetera seleccionado. Esta lista no representa una limitación de los canales de pago disponibles.

POSThttps://stg-payins-api.pagodirecto.pe
Crear pago

Genera un voucher de pago. Devuelve un payment_id y un payment_token que usarás para mostrarle las instrucciones al cliente.

Campos del body
payment_reference_code REQ
string
Tu identificador único para este pago. Se devuelve en el callback.
payment_amount REQ
string
Monto en dígitos sin separador; los últimos 2 son decimales. "2500" = S/ 25.00
payment_currency REQ
string
Moneda ISO de 3 letras: PEN o USD.
client_email REQ
string
Email del cliente. PagoDirecto le envía las instrucciones de pago.
deposit_channel COND
string
Canal de pago: qr, yapeof, bcp, ibk, bbva, banbif, yape
Obligatorio para QR y Yape On File. Si se omite, se ofrecen todos los canales.
payment_concept OPC
string
Descripción del pago (ej. “Orden #123”).
client_name OPC
string
Nombre del cliente.
client_id_type OPC
string
Tipo de documento del cliente: DNI, CE, RUC, PASSPORT, OTHER.
client_id_number OPC
string
Número de documento del cliente.
callback_url OPC
string
URL donde PagoDirecto enviará las notificaciones de estado.
metadata OPC
object
Datos libres clave-valor. PagoDirecto los devuelve en los callbacks sin modificarlos.
payment_source OPC
string
Origen del pago. Enviar "mobile" o "web". Requerido cuando se usan deeplinks para redirigir al cliente a la app del banco o billetera.
client_phone_mobile COND
string
Número de celular del cliente.
Obligatorio para los pagos con Yape-on-file.
client_email COND
string
Correo electrónico del cliente.
Obligatorio para los pagos con Yape-on-file.
💡

También existen client_city, client_province y client_country_code como campos opcionales para enriquecer el registro.

🚨

El voucher expira automáticamente en 7 días una vez creado.

Request
curl -X POST https://stg-payins-api.pagodirecto.pe \
        -H "Authorization: Bearer <tu-api-key>" \
        -H "Content-Type: application/json" \
        -d '{
          "payment_reference_code": "REF-2026-000123",
          "payment_amount": "2500",
          "payment_currency": "PEN",
          "payment_concept": "Orden #123",
          "client_name": "Juan Perez",
          "client_email": "juan@example.com",
          "deposit_channel": "qr",
          "callback_url": "https://tutienda.com/payins/callback",
          "metadata": { "order_id": "123" }
        }'
      
const res = await fetch("https://stg-payins-api.pagodirecto.pe", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${API_KEY}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          payment_reference_code: "REF-2026-000123",
          payment_amount: "2500",
          payment_currency: "PEN",
          client_email: "juan@example.com",
          deposit_channel: "qr",
          callback_url: "https://tutienda.com/payins/callback"
          })
        });
        const data = await res.json();
      
import requests
        res = requests.post(
            "https://stg-payins-api.pagodirecto.pe",
            headers={"Authorization": f"Bearer {API_KEY}"},
            json={
                "payment_reference_code": "REF-2026-000123",
                "payment_amount": "2500",
                "payment_currency": "PEN",
                "client_email": "juan@example.com",
                "deposit_channel": "qr",
                "callback_url": "https://tutienda.com/payins/callback"
            }
        )
        data = res.json()
      
201 Created
Response
Location: https://stg-payins-api.pagodirecto.pe/102030
        {
          "object": "payins",
          "payment_id": 102030,
          "payment_token": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
        }

Guarda el payment_id (para consultar) y el payment_token (para mostrar el voucher).

400 Bad Request
JSON
{
          "object": "error",
          "error_type": "parameter_error",
          "error_code": "400",
          "params": [
            { "param": "client_email",
              "user_message": "No es una dirección email válida" }
          ]
        }
Mostrar el voucher al cliente

Existen dos variantes de URL según cómo quieras presentar el voucher. Ambas usan el payment_token devuelto al crear el pago.

Voucher con frame
GEThttps://stg-payins-iframe.pagodirecto.pe/payins/{payment_token}

Renderiza el QR o las instrucciones de pago dentro de un frame propio de PagoDirecto. Ideal para incrustar en un iframe dentro de tu checkout o abrir en un WebView móvil.

Voucher sin frame
GEThttps://stg-payins-iframe.pagodirecto.pe/payins/{payment_token}/info

Devuelve el contenido del voucher sin el frame de PagoDirecto. Útil para integrar el diseño dentro de tu propio flujo de UI sin contenedor visual externo.

VarianteURLIdeal para
Con frame/payins/{token}iframe · WebView · pestaña nueva
Sin frame/payins/{token}/infoIntegración en UI propia
✉

Al crear el pago, PagoDirecto también envía automáticamente un email con las instrucciones al client_email. Mostrar el voucher es un refuerzo recomendado.

URLs del voucher
Con frame
# Voucher con frame
GET https://stg-payins-iframe.pagodirecto.pe/payins/{payment_token}
Sin frame
# Voucher sin frame
GET https://stg-payins-iframe.pagodirecto.pe/payins/{payment_token}/info

El contenido detecta el canal (qr, CIP…) y renderiza automáticamente el QR o el código de pago correspondiente.

🏦
Método 1 de 3 · Payins

CIP Bancario

Función en la plataforma

CIP permite realizar pagos mediante un código numérico que el usuario ingresa en los canales habilitados por su entidad financiera, como banca móvil, agentes o cajeros.

Flujo visual completo
Tu Backend
Envía POST https://stg-payins-api.pagodirecto.pe con deposit_channel: "bcp" (o el banco elegido).
PagoDirecto
Genera el voucher y el código CIP asociado.
Banco
El cliente ingresa el código en su app, agente o cajero.
Cliente
Confirma el pago desde su banco.
Webhook
PagoDirecto te notifica el resultado en tu callback_url.
Request & Response

Usa el mismo endpoint de Payins, cambiando deposit_channel. Ejemplo completo y código listo para copiar en la Referencia técnica ↓.

Fragmento del body
{ "deposit_channel": "bcp", // también: bbva, ibk...
  "payment_amount": "2500", "payment_currency": "PEN" }
¿Qué ve el cliente?
0021 9213 866
🏦 BCP · Banca por Internet
S/ 25.00
Código válido por 7 días

Voucher con el código CIP, el banco elegido y el monto. El cliente lo copia en su app bancaria o lo lleva a un agente.

Callback

Mismo formato que todos los métodos de Payins — ver ejemplo completo ↓.

🎯

Resultado esperado: al recibir payment_status = 3, acredita al cliente y marca el pedido como pagado. Si recibes 98 (expirado), invita a generar un nuevo voucher.

📱
Método 2 de 3 · Payins

QR Interoperable

Función en la plataforma

El QR Interoperable elimina la necesidad de capturar datos de tarjeta o cuenta bancaria. Un único código es compatible con múltiples aplicaciones (Yape, Plin, banca móvil), lo que reduce la fricción de integración del lado del checkout.

Flujo visual completo
Tu Backend
Envía POST https://stg-payins-api.pagodirecto.pe con deposit_channel: "qr".
PagoDirecto
Genera un QR dinámico asociado al monto exacto.
Banco / Wallet
El cliente escanea con la app de su preferencia.
Cliente
Confirma el pago en segundos.
Webhook
Recibes la confirmación casi de inmediato.
Request & Response

Ejemplo completo (cURL, Node.js, Python) en la Referencia técnica ↓.

Fragmento del body
{ "deposit_channel": "qr",
  "payment_amount": "2500", "payment_currency": "PEN" }
¿Qué ve el cliente?
S/ 25.00
Escanea con tu app bancaria

QR dinámico embebido en tu checkout vía iframe. El cliente lo escanea desde cualquier app compatible.

Callback

Mismo formato que todos los métodos de Payins — ver ejemplo completo ↓.

🎯

Resultado esperado: al recibir payment_status = 3, confirma la orden de inmediato — la experiencia esperada es que el cliente vea éxito en segundos.

⚡
Método 3 de 3 · Payins

Yape On File

Función en la plataforma

Yape On File permite ejecutar débitos automáticos sobre una cuenta Yape previamente autorizada por el usuario. La afiliación se gestiona una única vez; los cobros posteriores no requieren intervención del cliente.

Criterios de uso
  • Facilitar el pago reduciendo la cantidad de interacciones que hace el usuario.
  • Quieres reducir el churn por pagos manuales olvidados.
  • Tus clientes ya usan Yape habitualmente.
Caso de uso
Suscripciones, membresías
Tiempo estimado
Segundos (afiliados)
Minutos (usuarios nuevos)
Interacción del cliente
Solo la 1ª vez (afiliación)
Requiere callback
Sí
Recomendado para
Cobros recurrentes
¿Qué ve el cliente?
Autorizar débito automático
para Tu App
Se ejecutará solo cuando factures
✓
Pago confirmado
S/ 150.00

Izquierda: pantalla de afiliación (solo la primera vez). Derecha: pantalla de éxito, idéntica en cada cobro posterior.

Flujo visual completo
Paso 1 · Tu backend
Invocas el endpoint con yapeof
Un POST con deposit_channel: "yapeof". No necesitas lógica condicional de tu lado.
Paso 2 · PagoDirecto
Valida la suscripción del cliente
El sistema decide automáticamente: ¿este cliente ya tiene débito automático habilitado?
Paso 3 · Bifurcación automática
Afiliación si hace falta, luego cobro
Si no está afiliado, se inicia la suscripción y al terminar se ejecuta el pago. Si ya lo está, cobra directo.
Paso 4 · Resultado
Webhook con el estado final
payment_status: 3 = pagado · 98 = expirado . 99 = Anulado. Actúa solo con estados finales.
Flujo diferenciado
⌛ No afiliado
Afiliación
↓
Cobro automático
↓
Webhook
✅ Ya afiliado
Cobro automático
directo
↓
Webhook
⚠️

Los estados intermedios no generan callback. Actúa solo al recibir 3 (pagado), 98 o 99.

Request & Response

Ejemplo completo (cURL, Node.js, Python) en la Referencia técnica ↓.

Fragmento del body
{ "deposit_channel": "yapeof",
  "payment_amount": "2500", 
  "payment_currency": "PEN", 
  "client_phone_mobile": "51999999999", 
  "client_email": "juan@example.com" }

Respuesta al suscribirse

El primer pago con Yape-on-file dispara el flujo de suscripción, se recibirá en el Response en el campo flow el valor SUBSCRIPTION.

Response
{ "object": "payins",
    "payment_id": "00000000", 
    "payment_token": "a0a0a0a0-b1b1-c2c2-d3d3-ab66802c560b", 
    "flow": "SUBSCRIPTION", 
    "yape_link": "https://www.yape.com.pe/app/checkout/ocp/subscription?subscriptionRequestId=000000&origin=deeplink-externo&origin_detail=mobile", 
    "yape_detail": "Successful operation." }

Respuesta al estar suscrito

Una vez suscrito a Yape-on-file se recibirá en el Response en el campo flow el valor DEPOSIT.

Response
{ "object": "payins",
    "payment_id": "00000000", 
    "payment_token": "a0a0a0a0-b1b1-c2c2-d3d3-ab66802c560b", 
    "flow": "DEPOSIT", 
    "yape_link": null, 
    "yape_detail": "Successful operation." }
⚠️

Los Deeplinks (yape_link) se reciben en el Response solamente cuando se envía como parámetro payment_source con valor mobile.

Respuesta inmediata vs. resultado final
📤 Respuesta API (201)

La recibes al instante cuando llamas al endpoint.

payment_id + token
↓
Flujo iniciado
⚠ No indica el resultado final
📡 Webhook (callback)

Llega después, de forma asíncrona, cuando el cobro concluye.

payment_status: 3
↓
Pago confirmado ✅
✅ Resultado definitivo
Callback

Cuando se realiza el primer pago con un cliente se recibirán 2 callbacks:

Aprobación de suscripción

Response 1
{ "subscriptionId": 102808,
    "chargeType": "ON_DEMAND", 
    "customerId": "juan@example.com", 
    "status": "AUTHORIZED", 
    "statusDescription": "Subscription confirmed", 
    "errorDetails": null }

Confirmación de pago

Response 2
{ "object": "payins",
    "payment_id": "00000000", 
    "payment_token": "a0a0a0a0-b1b1-c2c2-d3d3-ab66802c560b", 
    "payment_status": "3", 
    "payment_paid_date": "1788967242", 
    "payment_reference_code": "TestYape", 
    "payment_concept": "Test Yape OnFile", 
    "payment_currency": "PEN", 
    "payment_amount": "10000", 
    "payment_expire_date": "1789157825", 
    "client_name": "Cliente de Prueba", 
    "client_email": "juan@example.com", 
    "client_id_type": "DNI", 
    "client_id_number": "12345678", 
    "client_city": "Lima", 
    "client_province": "Lima", 
    "client_country_code": "PE", 
    "client_phone_mobile": "999999999", 
    "metadata": {} }

Una vez suscrito los callbacks con este canal mantienen el mismo formato que todos los métodos de Payins (Response 2 en esta sección) — ver ejemplo completo ↓. Además del endpoint compartido en la Referencia técnica ↓, usa deposit_channel: "yapeof".

🎯

Resultado esperado: guarda al cliente como “afiliado” en tu sistema tras el primer éxito. Los siguientes cobros serán automáticos — solo espera el webhook cada vez que factures.

POSThttps://stg-payins-api.pagodirecto.pe/subscriptions/cancel
Cancelar una suscripción Yape-on-file

Elimina la suscripción del cliente en Yape. Se debe especificar el celular y correo electrónico del cliente.

Request
curl -X POST https://stg-payins-api.pagodirecto.pe/subscriptions/cancel \
        -H "Authorization: Bearer <tu-api-key>" \
        -H "Content-Type: application/json" \
        -d '{
          "client_phone_mobile": "999999999",
          "client_email": "juan@example.com"
        }'
      
const res = await fetch("https://stg-payins-api.pagodirecto.pe/subscriptions/cancel", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${API_KEY}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          client_phone_mobile: "999999999",
          client_email: "juan@example.com"
          })
        });
        const data = await res.json();
      
import requests
        res = requests.post(
            "https://stg-payins-api.pagodirecto.pe/subscriptions/cancel",
            headers={"Authorization": f"Bearer {API_KEY}"},
            json={
                "client_phone_mobile": "999999999",
                "client_email": "juan@example.com"
            }
        )
        data = res.json()
      
200 OK
Response
        {
          "success": true,
          "operation_detail": "Successful operation."
        }
GEThttps://stg-payins-api.pagodirecto.pe/13745571
Consultar estado de un pago

Consulta el estado y los datos completos de un voucher en cualquier momento — útil si el callback no llegó. Requiere tu private key.

🔄

El campo clave es payment_status. Determina si el voucher está pendiente, pagado, confirmado, expirado o anulado.

Request
cURL
curl https://stg-payins-api.pagodirecto.pe/102030 \
  -H "Authorization: Bearer <private-key>"
200 OK
JSON
{
        "object": "payins",
        "payment_token": "c0984b7a-f79b-f111-93b2-8f4adacb067d",
        "payment_status": 1,
        "payment_creation_date_ts": 1787162264.6340404,
        "payment_paid_date": null,
        "payment_reference_code": "pruebas122",
        "payment_concept": "TEST-payins",
        "payment_currency": "PEN",
        "payment_amount": "162",
        "payment_expire_date": 1787335063.80248,
        "payment_callback": "https://prueb225.requestcatcher.com/test",
        "payment_deposit_channel": "QR",
        "client_name": "Prueba1",
        "client_email": "juan@example.com",
        "client_id_type": "1",
        "client_id_number": "",
        "client_city": "Lima",
        "client_province": "Lima",
        "client_country_code": "PEN",
        "client_phone_mobile": "99999999",
        "partner_id": 402,
        "metadata": {}}
        }
Callbacks (webhooks) de Payins

Cuando el cliente paga o el voucher expira, PagoDirecto envía un POST a tu callback_url con la misma estructura del GET. El header Authorization incluye tu llave para que verifiques el origen.

Estados en el webhook
  • Pago exitoso: payment_status = 3 (Paid) → acredita al cliente.
  • Voucher expirado: payment_status = 98 con payment_paid_date: null → invita a generar un nuevo voucher.
  • Voucher anulado: payment_status = 99 → el voucher fue cancelado antes de recibir pago.
🔄

Reintentos: tu handler debe ser idempotente y responder HTTP 200. Si no respondes, PagoDirecto reintenta la entrega.

Callback entrante
POST a tu callback_url
POST /payins/callback HTTP/1.1
Authorization: Bearer <private-key>
Content-Type: application/json

{
"object": "payins",
"payment_id": "13745571",
"payment_token": "00d35cdc-109b-f111-93b2-8f4adacb067d",
"payment_status": "3",
"payment_paid_date": "1787063436.4010353",
"payment_reference_code": "Prueba payins",
"payment_concept": "TEST321",
"payment_currency": "PEN",
"payment_amount": "10000",
"payment_expire_date": "1787236015.398",
"client_name": "Prueba1",
"client_email": "juan@example.com",
"client_id_type": "70127294",
"client_id_number": "70127294",
"client_city": "Lima",
"client_province": "Lima",
"client_country_code": "PEN",
"client_phone_mobile": "937535099",
"metadata": {}
}
Referencia

Estados de Payins

El campo payment_status te dice en qué punto está el pago. Actúa solo en estados finales.

ValorEstadoSignificadoTipo
1CreatedVoucher generado, esperando el pago del cliente.Intermedio
3PaidVoucher pagado y acreditado.Final cliente
4ConfirmedEstado interno luego de notificar al cliente (Callback interno exitoso).Final PagoDirecto
98ExpiredEl voucher venció sin recibir pago.Final
99AnnulledVoucher anulado antes de recibir pago.Final
API Payouts · Dispersión

Métodos de desembolso disponibles

Payouts ejecuta transferencias hacia una billetera, en segundos vía Open Banking, o a cualquier cuenta bancaria del Perú.

Tu Backend
Solicita el desembolso con monto y destinatario
POST
→
WalletsYape · Plin
Instant PayoutsOpen Banking
H2H a bancosCCI · 40+ entidades
📱
Wallets
Yape · Plin

Envía el dinero directo a la billetera digital del destinatario. Sin necesidad de que tenga una cuenta bancaria tradicional.

✓ El destinatario recibe el dinero al instante en su app
✓ Solo necesitas su número de celular afiliado
⚡
Instant Payouts
Open Banking

Transferencia bancaria en segundos mediante integración Open Banking, sin pasar por los tiempos tradicionales de liquidación interbancaria.

✓ Liquidación casi inmediata a la cuenta destino
✓ Conexión directa con los bancos participantes
🏦
H2H a Bancos
CCI · 40+ entidades

Transferencia Host-to-Host directa a cualquier cuenta bancaria peruana usando el CCI. La cobertura más amplia del mercado.

✓ Llega a bancos, financieras y cajas municipales
✓ Procesamiento validado y conciliado por PagoDirecto
🏦
Método 1 de 3 · Payouts

Host-to-Host (H2H)

Transferencia directa a cualquier cuenta bancaria peruana usando el CCI. La cobertura más amplia del mercado.

Función en la plataforma

H2H ejecuta transferencias a cuentas bancarias peruanas identificadas por CCI. El sistema recibe el request, valida los datos del destinatario y encola la transferencia hacia el banco correspondiente sin intervención manual.

Criterios de uso
  • El destinatario no tiene o no usa billetera digital.
  • Necesitas la máxima cobertura posible (bancos, financieras, cajas municipales).
  • El desembolso puede tardar minutos — no es urgente al segundo.
Flujo visual completo
ERP / Mi Backend
Envía POST con el CCI y el monto.
PagoDirecto
Valida los datos y encola la transferencia.
Banco
Recibe y procesa la transferencia interbancaria.
Webhook
PagoDirecto notifica éxito o fallo a tu callback_url.
Caso de uso
Proveedores, planillas
Tiempo estimado
Minutos
Interacción del destinatario
Ninguna
Requiere callback
Sí
Recomendado para
Volumen y cobertura

Ejemplo completo (cURL, Node.js, Python) en la Referencia técnica ↓.

🎯

Resultado esperado: al recibir payment_status = 5 (Archive), marca el pago como completado. Si recibes 6 (Void), revisa payment_notes.

📱
Método 2 de 3 · Payouts

Digital Wallets

Envía dinero directo a Yape o Plin. El destinatario lo recibe en su billetera en segundos, sin necesitar cuenta bancaria.

Función en la plataforma

Wallets envía desembolsos directamente a una billetera Yape o Plin, identificando al destinatario por su número de celular afiliado. No requiere CCI ni cuenta bancaria.

Criterios de uso
  • Solo cuentas con el celular afiliado del destinatario, no su CCI.
  • El destinatario espera recibir el dinero casi al instante.
  • El monto es en PEN únicamente.
Flujo visual completo
Mi Backend
Envía POST wallets con el celular y payment_wallet (1=Yape, 2=Plin).
PagoDirecto
Valida el número y encola el envío instantáneo.
Yape / Plin
Acredita el saldo en la billetera del destinatario.
Webhook
PagoDirecto notifica el resultado en segundos.
Caso de uso
Repartidores, freelancers
Tiempo estimado
Segundos
Interacción del destinatario
Ninguna (recibe directo)
Requiere callback
Sí
Recomendado para
Pagos urgentes y pequeños

Contrato técnico completo en Referencia Wallets ↓.

🎯

Resultado esperado: al recibir payment_status = 5 (Archive) el destinatario ya tiene el dinero en su app. Si es 6 (Void) revisa payment_notes. Rejected (7) y Cancelled (8) no generan callback — consúltalos vía GET si necesitas el detalle.

⚡
Método 3 de 3 · Payouts

Open Banking (Instant Payouts - BCP)

Transferencia bancaria en segundos mediante integración Open Banking, evitando los tiempos tradicionales de liquidación interbancaria.

Función en la plataforma

Cuando se requiere mayor agilidad en una transferencia, Open Banking permite conectar directamente con las entidades financieras para procesar las operaciones de forma rápida, segura y automatizada.

Flujo visual completo
Mi Backend
Solicita el desembolso indicando la cuenta destino.
PagoDirecto
Enruta vía Open Banking al banco correspondiente.
Banco
Liquida la cuenta.
Webhook
Confirmación casi inmediata.
Caso de uso
Reembolsos urgentes
Tiempo estimado
Segundos
Interacción del destinatario
Ninguna
Requiere callback
Sí
Recomendado para
Velocidad máxima
Método H2H · Transferencia CCI
POSThttps://payouts-api-functionapp-stg.azurewebsites.net/api/payouts
Crear un payout (H2H)

Envía dinero a cualquier cuenta bancaria peruana usando el CCI (Código de Cuenta Interbancario). PagoDirecto valida los datos, encola la solicitud y la procesa vía integración directa con los bancos.

Campos del body
payment_reference REQ
string (50)
Tu código único. Se devuelve en el callback.
customer_name REQ
string
Nombre completo del destinatario (nombre y apellido).
customer_id_type REQ
string
Documento: DNI, CE o Passport.
customer_id_number REQ
string (50)
Número de documento. DNI = 8 dígitos; CE = 9 o menos.
account_cci REQ
string (20)
CCI de la cuenta destino. Identifica banco y cuenta.
account_currency REQ
string
Moneda de la cuenta: SOLES o USD.
payment_amount REQ
string
Monto decimal con 2 posiciones. Ej: "150.00". (Distinto a Payins.)
payment_currency REQ
string
Moneda del pago: PEN o USD.
customer_email OPC
string (100)
Email del destinatario.
callback_url OPC
string (200)
URL para notificar el resultado del desembolso.
🚨

La respuesta exitosa (201) no tiene body. Extrae el payment_id del header Location y guárdalo de inmediato.

Request
curl -X POST https://payouts-api-functionapp-stg.azurewebsites.net/api/payouts \
  -H "Authorization: Bearer <tu-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_reference": "PAYOUT-001",
    "customer_name": "Maria Torres Flores",
    "customer_id_type": "DNI",
    "customer_id_number": "12345678",
    "account_cci": "00219213866047808638",
    "account_currency": "SOLES",
    "payment_amount": "150.00",
    "payment_currency": "PEN",
    "callback_url": "https://tuapp.com/payouts/callback"
  }'
const res = await fetch("https://payouts-api-functionapp-stg.azurewebsites.net/api/payouts", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    payment_reference: "PAYOUT-001",
    customer_name: "Maria Torres Flores",
    customer_id_type: "DNI",
    customer_id_number: "12345678",
    account_cci: "00219213866047808638",
    account_currency: "SOLES",
    payment_amount: "150.00",
    payment_currency: "PEN"
  })
});
import requests

res = requests.post(
    "https://payouts-api-functionapp-stg.azurewebsites.net/api/payouts",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "payment_reference": "PAYOUT-001",
        "customer_name": "Maria Torres Flores",
        "customer_id_type": "DNI",
        "customer_id_number": "12345678",
        "account_cci": "00219213866047808638",
        "account_currency": "SOLES",
        "payment_amount": "150.00",
        "payment_currency": "PEN"
    }
)
201 Created
Headers (sin body)
Location: https://payouts-api-functionapp-stg.azurewebsites.net/api/payouts/5574127
// El payment_id es el número final del path → 5574127
400 Validation Failed
JSON
{
  "code": 8,
  "message": "Validation Failed",
  "errors": [
    { "code": 1000, "field": "payment_amount",
      "message": "Amount can not be empty" }
  ]
}
GEThttps://payouts-api-functionapp-stg.azurewebsites.net/api/payouts/{payment_id}
Consultar un payout

Obtiene el estado operativo del desembolso, junto con notas del procesamiento bancario (útil para diagnosticar rechazos).

📋

Revisa payment_status para conocer el estado del desembolso. Cuando algo falla, payment_notes explica la razón.

Response
JSON
{
  "payment_id": "5574119",
  "payment_reference": "PAYOUT-001",
  "customer_name": "Maria Torres Flores",
  "account_cci": "00219213866047808638",
  "account_currency": "SOLES",
  "payment_amount": "150.00",
  "payment_currency": "PEN",
  "payment_status": "5",
  "payment_notes": "Transferencia completada."
}
Webhook · éxito vs. fallo
POST a tu callback_url
// Éxito
{ "payment_status": "5" }

// Fallo — revisa payment_notes
{ "payment_status": "6",
  "payment_notes": "Bank account validation failed." }

Solo los estados Archive (5) y Void (6) generan callback.

Método Wallets · Yape / Plin
POSThttps://stg-payouts-api-wallet.azurewebsites.net/api/payouts
Crear un payout a Wallet

Endpoint dedicado para envíos instantáneos a Yape o Plin. A diferencia de H2H, identificas al destinatario por su número de celular, no por CCI.

Campos del body
payment_reference REQ
string (50)
Tu código único. Se devuelve en el callback.
customer_name REQ
string
Nombre completo del destinatario.
customer_id_type REQ
string
Documento: DNI, CE o Passport.
customer_id_number REQ
string (50)
Número de documento. DNI = 8 dígitos; CE = 9 o menos.
customer_phone_number REQ
string (11)
Celular afiliado a la billetera, con código de país. Ej: 51999999999
payment_amount REQ
string
Monto decimal con 2 posiciones. Ej: "98.67".
payment_currency REQ
string
Único valor permitido: PEN.
payment_wallet REQ
string
Billetera destino: 1 = Yape, 2 = Plin.
customer_email OPC
string (100)
Email del destinatario.
customer_reference OPC
string
Tu referencia interna adicional del cliente.
callback_url OPC
string (200)
URL HTTPS para notificar el resultado final.
💡

A diferencia de H2H, la respuesta 201 sí incluye body completo con los datos del payout, además del header Location.

Request
cURL
curl -X POST https://stg-payouts-api-wallet.azurewebsites.net/api/payouts \
  -H "Authorization: Bearer <tu-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_reference": "PO-WALLET-001",
    "customer_name": "Jose Andres Polanco Gonzales",
    "customer_id_type": "DNI",
    "customer_id_number": "42553791",
    "customer_phone_number": "51919468262",
    "payment_amount": "50.00",
    "payment_currency": "PEN",
    "payment_wallet": "1",
    "callback_url": "https://tuapp.com/payouts/callback"
  }'
201 Created
Headers + Body
Location: https://stg-payouts-api-wallet.azurewebsites.net/api/payouts/5433533

{
  "payment_id": 5566808,
  "payment_reference": "PO-WALLET-001",
  "customer_name": "Jose Andres Polanco Gonzales",
  "payment_amount": "50.00",
  "payment_currency": "PEN",
  "payment_date": "28/10/2025",
  "payment_time": "17:21:26",
  "payment_status": "2" // Process (encolado)
}
400 Validation Failed
JSON
{
  "code": 400,
  "errors": [
    { "code": 1000, "field": "customer_phone_number",
      "message": "customer_phone_number cannot be empty." }
  ],
  "message": "Validation Failed"
}
Webhook · resultado final
POST a tu callback_url
// Éxito — payment_status = 5
{ "payment_status": "5" }

Solo Archive (5) y Void (6) generan callback, igual que en H2H.

Referencia Payouts

Estados de un desembolso

El campo payment_status indica el estado operativo del payout. Los estados 7 y 8 son exclusivos de Wallets.

ValorEstadoSignificadoCanal
1PendingRetenido para revisión manual del equipo PagoDirecto.H2H · Wallet
2ProcessEncolado para procesamiento.H2H · Wallet
4SentEnviado al banco o billetera, esperando respuesta.H2H · Wallet
5ArchiveÉxito: dinero enviado al destinatario. Genera callback.H2H · Wallet
6VoidFallo confirmado. Ver payment_notes. Genera callback.H2H · Wallet
7RejectedRechazado por la billetera. Ver payment_notes. No genera callback.Wallet
8CancelledCancelado antes de procesar. No genera callback.Wallet

ⓘ Solo Archive (5) y Void (6) generan callback. Rejected y Cancelled deben consultarse vía GET.

Cobertura

Bancos y cajas aceptados

Cuentas CCI de estas entidades pueden recibir desembolsos vía Payouts. Cada CCI empieza con el código del banco.

002Banco de Crédito (BCP)
003Interbank
011BBVA Continental
009Scotiabank
007Citibank
018Banco de la Nación
023Banco de Comercio
035Pichincha
038BANBIF
043CrediScotia
049Mi Banco
053Banco GNB
054Banco Falabella
055Banco Ripley
056Santander Perú
058Banco Azteca
800Caja Metropolitana Lima
801CMAC Piura
802Caja Trujillo
803Caja Arequipa
805CMAC Sullana
806CMAC Cuzco
808CMAC Huancayo

Y más de 40 entidades incluyendo financieras y cajas rurales. Lista completa disponible en el onboarding.

Troubleshooting

Errores comunes al integrar

Los problemas más frecuentes durante la integración, y cómo resolverlos rápido.

401

No autorizado

Tu Authorization falta o la llave es inválida.

🔧

Verifica que uses Bearer <key> y que la llave corresponda al ambiente (Sandbox vs. Producción).

404

Recurso no encontrado

El payment_id consultado no existe.

🔧

Confirma que guardaste el ID correcto desde la respuesta del POST (o el header Location en Payouts).

422

Datos inválidos

Uno o más campos no pasaron la validación.

🔧

Revisa el array params o errors de la respuesta — indica campo por campo qué falta corregir.

⏳

Timeout

La solicitud tardó demasiado en responder.

🔧

Reintenta con backoff exponencial. Si persiste, consulta el estado por GET antes de crear un pago duplicado.

📡

El webhook no llega

Tu servidor no recibe el callback esperado.

🔧

Confirma que tu callback_url sea HTTPS público y que hayas autorizado las IPs de PagoDirecto ↓. Mientras tanto, consulta por GET.

🔒

IP bloqueada

Tus llamadas son rechazadas por el firewall.

🔧

Reporta tus IPs de producción y sandbox para whitelisting durante el onboarding.

≠ 200

Tu callback responde distinto de 200

PagoDirecto interpreta esto como entrega fallida.

🔧

Responde HTTP 200 apenas recibas el webhook (antes de procesarlo si es necesario) para evitar reintentos duplicados.

Referencia
Manejo de errores

La API usa códigos HTTP estándar. Los errores 400 y 500 incluyen un objeto error con detalle por campo.

HTTPSignificado
200Operación exitosa (GET)
201Recurso creado (POST)
204Exitoso sin contenido (DELETE)
400Parámetro faltante o inválido
401Token inválido o ausente
403Sin permisos para el recurso
404Recurso no encontrado
429Demasiadas solicitudes (rate limit)
500Error interno del servidor
Tipos de error (error_type)
error_typeCuándo
parameter_errorUno o más campos con valores inválidos (revisa params).
invalid_request_errorEl JSON no se pudo leer / procesar.
limit_api_errorSe excedió el límite de peticiones.
api_errorError interno de la API.
Objeto de error
JSON
{
  "object": "error",
  "error_type": "parameter_error",
  "error_code": "400",
  "merchant_message": "Petición inválida, los valores en el JSON no son correctos",
  "user_message": "El valor de uno o más campos no es correcto",
  "params": [
    { "param": "client_email",
      "user_message": "No es una dirección email válida" },
    { "param": "payment_amount",
      "user_message": "No puede ser vacío" }
  ]
}

merchant_message es para tus logs; user_message puedes mostrarlo al cliente.

Producción
IPs & seguridad

Para operar en producción, tu red y la de PagoDirecto deben reconocerse mutuamente. Coordina estos pasos con tu equipo de infraestructura.

Checklist de red
  • Reportas tus IPs (test y producción) para el whitelisting en el firewall de PagoDirecto.
  • Autorizas las IPs de PagoDirecto que envían los callbacks hacia tu servidor.
  • Reportas el/los dominios desde donde se mostrará el iFrame en tu web.
  • Reportas tu callback_url para habilitar las conexiones salientes de PagoDirecto.
🔐

Cada callback incluye tu llave en el header Authorization. Verifícala siempre antes de procesar el evento.

IPs de notificación de PagoDirecto
QA
20.165.6.103

Autoriza estas IPs en tu firewall para recibir los webhooks. Las direcciones definitivas se confirman durante el onboarding.

Último paso del roadmap

Checklist antes de pasar a producción

Revisa cada punto antes de activar tus llaves productivas. Evita el 90% de los incidentes de integración.

  • API Key de producción solicitada y activa
  • Callback URL sirve sobre HTTPS válido
  • Tu endpoint de callback responde siempre HTTP 200
  • Verificas la llave/firma antes de procesar cada webhook
  • Whitelist de IPs de PagoDirecto configurada en tu firewall
  • Timeouts configurados en tus llamadas salientes a la API
  • Reintentos con backoff implementados para errores 5xx/timeout
  • Handler de webhooks es idempotente (soporta reintentos de PagoDirecto)
  • Casos de prueba completados: éxito, error, expiración
  • Monitoreo/alertas activos sobre tu endpoint de callback