<!-- Source: https://docs.infraio.xyz/es/api-reference -->
<!-- Last updated: 2026-10-04 -->

# 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](https://docs.infraio.xyz/es/api-reference/authentication) para la firma de
peticiones y [Errores](https://docs.infraio.xyz/es/api-reference/errors) para la forma del
envelope de error.

Esta página lista los endpoints para integraciones de comerciante.
Cuando un endpoint no tiene página propia, se describe en la página de
concepto relacionada.

> **Note:**
>
> Los endpoints bajo **`/b2b/v1/*`** se firman con HMAC usando tu clave
> **secreta** (`sk_…`). Esta es la superficie que llama tu backend. El
> dashboard del comerciante y el checkout alojado usan sus propios
> endpoints, que no forman parte de la API de integración.

## 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](https://docs.infraio.xyz/es/get-started/quickstart#2-create-a-checkout-session-server) 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. |

## Ó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](#cursor-pagination) 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](https://docs.infraio.xyz/es/concepts/refunds) 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. Puedes emitir
tokens desde tu backend (abajo) o desde el dashboard del comerciante.
Las renovaciones y cancelaciones se gestionan en el dashboard.

| 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`). |

### Ciclo de vida del reembolso (post-creación)

Aplica a ambos flujos. Los endpoints siguientes operan sobre el
reembolso en sí (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 Pay puede liquidar (mainnet + testnet, filtrado por entorno). |
| `GET` | `/v1/supported/tokens` | Todas las stablecoins en esas cadenas. |
| `GET` | `/v1/supported/currencies` | Monedas aceptadas para `order.currency`. |

## Salud

| Método | Ruta | Auth | Propósito |
| --- | --- | --- | --- |
| `GET` | `/health` | Ninguna (público) | Comprobación de liveness. Devuelve `{"status":"ok"}`. Apunta aquí tus monitores de uptime. |

## Paginación por cursor

Cada endpoint de lista acepta los mismos query params, devuelve el
mismo envelope. Los cursores son opacos y se usan en lugar de offsets
para que una página nunca se desplace cuando llega una fila nueva
mientras paginas.

| 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:

```json
{
  "orders": [ /* page rows */ ],
  "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0...",
  "has_next": true
}
```

`has_next` siempre está presente. `next_cursor` se omite cuando
`has_next` es `false`. Trata el cursor como una cadena opaca.

## Lo que falta en esta página

Esta página cubre los endpoints pensados para integraciones de
comerciante. Si necesitas un endpoint que no está listado, o una
especificación OpenAPI, contacta con soporte.
