Saltar al contenido principal
Un payin es un cobro fiat: tu cliente paga en moneda local y tu cuenta recibe el abono en USDT automáticamente, convertido a tu tasa de payin (payin_rate en GET /v1/rates) menos la comisión fija de payin si tu cuenta la tiene configurada. Sea cual sea la modalidad, todos los caminos terminan igual — abono automático + webhook:

1. Descubre los corredores disponibles

Los países, monedas y modalidades disponibles los define CBPay. Consúltalos siempre por catálogo:
delivery indica cómo se confirma el pago del lado de CBPay (notificación del banco, sondeo o ambos) — no cambia nada en tu integración: tú siempre recibes el webhook payin_credited. Corredores y modalidades de cobro: La disponibilidad puede variar; el catálogo (GET /v1/payins/methods) es siempre la fuente de verdad. En todos los casos el abono llega igual: se convierte a USDT a tu payin_rate del momento y se acredita neto de la comisión fija de payin.

2. Elige la modalidad y crea el cobro

Cada país tiene su propia modalidad de cobro. El request y la respuesta real de cada una:
Página de pago hosted (fintoc) — recomendado: recibes una payment_url; el pagador la abre y transfiere desde cualquier banco o billetera chilena (Banco Estado, Santander, Mach, Tenpo, Mercado Pago…). El pago se detecta y valida automáticamente — sin referencias manuales.
Respuesta 201:
Comparte la payment_url con el pagador (link, redirección o WebView). Cuando el pago se confirma, tu cuenta se acredita en USDT y recibes el webhook payin_credited. El monto CLP debe ser entero (el peso chileno no usa decimales) y la sesión de pago vence en 24 horas por defecto. Un retry con la misma idempotency_key devuelve el mismo payin y la misma URL — nunca abre una segunda sesión de pago.Transferencia anunciada (alternativa manual): anuncias el depósito entrante y compartes la referencia con quien transfiere.
Respuesta 201:
Cuando la transferencia llega, se matchea por la referencia en la glosa (o por monto+moneda como respaldo) y tu cuenta se acredita automáticamente.
Crea un link de cobro universal: un solo POST /v1/payins con method: "checkout" devuelve una URL pública brandeada donde el pagador elige cómo pagar. El cobro se denomina en el saldo virtual que tú elijas (settlement_asset: USDT, USDC, BTC o GOLD, default USDT) y todo pago se convierte automáticamente a ese saldo al acreditarse — salvo que te paguen en el mismo asset, ahí no hay conversión. La página organiza el pago en cuatro pestañas:
  • CBPay — pago directo con la app: el alias y el QR del comercio; quien escanea con la app paga al instante por transferencia interna, en cualquiera de los 4 saldos.
  • Crypto — las monedas disponibles agrupadas por red (hoy USDT en TRON y Ethereum, USDC en Ethereum y BTC; redes nuevas aparecen solas al habilitarse), cada una con una dirección de depósito exclusiva de ese cobro y QR escaneable por wallets externas (Trust Wallet, MetaMask, Binance y similares).
  • Fiat — el pagador elige su país entre todos los que tienen corredor de payin vivo y ve los métodos disponibles (QR, transferencia bancaria, pago hosted) con el monto local cotizado al momento.
  • Tarjeta — pago con tarjeta de crédito o débito en una página segura, listado por moneda de cargo (hoy BOB y USD; monedas de adquirentes futuros aparecen solas). Cada moneda es una opción de pago independiente con su propio monto cotizado.
  • amount se denomina en el settlement_asset: "50" con USDT son 50 USDT; "0.001" con BTC son 0.001 BTC; "2" con GOLD son 2 gramos de oro. No envíes currency — es el contrato viejo y responde 400 (el cobro ya no se ata a una moneda local).
  • country es opcional y solo preselecciona el país en la página; el pagador puede cambiarlo.
  • GOLD no tiene riel de pago propio: el cobro se alcanza siempre por conversión automática desde lo que pague el cliente.
Respuesta 201:
Comparte la checkout_url (link, correo, WhatsApp, QR impreso). La página no exige login, lleva el branding de tu organización y se actualiza sola: cuando el pago se confirma por cualquiera de los métodos, muestra “pagado” y redirige a tu success_url si la configuraste.

Cómo paga cada rail

  • Fiat multi-país: el pagador elige país y método; el monto local se cotiza al momento (meta → USD → moneda local con tu payin_rate del corredor, redondeado hacia arriba) y queda congelado al elegir el método. El abono acredita con la conversión y comisiones normales de payin y después se convierte al settlement_asset. Un pago anunciado MENOR a la cotización congelada se acredita igual (la plata es real) pero no marca el link como pagado. Si un país ofrece el mismo método en varias monedas (ej. Bolivia con QR en BOB y en USD), la página lista cada moneda como opción independiente. En transferencias bancarias en México el link genera una CLABE dedicada y exclusiva de ese cobro: el pagador transfiere el monto exacto sin poner referencia — el abono se detecta y liquida automático porque la cuenta identifica al link. Si la cuenta dedicada no puede emitirse en ese momento, la página degrada al camino clásico (cuenta general del comercio + referencia obligatoria en la glosa).
  • Cobros pull (Venezuela): c2p y debito_inmediato cobran directo en la cuenta del pagador. La página le pide banco, documento, teléfono (C2P) o cuenta (débito inmediato) y la clave OTP — generada en su app bancaria para C2P, o enviada a demanda para débito inmediato (botón “Solicitar clave”). El monto SIEMPRE es el congelado en la cotización; si el rail confirma síncrono, el link queda pagado al instante. Un rechazo no mata el link: el pagador corrige los datos o elige otro método.
  • Tarjeta (multi-moneda): la pestaña lista cada moneda de cargo disponible con su monto cotizado; al elegir una se abre la página de pago hosted en esa moneda. Cada moneda es una materialización independiente (puedes cotizar en BOB y en USD sobre el mismo link; paga la primera que complete).
  • Crypto (wallet por cobro): al elegir una moneda se genera una dirección exclusiva con su qr_payload y qr_png_base64 — el QR lleva SIEMPRE la dirección cruda (BTC bech32, TRON base58, ETH hex) para máxima compatibilidad con wallets y exchanges (Binance y similares rechazan URIs BIP-21/EIP-681); el monto exacto se muestra al lado con botón copiar. Si el asset pagado difiere del settlement_asset, el due cotizado ya incluye la conversión (la cubre el pagador; tú recibes tu meta exacta). Los pagos parciales se acumulan y la página muestra cuánto falta. Cotizaciones con BTC/GOLD se refrescan cada 15 minutos.
  • App CBPay: el QR del comercio embebe el link (cbpay:pay?to=…&checkout=…). La app paga por transferencia interna en cualquiera de los 4 saldos: mismo asset ⇒ meta exacta; distinto ⇒ due con la conversión incluida. El monto se valida server-side contra una cotización fresca — si no cubre el cobro responde 422 checkout_amount_mismatch con el monto vigente. Integradores: POST /v1/transfers acepta el campo opcional checkout_token (o el QR extendido en to_qr_token); el destino se fuerza a la cuenta del link.

Conversión automática al saldo elegido

Todo abono en un asset distinto al settlement_asset se convierte con el motor de conversiones de tu cuenta (mismos spreads y límites que POST /v1/swaps). El estado agregado viaja en conversion_status:
  • GET {checkout_url}/state — estado del link: status, paid_method, settlement_asset, asset_amount, materializaciones fiat congeladas (fiat_methods), progreso crypto (crypto con due/received) y conversion_status.
  • GET {checkout_url}/quote — cotizaciones ANTES de elegir: countries (catálogo por país; cada país lista sus corredores en options[] — una fila por método+moneda, con collect: true en los métodos pull), cards (opciones de tarjeta por país y moneda con su local_amount), crypto (due indicativo por par) y cbpay (alias + dues por asset). Con ?country=XX agrega country_quote con el monto local por opción de ese país.
  • POST {checkout_url}/methods/{method} — materializa la opción elegida. Métodos fiat exigen ?country=XX; si el país ofrece el método en más de una moneda (tarjetas, QR BOB/USD en Bolivia) exige además &currency=YYY; crypto usa crypto:<chain>:<asset> (ej. crypto:tron:usdt) sin país. Los métodos pull devuelven el formulario del pagador (banks[], requires_otp_request) con la cotización congelada. Re-POST de la misma combinación devuelve la MISMA materialización.
  • POST {checkout_url}/collect/otp — solicita la clave OTP de un cobro pull cuando el rail la envía a demanda (requires_otp_request: true, ej. débito inmediato VE). Devuelve el otp_reference que acompaña al cobro final. Rate limit estricto (cada llamada es un SMS/push real).
  • POST {checkout_url}/collect — ejecuta el cobro pull con los datos del pagador (banco, documento, teléfono o cuenta, OTP). El monto siempre es el congelado; si el rail confirma síncrono responde paid: true y el link queda liquidado en la misma llamada.
Útil si prefieres renderizar tu propia página de pago sobre el mismo link.
  • Un link = un cobro: el primer método que completa el pago gana; un pago posterior por otro rail no se acredita (elegir un método NO bloquea los demás mientras nadie pague).
  • expires_in acepta de 600 a 604800 segundos (10 minutos a 7 días; default 24 horas). Al vencer sin pago el payin pasa a expired y recibes el webhook payin_expired.
  • El retry con la misma idempotency_key devuelve el mismo link (la URL no cambia); jamás se abre un segundo cobro.
  • El settlement_asset debe estar habilitado para tu organización; si está apagado la creación responde 422 settlement_asset_disabled.
Cuando el cobro se paga recibes el payin_credited con settled_via (ej. crypto:tron:usdt, qr, cbpay), settlement_asset y asset_amount; los pagos crypto agregan crypto_amount y los pagos con la app CBPay agregan transfer_id, asset y amount. Errores propios del link (los ve quien abre la página):

3. Recibe el abono

Cuando el pago llega (por cualquiera de las modalidades), tu cuenta se acredita automáticamente y se emite el webhook payin_credited:
fx_rate es tu payin_rate del momento del abono — la conversión se hace exactamente a esa tasa: usdt_gross = 700.00 / 6.91. El objeto payin queda con el detalle completo:

Estados

Los depósitos que llegan por transferencia directa sin referencia clara quedan unassigned hasta que el equipo de CBPay los asigna a una cuenta. Al asignarse, se acreditan con la tasa y comisiones de la cuenta destino.
Cuando un cobro activo (QR o checkout) muere sin pago, el payin pasa de pending a expired (o failed) automáticamente y recibes el webhook payin_expired. No se mueve dinero: si quieres reintentar el cobro, crea un payin nuevo.

Consulta e historial

from/to van en YYYY-MM-DD (UTC); fecha inválida responde 400 invalid_range.

Errores frecuentes

Última modificación el 17 de julio de 2026