Referencia de la API
Cada endpoint a continuación habla JSON, vive bajo
https://api.infraio.xyz (prod) o https://api-dev.infraio.xyz
(test) y se autentica vía HMAC-SHA256: consulta
Autenticación para el ritual de
firma y Errores para la forma del envelope
de error.
Esta página es el índice. Cada fila enlaza al desarrollo más profundo existente; si una fila solo referencia una ruta, el endpoint existe hoy pero está documentado en línea en la página de concepto relevante en lugar de en su propia página de referencia.
Prefijos de ruta del gateway y su modelo de auth:
/b2b/v1/*: firmado con HMAC usando tu clave secreta (sk_…). La superficie del backend del comerciante./payment/v1/*: Bearer JWT (sesiones del dashboard). Usado por el frontend del dashboard del comerciante; no para integradores de terceros./pub/v1/*: bearer-of-truth en la ruta (un tokenrfqt_…para solicitudes de reembolso). Sin credenciales. Seguro de llamar desde un navegador./checkout/:key/*: prefijo público para el flujo de checkout alojado.keyes lacst_…session key devuelta al crearla; el navegador del comprador es el único llamante. Sin credenciales.
Checkout
| Método | Ruta | Propósito | Notas |
|---|---|---|---|
POST | /b2b/v1/checkout-sessions/quick | Crea una sesión en una sola llamada: order + checkout-session emitidos juntos. | Consulta Inicio rápido para el request body y la muestra. |
POST | /b2b/v1/checkout-sessions | Crea una sesión contra una orden existente. Úsalo cuando tu plataforma ya tiene su propio modelo de orden y quieres una sesión por intento. | El flujo de dos pasos. |
GET | /b2b/v1/checkout-sessions/by-order/{order_id} | Lista todas las sesiones que se han emitido para una orden. | Útil cuando un comprador abandonó una sesión y quieres mostrar los intentos anteriores en tu dashboard. |
GET | /checkout/{session_key} | Público: la página de checkout alojada lo lee. Solo campos de cara al comprador (sin referencias internas). | Sin firma; usa la session_key como bearer-of-truth. |
POST | /checkout/{session_key}/intent | Público: elegir un método de pago en la página alojada. Emite un PaymentIntent con la dirección de depósito. | Lo llama checkout-web cuando el usuario selecciona método. |
POST | /checkout/{session_key}/verify | Público: dejar que el comprador pegue un tx hash para cortocircuitar la espera de confirmación. | Cae al chain watcher si el hash es incorrecto. |
Órdenes
Las órdenes son la entidad facturable atemporal. Una sola orden puede respaldar múltiples sesiones de checkout (p. ej., el comprador abandona, reintenta).
| Método | Ruta | Propósito | Notas |
|---|---|---|---|
POST | /b2b/v1/orders | Crea una orden sin una sesión. | Úsalo cuando quieras enviar al comprador un enlace de pago más tarde en lugar de redirigirlo inmediatamente. |
GET | /b2b/v1/orders/{id} | Lee una sola orden con line items + estado. | Estado: PENDING → PAID | PARTIAL_PAID | CANCELED. Tras el reembolso: PARTIALLY_REFUNDED | REFUNDED. |
GET | /b2b/v1/orders/by-merchant/{merchant_id} | Lista tus órdenes, paginado por cursor. | Consulta Paginación por cursor para el protocolo de cursor. |
PATCH | /b2b/v1/orders/{id}/cancel | Marca una orden no pagada como cancelada. Emite order.canceled. | Falla si la orden ya está pagada. |
PATCH | /b2b/v1/orders/{id}/reopen | Revertir una autocancelación (canceled_reason=payment_timeout). | Útil si el comprador vuelve después de que el TTL expire. |
Reembolsos
Consulta la página de concepto Reembolsos para el flujo saga y el ciclo de vida del token.
Iniciado por el comerciante
| Método | Ruta | Propósito | Notas |
|---|---|---|---|
POST | /b2b/v1/merchants/{merchant_id}/refunds | Reembolso iniciado por el comerciante. Auto-aprobado (salta PENDING). | Emite payment.refund.approved inmediatamente. |
Iniciado por el cliente — tokens de solicitud de reembolso
El comprador rellena el formulario de reembolso en nuestra página alojada; tú solo emites el token y entregas la URL. Dos rutas de emisión (HMAC para backends, JWT para el dashboard), tres rutas públicas de token (leer contexto, enviar, solicitar renovación) y dos rutas solo-dashboard para gestionar renovaciones.
| Método | Ruta | Auth | Propósito |
|---|---|---|---|
POST | /b2b/v1/merchants/{merchant_id}/refund-requests | HMAC (sk_…) | Emite un token desde tu backend. Body: {ref_type, ref_value, amount, ttl_seconds?, metadata?, hide_summary?, hide_header?}. ref_type es uno de order_id / order_number / session_id / session_key; ref_value es el identificador correspondiente. amount es obligatorio y bloquea el máximo que el comprador puede enviar. TTL por defecto 30 min. Emite refund_request.created (source: b2b). |
POST | /payment/v1/merchants/{merchant_id}/refund-requests | JWT (dashboard) | Emite un token desde el modal Emitir reembolso del dashboard del comerciante. Misma forma de body que la variante B2B. TTL por defecto 24 h. Emite refund_request.created (source: dashboard). |
GET | /pub/v1/refund-requests/{token} | Token en la ruta | Público: checkout-web lee el contexto del formulario (resumen de la orden, importe bloqueado, estado efectivo actual). |
POST | /pub/v1/refund-requests/{token}/submit | Token en la ruta | Público: el comprador envía el formulario. Body: {reason, refund_to_address, amount?, metadata?}. amount es opcional: cuando se omite, se usa el importe del enlace bloqueado por el comerciante; cuando está presente, el servidor exige amount ≤ importe bloqueado. Crea la fila Refund, emite payment.refund.requested, devuelve {link_token, refund_id} para la página de recibo. |
POST | /pub/v1/refund-requests/{token}/request-renewal | Token en la ruta | Público: el comprador solicita un enlace nuevo tras la expiración. Body: {customer_note?}. Emite refund_request.renewal_requested. |
GET | /payment/v1/merchants/{merchant_id}/refund-requests/renewals | JWT (dashboard) | Lista tokens pendientes RENEWAL_REQUESTED para el widget de renovaciones del comerciante. Paginado por cursor. |
POST | /payment/v1/merchants/{merchant_id}/refund-requests/renewals/{token}/issue-new | JWT (dashboard) | Aprueba una renovación: emite un nuevo token ACTIVE, retira el antiguo. Emite refund_request.renewed + refund_request.created (source: renewal). |
GET | /payment/v1/merchants/{merchant_id}/refund-requests/by-order/{order_id} | JWT (dashboard) | Lista todos los tokens de solicitud de reembolso que se han emitido contra una orden con su estado efectivo. Más recientes primero. |
POST | /payment/v1/merchants/{merchant_id}/refund-requests/{token}/send-email | JWT (dashboard) | Encola un envío por email del enlace de solicitud de reembolso al cliente. Body: {to}. Emite refund_request.email_send_requested. |
POST | /payment/v1/merchants/{merchant_id}/refund-requests/{token}/cancel | JWT (dashboard) | Kill-switch del comerciante: cambia ACTIVE o RENEWAL_REQUESTED → CANCELED. Body: {reason?}. Idempotente: una segunda llamada cuando el estado ya se ha movido devuelve éxito sin re-emitir. Emite refund_request.canceled en la primera transición. |
Ciclo de vida del reembolso (post-creación)
Aplica a ambos flujos. Los endpoints siguientes operan sobre la fila
Refund (id comienza con rfn_…), no sobre el token de solicitud.
| Método | Ruta | Propósito | Notas |
|---|---|---|---|
GET | /b2b/v1/refunds/{id} | Lee un reembolso. | Estado: PENDING → APPROVED → EXECUTED | REJECTED. |
GET | /b2b/v1/refunds/by-merchant/{merchant_id} | Lista tus reembolsos, paginado por cursor. | — |
POST | /b2b/v1/refunds/{id}/approve | Aprueba un reembolso PENDING (solo iniciado por el cliente: los iniciados por el comerciante aterrizan ya en APPROVED). | Cripto: aterriza en APPROVED, luego llamas a /submit-tx. |
POST | /b2b/v1/refunds/{id}/reject | Deniega un reembolso PENDING. | Emite payment.refund.rejected. |
POST | /b2b/v1/refunds/{id}/submit-tx | Solo cripto: sella el tx hash on-chain que difundiste. | Body: {tx_hash, network, token_address}: los tres son obligatorios. |
Catálogo (solo lectura)
| Método | Ruta | Propósito |
|---|---|---|
GET | /v1/supported/networks | Todas las cadenas en las que InfraIO puede liquidar (mainnet + testnet, filtrado por entorno). |
GET | /v1/supported/tokens | Todas las stablecoins en esas cadenas. |
GET | /v1/supported/currencies | Monedas fiat aceptadas para order.currency. |
GET | /v1/merchants/payment-methods | Métodos que ESTE comerciante tiene habilitados: combinación del catálogo de la plataforma + toggles por comerciante. Usado por checkout-web. |
GET | /v1/public/merchants/{merchant_id}/branding | Público: lo que la página de checkout lee para personalizarse. |
Salud
| Método | Ruta | Auth | Propósito |
|---|---|---|---|
GET | /health | Ninguna (público) | Sonda de liveness simple: devuelve {"status":"ok"}. Este (sin prefijo /v1) es el único endpoint de salud no autenticado: apunta aquí tus monitores de k8s / uptime. |
GET | /payment/v1/merchants/{merchant_id}/health | JWT del dashboard | Vista de salud por comerciante: tasa reciente de liquidación de intents, backlog de sweep. Útil para tus propias páginas de estado. Requiere un token de sesión del dashboard, no una clave de API B2B. Solo accesible bajo el prefijo /payment/ del gateway: la ruta bare /v1/... no está enrutada públicamente. |
GET | /payment/v1/stats/health | JWT del dashboard | Salud agregada a través del árbol de workspaces del comerciante. No es una sonda pública de liveness: se encuentra detrás de la misma auth JWT bajo el prefijo /payment/ del gateway. |
Paginación por cursor
Cada endpoint de lista acepta los mismos query params, devuelve el
mismo envelope. Usamos cursores opacos (base64url-encoded
(created_at, id)) en lugar de offsets para que una página nunca se
desplace cuando una fila aterriza a mitad de scroll.
| Query param | Tipo | Por defecto | Notas |
|---|---|---|---|
cursor | string | — | Opaco: copia el next_cursor de la respuesta anterior tal cual. |
limit | int | 20 | 1..100. |
sort_dir | 'asc' | 'desc' | desc | Ordena por (created_at, id). |
from / to | RFC3339 | — | Filtro opcional por ventana temporal. |
search | string | — | Filtro de texto libre donde se admite. |
Envelope de respuesta:
{
"orders": [ /* page rows */ ],
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0...",
"has_next": true
}has_next siempre está presente. next_cursor se omite cuando
has_next es false. No intentes parsear el cursor: su forma es
interna y cambiará.
Lo que falta en esta página
Este índice cubre la superficie de cara al comerciante: los endpoints
bajo /admin/* (herramientas del dashboard, revisión KYB, gestión de
red) y las rutas gRPC internas no se listan intencionadamente. La
especificación OpenAPI generada por swag cubre la superficie
completa; si la necesitas, contacta con soporte y te compartiremos
una snapshot actualizada.