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.
amountse denomina en elsettlement_asset:"50"conUSDTson 50 USDT;"0.001"conBTCson 0.001 BTC;"2"conGOLDson 2 gramos de oro. No envíescurrency— es el contrato viejo y responde400(el cobro ya no se ata a una moneda local).countryes opcional y solo preselecciona el país en la página; el pagador puede cambiarlo.GOLDno tiene riel de pago propio: el cobro se alcanza siempre por conversión automática desde lo que pague el cliente.
201:
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_ratedel 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 alsettlement_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):
c2pydebito_inmediatocobran 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). En la página de pago el pagador puede usar una tarjeta guardada: escribe su correo, lo verifica con un código y elige — con “Recordar este dispositivo” no repite el código por 30 días (ver tarjetas guardadas).
- Crypto (wallet por cobro): al elegir una moneda se genera una
dirección exclusiva con su
qr_payloadyqr_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 delsettlement_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 responde422 checkout_amount_mismatchcon el monto vigente. Integradores:POST /v1/transfersacepta el campo opcionalcheckout_token(o el QR extendido ento_qr_token); el destino se fuerza a la cuenta del link.
Conversión automática al saldo elegido
Todo abono en un asset distinto alsettlement_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:
Endpoints públicos del link (sin auth, rate-limited)
GET {checkout_url}/state— estado del link:status,paid_method,settlement_asset,asset_amount, materializaciones fiat congeladas (fiat_methods), progreso crypto (cryptocondue/received) yconversion_status.GET {checkout_url}/quote— cotizaciones ANTES de elegir:countries(catálogo por país; cada país lista sus corredores enoptions[]— una fila por método+moneda, concollect: trueen los métodos pull),cards(opciones de tarjeta por país y moneda con sulocal_amount),crypto(due indicativo por par) ycbpay(alias + dues por asset). Con?country=XXagregacountry_quotecon 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¤cy=YYY; crypto usacrypto:<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 elotp_referenceque 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 respondepaid: truey el link queda liquidado en la misma llamada.
Reglas del 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_inacepta de 600 a 604800 segundos (10 minutos a 7 días; default 24 horas). Al vencer sin pago el payin pasa aexpiredy recibes el webhookpayin_expired.- El retry con la misma
idempotency_keydevuelve el mismo link (la URL no cambia); jamás se abre un segundo cobro. - El
settlement_assetdebe estar habilitado para tu organización; si está apagado la creación responde422 settlement_asset_disabled.
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.
En GET /v1/payins y GET /v1/payins/{payin_id} los payins de checkout
llevan siempre su denominación — settlement_asset + asset_amount — en
todo estado (pendiente, vencido y abonado); currency/local_amount
quedan vacíos hasta que se usa un método de pago local. Un cobro
liquidado en crypto o vía la app CBPay expone su usdt_credited sin
fx_rate (no aplica cotización FX).
Errores propios del link (los ve quien abre la página):
Idioma
La página hospedada de checkout sigue la cadena pública:?lang= / ?locale= (un valor inválido se ignora),
luego la cookie del pagador cbpay_pay_locale, luego la cuenta del comercio, luego el default_locale de la org, luego Accept-Language, luego inglés.
El JSON de la API sigue en inglés. Detalle: Idioma y locale.
FAQ
¿El mismo link se puede pagar dos veces?
¿El mismo link se puede pagar dos veces?
No. Un link = un cobro: el primer riel que paga gana (
already_paid, 409).
Un depósito crypto que llega después de que el link se liquidó por otro riel
no se acredita — queda retenido para conciliación.¿Qué pasa si el pagador envía menos (o más) crypto que lo cotizado?
¿Qué pasa si el pagador envía menos (o más) crypto que lo cotizado?
Los pagos crypto parciales se acumulan: la página muestra cuánto falta
hasta cubrir el monto cotizado. Los pagos tardíos que llegan con el link
expirado igual acreditan tu cuenta.
¿Cuánto vive un link?
¿Cuánto vive un link?
expires_in entre 600 s y 7 días (default 24 h). Al expirar recibes el
webhook payin_expired y la página pública responde checkout_expired
(410).¿Qué pasa si falla la conversión a mi saldo de liquidación?
¿Qué pasa si falla la conversión a mi saldo de liquidación?
La plata queda segura en USDT y el payin reporta
conversion_status: pending_retry; la plataforma reintenta automáticamente
hasta que el swap resulte — nunca pierdes dinero ni se convierte dos veces.¿El pagador puede cambiar de método después de elegir uno?
¿El pagador puede cambiar de método después de elegir uno?
Sí. Cada método se materializa de forma independiente; volver a pedir el
mismo método devuelve la misma materialización. El primer riel que paga
liquida el link.
¿Puedo reintentar la creación del link sin riesgo?
¿Puedo reintentar la creación del link sin riesgo?
Sí — reintenta
POST /v1/payins con la misma idempotency_key y
recibes el mismo link. Una clave nueva crea un link nuevo e independiente.