{"openapi":"3.0.3","info":{"title":"NIIO Payments API","description":"API para integración de cobros en Colombia. Acepta PSE, transferencias bancarias y criptomonedas (BTC, ETH, USDT, USDC).\n\n## Autenticación\n\nTodas las solicitudes requieren dos headers:\n- `X-Api-Key`: Tu API Key (ej: `niio_live_xxx`)\n- `X-Api-Secret`: Tu API Secret\n\nObtén tus credenciales en **Dashboard → Configuración → API Keys**.\n\n## Métodos de Pago\n\n| Método | Descripción |\n|--------|-------------|\n| `PSE` | Pago por PSE (débito bancario Colombia) |\n| `BANK_TRANSFER` | Transferencia bancaria |\n| `CRYPTO` | Criptomonedas (BTC, ETH, USDT, USDC) |\n\n## Cobertura por País\n\n| Producto | País | Opciones |\n|----------|------|----------|\n| **Cobros (Payin)** | 🇨🇴 Colombia | PSE, transferencia bancaria; Nequi, Bancolombia y Bre-B según habilitación de tu comercio (Direct API) |\n| **Cobros (Payin)** | 🌎 Global | Criptomonedas: BTC, ETH, USDT, USDC |\n| **Dispersiones (Payout)** | 🇨🇴 Colombia | Cuenta bancaria (`BANK`) y llave Bre-B (`BREB`), en COP |\n| **Recargas** | 🇨🇴 Colombia | Recarga de celular de cualquier operadora, en COP |\n| **Facturas** | 🇨🇴 Colombia | Pago de facturas/convenios (servicios públicos, créditos…), en COP |\n\n## Flujo de Integración\n\n1. **Crear orden** - POST /v1/collect con datos del cobro\n2. **Redirigir cliente** - Envía al cliente a la `collectUrl` retornada\n3. **Cliente paga** - El cliente selecciona método y completa el pago\n4. **Recibir webhook** - NIIO notifica cuando el pago se completa\n5. **Verificar estado** - (Opcional) Consulta GET /v1/collect/:id, lista tus transacciones con GET /v1/collect y concilia totales con GET /v1/collect/stats\n\n**Direct API (opcional):** si prefieres construir tu propia UI de pago, reemplaza el paso 2 por GET /collect/:id/methods + POST /collect/:id/pay y obtén directamente el link del proveedor (PSE, Nequi, Bre-B…). Requiere habilitación previa — ambas modalidades conviven.","version":"1.0.0","contact":{"name":"NIIO Developers","url":"https://pay.niiopay.com/docs"}},"servers":[{"url":"https://api.prod.niiopay.com/api/v1","description":"Producción"}],"tags":[{"name":"Cobros (Payin)","description":"Crea y consulta órdenes de cobro: tu cliente te paga por PSE, transferencia bancaria o criptomonedas, vía checkout hosteado o Direct API. _(EN: Payins — collect payments from your customers.)_"},{"name":"Dispersiones (Payout)","description":"Dispersa fondos de tu saldo NIIO a terceros. _(EN: Payouts — send funds from your balance to third parties.)_\n\n## Países y opciones de dispersión\n\n| País | Opción de dispersión | `network` | Moneda destino |\n|------|----------------------|-------------|----------------|\n| 🇨🇴 Colombia | Cuenta bancaria (ahorros o corriente, cualquier banco del catálogo) | `BANK` | COP |\n| 🇨🇴 Colombia | Llave Bre-B (alias @usuario, teléfono, email o documento) | `BREB` | COP |\n\nPagas con tu saldo `COPM` (default) o `USDT`. Consulta **GET /payout/methods** antes de crear una dispersión: ese catálogo es la fuente de verdad de los métodos, bancos, campos y topes habilitados para tu comercio."},{"name":"Recargas","description":"Vende recargas de celular a tus usuarios. Cada recarga debita tu saldo NIIO (COPM). Consulta **GET /topup/operators** para las operadoras. Requiere habilitación de tu comercio. _(EN: Mobile top-ups.)_"},{"name":"Facturas","description":"Cobra el pago de facturas/convenios a tus usuarios. Busca convenios con **GET /bills/agreements**, consulta la deuda con **POST /bills/check** y paga con **POST /bills/pay** (debita tu saldo COPM). Requiere habilitación de tu comercio. _(EN: Bill payments.)_"},{"name":"Webhooks","description":"Notificaciones de eventos de pago"}],"paths":{"/collect":{"post":{"tags":["Cobros (Payin)"],"summary":"Crear orden de cobro","description":"Crea una nueva orden de cobro y genera un link de pago para tu cliente.","operationId":"createCollectOrder","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCollectOrderRequest"},"example":{"reference":"ORDER-12345","amount":150000,"currency":"COP","description":"Pago de factura #12345","customerName":"Juan Pérez","customerEmail":"juan@email.com","customerDocType":"CC","customerDocNumber":"1234567890","expirationMinutes":60,"callbackUrl":"https://mitienda.com/pago-exitoso","allowedMethods":["PSE","BANK_TRANSFER","CRYPTO"],"metadata":{"orderId":"12345","userId":"user_abc"}}}}},"responses":{"201":{"description":"Orden creada exitosamente","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCollectOrderResponse"},"example":{"success":true,"data":{"id":"clxyz123abc456def","reference":"ORDER-12345","amount":150075,"baseAmount":150000,"feeAmount":75,"currency":"COP","status":"PENDING","collectUrl":"https://pay.niiopay.com/c/clxyz123abc456def","expiresAt":"2024-01-15T13:00:00.000Z","createdAt":"2024-01-15T12:00:00.000Z"}}}}},"400":{"description":"Error de validación","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"El campo amount es requerido","details":{"field":"amount"}}}}}},"401":{"description":"No autorizado - API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"INVALID_API_KEY","message":"API Key inválido o no encontrado"}}}}}}},"get":{"tags":["Cobros (Payin)"],"summary":"Listar órdenes de cobro (transacciones)","description":"Lista las transacciones de cobro de tu comercio, de la más reciente a la más antigua. Filtra por `status` y pagina con `limit`/`offset`. Úsalo para conciliación; el estado autoritativo de un pago completado siempre llega por el webhook firmado.","operationId":"listCollectOrders","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Filtrar por estado de la orden","schema":{"type":"string","enum":["PENDING","PROCESSING","WAITING_TRANSFER","COMPLETED","FAILED","EXPIRED"]}},{"name":"limit","in":"query","required":false,"description":"Máximo de resultados por página","schema":{"type":"integer","default":20}},{"name":"offset","in":"query","required":false,"description":"Desplazamiento para paginación","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Listado de órdenes (cada elemento con el mismo shape que GET /collect/{id})","content":{"application/json":{"example":{"success":true,"data":[{"id":"clxyz123abc456def","reference":"ORDER-12345","amount":150075,"baseAmount":150000,"feeAmount":75,"currency":"COP","description":"Pago de factura #12345","status":"COMPLETED","selectedMethod":"PSE","allowedMethods":["PSE","BANK_TRANSFER"],"customer":{"name":"Juan Pérez","email":"juan@email.com","documentType":"CC","documentNumber":"1234567890"},"collectUrl":"https://pay.niiopay.com/c/clxyz123abc456def","callbackUrl":"https://mitienda.com/pago-exitoso","expiresAt":"2024-01-15T13:00:00.000Z","paidAt":"2024-01-15T12:15:00.000Z","createdAt":"2024-01-15T12:00:00.000Z","updatedAt":"2024-01-15T12:15:00.000Z","metadata":{"orderId":"12345"}}]}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/collect/stats":{"get":{"tags":["Cobros (Payin)"],"summary":"Estadísticas de cobros del comercio","description":"Totales agregados de tus órdenes de cobro: conteo total, conteos por estado (PENDING/COMPLETED/FAILED) y monto total recaudado (`totalCollected`, suma de `amount` de las órdenes COMPLETED). `totalCollected` llega como string decimal; es `0` numérico si aún no hay órdenes completadas.","operationId":"getCollectStats","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"responses":{"200":{"description":"Estadísticas del comercio","content":{"application/json":{"example":{"success":true,"data":{"total":128,"pending":3,"completed":117,"failed":8,"totalCollected":"17550000"}}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/collect/{id}":{"get":{"tags":["Cobros (Payin)"],"summary":"Obtener orden de cobro","description":"Obtiene los detalles y estado actual de una orden de cobro.","operationId":"getCollectOrder","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID de la orden de cobro","schema":{"type":"string","example":"clxyz123abc456def"}}],"responses":{"200":{"description":"Detalles de la orden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCollectOrderResponse"},"example":{"success":true,"data":{"id":"clxyz123abc456def","reference":"ORDER-12345","amount":150075,"baseAmount":150000,"feeAmount":75,"currency":"COP","description":"Pago de factura #12345","status":"COMPLETED","selectedMethod":"PSE","allowedMethods":["PSE","BANK_TRANSFER"],"customer":{"name":"Juan Pérez","email":"juan@email.com","documentType":"CC","documentNumber":"1234567890"},"collectUrl":"https://pay.niiopay.com/c/clxyz123abc456def","callbackUrl":"https://mitienda.com/pago-exitoso","metadata":{"orderId":"12345"},"expiresAt":"2024-01-15T13:00:00.000Z","paidAt":"2024-01-15T12:15:00.000Z","createdAt":"2024-01-15T12:00:00.000Z","updatedAt":"2024-01-15T12:15:00.000Z"}}}}},"404":{"description":"Orden no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"ORDER_NOT_FOUND","message":"Orden de cobro no encontrada"}}}}}}}},"/collect/{id}/methods":{"get":{"tags":["Cobros (Payin)"],"summary":"Listar métodos de pago (Direct API)","description":"Métodos que POST /collect/{id}/pay puede ejecutar para esta orden, con los campos a capturar del pagador (options inline para selects). Requiere la Direct API habilitada para tu comercio; sin habilitar responde 503.","operationId":"getCollectOrderMethods","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID de la orden de cobro","schema":{"type":"string","example":"clxyz123abc456def"}}],"responses":{"200":{"description":"Métodos disponibles para la orden","content":{"application/json":{"example":{"success":true,"data":[{"method":"pse","label":"PSE","uiType":"webview","currency":"COP","minAmount":5000,"requiredFields":[{"key":"bank","type":"bankSelect","label":"Banco","required":true,"options":[{"value":"1007","label":"Bancolombia"}]},{"key":"phone","type":"phone","label":"Teléfono","required":true}]},{"method":"nequi","label":"Nequi","uiType":"push","currency":"COP","minAmount":5000,"requiredFields":[{"key":"phone","type":"phone","label":"Teléfono","required":true}]}]}}}},"404":{"description":"Orden no encontrada (o no pertenece a tu comercio)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Direct API no habilitada para tu comercio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/collect/{id}/pay":{"post":{"tags":["Cobros (Payin)"],"summary":"Crear el cargo y obtener el link de pago (Direct API)","description":"Crea el cargo con el proveedor y devuelve el link de pago (flow redirect), la instrucción push o la llave copiable (flow key) — sin pasar por el checkout hosteado. El pago se confirma SOLO por el webhook firmado, nunca por el retorno del pagador. Reintentar crea un cargo nuevo en el proveedor. Requiere la Direct API habilitada; sin habilitar responde 503.","operationId":"payCollectOrder","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID de la orden de cobro","schema":{"type":"string","example":"clxyz123abc456def"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["method"],"properties":{"method":{"type":"string","description":"Key del método tal como la sirve GET /collect/{id}/methods","example":"pse"},"fields":{"type":"object","description":"Valores de los requiredFields del método (misma key)","additionalProperties":{"type":"string"}},"payer":{"type":"object","description":"Datos del pagador (opcional)","properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"docType":{"type":"string","example":"CC"},"docNumber":{"type":"string"}}},"returnUrl":{"type":"string","description":"HTTPS. Adonde vuelve el pagador tras pagar en el proveedor (solo métodos redirect). El retorno NO confirma el pago.","example":"https://mitienda.com/pagos/retorno"}}},"example":{"method":"pse","fields":{"bank":"1007","phone":"3001234567","docType":"CC","docNumber":"1234567890"},"returnUrl":"https://mitienda.com/pagos/retorno"}}}},"responses":{"200":{"description":"Cargo creado. Según flow: redirect (usar paymentUrl), push (el pagador aprueba en su app) o key (mostrar keyValue).","content":{"application/json":{"examples":{"redirect":{"summary":"PSE / Bancolombia — redirigir a paymentUrl","value":{"success":true,"data":{"paymentUrl":"https://registro.pse.com.co/PSEUserRegister/...","transactionId":"tx-123","method":"pse","flow":"redirect"}}},"push":{"summary":"Nequi — solicitud push en la app del pagador","value":{"success":true,"data":{"paymentUrl":null,"transactionId":"tx-124","method":"nequi","flow":"push"}}},"key":{"summary":"Bre-B — llave copiable","value":{"success":true,"data":{"paymentUrl":null,"transactionId":"tx-125","method":"breb","flow":"key","keyValue":"@llave-breb","expiresAt":"2026-07-20T15:00:00.000Z"}}}}}}},"400":{"description":"Método no disponible para la orden o datos inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Orden no encontrada (o no pertenece a tu comercio)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Direct API no habilitada para tu comercio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payout/methods":{"get":{"tags":["Dispersiones (Payout)"],"summary":"Catálogo de opciones de dispersión disponibles","description":"Devuelve las opciones de dispersión habilitadas para tu comercio (cobertura actual: 🇨🇴 Colombia, en COP), con sus campos requeridos (`requiredFields`), el valor exacto de `network` a enviar en el POST, los bancos disponibles (`banks`, con su `bankCanonicalId`) y el tope por transacción. Consúltalo antes de crear un payout: un método fuera de este catálogo se rechaza con `PAYOUT_METHOD_NOT_AVAILABLE`. Si el payout está deshabilitado globalmente, responde `enabled: false` con lista vacía.","operationId":"listPayoutMethods","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"responses":{"200":{"description":"Catálogo de métodos","content":{"application/json":{"example":{"success":true,"data":{"enabled":true,"methods":[{"method":"bank","label":"Cuenta bancaria","network":"BANK","currency":"COP","minAmount":null,"limits":{"maxAmountCop":2000000},"requiredFields":[{"key":"amount","required":true,"type":"number"},{"key":"bankCanonicalId","required":true,"type":"string"},{"key":"accountType","required":true,"type":"string","enum":["SAVINGS","CHECKING"]},{"key":"accountNumber","required":true,"type":"string"}],"banks":[{"bankCanonicalId":"bancolombia","name":"Bancolombia"}]},{"method":"breb","label":"Bre-B","network":"BREB","currency":"COP","minAmount":null,"limits":{"maxAmountCop":2000000},"requiredFields":[{"key":"amount","required":true,"type":"number"},{"key":"keyValue","required":true,"type":"string"}]}]}}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"El payout por API no está habilitado para tu comercio o la key no tiene payout:create","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payout":{"get":{"tags":["Dispersiones (Payout)"],"summary":"Listar payouts del comercio (transacciones)","description":"Lista las dispersiones de tu comercio, de la más reciente a la más antigua. Filtra por `status` y pagina con `limit` (default 20, máx 100) y `offset`. Cada elemento tiene el mismo shape que GET /payout/{id}.","operationId":"listPayouts","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Filtrar por estado del payout","schema":{"type":"string","enum":["PENDING","PROCESSING","COMPLETED","FAILED","REFUNDED"]}},{"name":"limit","in":"query","required":false,"description":"Máximo de resultados por página (máx 100)","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","required":false,"description":"Desplazamiento para paginación","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Listado de payouts","content":{"application/json":{"example":{"success":true,"data":[{"payoutId":"clpay123abc456def","status":"COMPLETED","amount":100000,"feeAmount":500,"recipientName":"María Gómez","network":"breb","providerPayoutId":"mm_abc123","createdAt":"2024-01-15T12:00:00.000Z","completedAt":"2024-01-15T12:01:30.000Z"}]}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"El payout por API no está habilitado para tu comercio o la key no tiene payout:create","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Dispersiones (Payout)"],"summary":"Crear payout (dispersión COP)","description":"Dispersa fondos de tu saldo NIIO a una cuenta bancaria o llave Bre-B en Colombia. Requiere una API Key con el permiso `payout:create` (contacta a NIIO para habilitarlo). El pagador del fee eres tú (fee on-top): la respuesta incluye `feeAmount`. La cabecera `Idempotency-Key` es obligatoria: un reintento con la misma clave no duplica el envío.","operationId":"createPayout","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Clave única de idempotencia por payout (evita dobles envíos ante reintentos).","schema":{"type":"string","example":"a1b2c3d4-e5f6-7890"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePayoutRequest"},"example":{"amount":100000,"currency":"COPM","recipientName":"María Gómez","recipientDocType":"CC","recipientDocNumber":"1020304050","network":"BREB","keyValue":"@mariagomez","keyType":"ALPHANUMERIC","description":"Pago proveedor #55"}}}},"responses":{"201":{"description":"Payout creado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePayoutResponse"},"example":{"success":true,"data":{"payoutId":"clpay123abc456def","status":"PENDING","amount":100000,"feeAmount":500,"recipientName":"María Gómez","network":"breb","providerPayoutId":"mm_abc123","createdAt":"2024-01-15T12:00:00.000Z","completedAt":null}}}}},"400":{"description":"Error de validación, falta Idempotency-Key, excede el tope por transacción, o el método no está en el catálogo (PAYOUT_METHOD_NOT_AVAILABLE — consulta GET /payout/methods)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"PAYOUT_METHOD_NOT_AVAILABLE","message":"El método 'bank' no está disponible por API. Consulta GET /api/v1/payout/methods."}}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"El payout por API no está habilitado para tu comercio, o la API Key no tiene el permiso payout:create","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"FORBIDDEN","message":"Esta API key no tiene el permiso payout:create"}}}}},"503":{"description":"Payout deshabilitado temporalmente o sin proveedor disponible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payout/{id}":{"get":{"tags":["Dispersiones (Payout)"],"summary":"Consultar estado de un payout","description":"Obtiene el estado actual de un payout creado por tu comercio.","operationId":"getPayout","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"ID del payout","schema":{"type":"string","example":"clpay123abc456def"}}],"responses":{"200":{"description":"Detalle del payout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPayoutResponse"},"example":{"success":true,"data":{"payoutId":"clpay123abc456def","status":"COMPLETED","amount":100000,"feeAmount":500,"recipientName":"María Gómez","network":"breb","providerPayoutId":"mm_abc123","createdAt":"2024-01-15T12:00:00.000Z","completedAt":"2024-01-15T12:01:30.000Z"}}}}},"404":{"description":"Payout no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"NOT_FOUND","message":"Payout no encontrado"}}}}}}}},"/topup/operators":{"get":{"tags":["Recargas"],"summary":"Listar operadoras de recarga","description":"Operadoras de celular disponibles para recarga. Usa el `code` de la operadora como `operatorCode` en POST /topup.","operationId":"listTopupOperators","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"responses":{"200":{"description":"Operadoras disponibles","content":{"application/json":{"example":{"success":true,"data":[{"code":"737","name":"WOM RECARGAS","logo":"https://storage.googleapis.com/bucket-faas/suppliers/737.webp"},{"code":"959","name":"MOVISTAR","logo":"https://storage.googleapis.com/bucket-faas/suppliers/959.webp"}]}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/topup":{"post":{"tags":["Recargas"],"summary":"Recargar un celular","description":"Recarga un celular colombiano. Debita tu saldo NIIO (COPM); el fee es on-top (la respuesta incluye `feeCop`). La cabecera `Idempotency-Key` (o el campo `idempotencyKey`) es obligatoria: un reintento con la misma clave no duplica la recarga. Requiere habilitación de tu comercio (contacta a NIIO).","operationId":"createTopup","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de idempotencia (alternativa al campo idempotencyKey del body). Requerida.","schema":{"type":"string","example":"a1b2c3d4-e5f6-7890"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phone","operatorCode","amountCop"],"properties":{"phone":{"type":"string","example":"3105571371"},"operatorCode":{"type":"string","example":"737"},"amountCop":{"type":"integer","example":5000},"idempotencyKey":{"type":"string","example":"a1b2c3d4-e5f6-7890"}}},"example":{"phone":"3105571371","operatorCode":"737","amountCop":5000,"idempotencyKey":"a1b2c3d4-e5f6-7890"}}}},"responses":{"201":{"description":"Recarga creada","content":{"application/json":{"example":{"success":true,"data":{"id":"clrec123abc456def","status":"completed","phone":"3105571371","amountCop":5000,"feeCop":150,"totalCop":5150,"reference":"TRACE123","ticket":{}}}}}},"400":{"description":"Error de validación, falta idempotencyKey, o excede el tope por transacción","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"La recarga por API no está habilitada para tu comercio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/bills/agreements":{"get":{"tags":["Facturas"],"summary":"Buscar convenios / facturas","description":"Busca los convenios disponibles (servicios públicos, créditos, etc.). Filtra por texto con `q` y pagina con `page`.","operationId":"listBillAgreements","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"q","in":"query","required":false,"description":"Texto de búsqueda del convenio","schema":{"type":"string","example":"EPM"}},{"name":"page","in":"query","required":false,"description":"Página (default 1)","schema":{"type":"integer","default":1}}],"responses":{"200":{"description":"Convenios disponibles","content":{"application/json":{"example":{"success":true,"data":{"items":[{"agreementId":43500,"name":"ALOCREDIT - PAGO CREDITOS","referenceLabel":"Numero de Cedula","type":"Referenciado"}],"total":22}}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/bills/check":{"post":{"tags":["Facturas"],"summary":"Consultar la deuda de un convenio","description":"Consulta las facturas/productos a pagar de un convenio para una referencia dada. Solo lectura: no cobra.","operationId":"checkBill","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agreementId","reference"],"properties":{"agreementId":{"type":"integer","example":43500},"reference":{"type":"string","example":"900123456"}}},"example":{"agreementId":43500,"reference":"900123456"}}}},"responses":{"200":{"description":"Facturas/productos a pagar del convenio","content":{"application/json":{"example":{"success":true,"data":{"agreementId":43500,"agreementName":"ALOCREDIT - PAGO CREDITOS","supplierMessage":null,"products":[{"codeRecord":"R1","description":"Factura enero","amount":50000,"minAmount":null,"maxAmount":null}]}}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/bills/pay":{"post":{"tags":["Facturas"],"summary":"Pagar una factura","description":"Paga una factura de un convenio. Debita tu saldo NIIO (COPM); el fee es on-top (`feeCop`). Revalida la deuda con un check fresco antes de cobrar. `codeRecord` es opcional si el convenio devuelve una sola factura. La cabecera `Idempotency-Key` (o el campo `idempotencyKey`) es obligatoria. Requiere habilitación de tu comercio.","operationId":"payBill","security":[{"ApiKeyAuth":[],"ApiSecretAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de idempotencia (alternativa al campo idempotencyKey del body). Requerida.","schema":{"type":"string","example":"a1b2c3d4-e5f6-7890"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agreementId","reference","amountCop"],"properties":{"agreementId":{"type":"integer","example":43500},"reference":{"type":"string","example":"900123456"},"codeRecord":{"type":"string","example":"R1"},"amountCop":{"type":"integer","example":50000},"idempotencyKey":{"type":"string","example":"a1b2c3d4-e5f6-7890"}}},"example":{"agreementId":43500,"reference":"900123456","codeRecord":"R1","amountCop":50000,"idempotencyKey":"a1b2c3d4-e5f6-7890"}}}},"responses":{"201":{"description":"Pago creado","content":{"application/json":{"example":{"success":true,"data":{"id":"clbill123abc456def","status":"completed","amountCop":50000,"feeCop":500,"totalCop":50500,"reference":"TRACEBILL","ticket":{}}}}}},"400":{"description":"Error de validación, falta idempotencyKey, o excede el tope por transacción","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"API Key o Secret inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"El pago de facturas por API no está habilitado para tu comercio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhooks":{"post":{"tags":["Webhooks"],"summary":"Recibir notificación de pago (tu servidor)","description":"NIIO envía webhooks a tu servidor cuando ocurren eventos de pago.\n\n## Configuración\n\nConfigura tu URL de webhook en **Dashboard → Configuración → Webhooks**.\n\n## Eventos\n\n| Evento | Descripción |\n|--------|-------------|\n| `payment.completed` | El pago fue procesado exitosamente |\n| `payment.failed` | El pago falló o fue rechazado |\n\n## Headers de Verificación\n\nCada webhook incluye headers para verificar su autenticidad:\n\n- `X-NIIO-Signature`: Firma HMAC-SHA256 del payload\n- `X-NIIO-Timestamp`: Timestamp Unix de la solicitud\n\n## Verificación de Firma\n\n```javascript\nconst crypto = require('crypto');\n\nfunction verifyWebhookSignature(payload, signature, timestamp, webhookSecret) {\n  const signedPayload = `${timestamp}.${JSON.stringify(payload)}`;\n  const expectedSignature = crypto\n    .createHmac('sha256', webhookSecret)\n    .update(signedPayload)\n    .digest('hex');\n  return signature === `sha256=${expectedSignature}`;\n}\n```\n\n## Reintentos\n\nSi tu servidor no responde con HTTP 2xx, NIIO reintenta:\n- Intento 1: Inmediato\n- Intento 2: 5 minutos\n- Intento 3: 30 minutos\n- Intento 4: 2 horas\n- Intento 5: 24 horas\n\nDespués de 5 intentos fallidos, el webhook se marca como fallido.","operationId":"receiveWebhook","x-webhook":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPayload"},"examples":{"paymentCompleted":{"summary":"Pago completado","value":{"event":"payment.completed","data":{"id":"clxyz123abc456def","reference":"ORDER-12345","amount":150075,"baseAmount":150000,"feeAmount":75,"currency":"COP","status":"COMPLETED","paidAt":"2024-01-15T12:15:00.000Z","metadata":{"orderId":"12345","userId":"user_abc"}},"timestamp":"2024-01-15T12:15:00.000Z"}},"paymentFailed":{"summary":"Pago fallido","value":{"event":"payment.failed","data":{"id":"clxyz123abc456def","reference":"ORDER-12345","amount":150000,"currency":"COP","status":"FAILED","paidAt":null,"metadata":{"orderId":"12345","userId":"user_abc"}},"timestamp":"2024-01-15T12:15:00.000Z"}}}}}},"responses":{"200":{"description":"Webhook recibido correctamente. Responde con cualquier código 2xx para confirmar recepción.","content":{"application/json":{"example":{"received":true}}}}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-Api-Key","description":"Tu API Key de NIIO"},"ApiSecretAuth":{"type":"apiKey","in":"header","name":"X-Api-Secret","description":"Tu API Secret de NIIO"}},"schemas":{"CreateCollectOrderRequest":{"type":"object","required":["reference","amount","customerName","customerEmail","customerDocType","customerDocNumber"],"properties":{"reference":{"type":"string","description":"Identificador único de la orden en tu sistema","maxLength":100,"example":"ORDER-12345"},"amount":{"type":"number","description":"Monto que recibe tu comercio en COP (mínimo 1,000). Se añade un fee de 0.05% on-top que paga el pagador: el pagador verá amount + fee, y tu comercio recibe este monto completo.","minimum":1000,"example":150000},"currency":{"type":"string","description":"Código de moneda. COP para fiat, o USDT/USDC/BTC/ETH para crypto","default":"COP","enum":["COP","USDT","USDC","BTC","ETH"]},"description":{"type":"string","description":"Descripción del cobro visible para el cliente","maxLength":500},"customerName":{"type":"string","description":"Nombre completo del cliente","maxLength":200,"example":"Juan Pérez"},"customerEmail":{"type":"string","format":"email","description":"Email del cliente","example":"juan@email.com"},"customerDocType":{"type":"string","description":"Tipo de documento","enum":["CC","CE","NIT","PP"],"example":"CC"},"customerDocNumber":{"type":"string","description":"Número de documento","example":"1234567890"},"expirationMinutes":{"type":"integer","description":"Tiempo de expiración en minutos","default":60,"minimum":5,"maximum":10080},"callbackUrl":{"type":"string","format":"uri","description":"URL de redirección después del pago"},"allowedMethods":{"type":"array","items":{"type":"string","enum":["PSE","BANK_TRANSFER","CRYPTO"]},"description":"Métodos de pago permitidos. CRYPTO permite pago con BTC, ETH, USDT, USDC"},"metadata":{"type":"object","description":"Datos adicionales (retornados en webhooks)","additionalProperties":true}}},"CreateCollectOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","description":"ID de la orden"},"reference":{"type":"string"},"amount":{"type":"number","description":"Monto que paga el pagador (baseAmount + feeAmount).","example":150075},"baseAmount":{"type":"number","nullable":true,"description":"Monto que recibe tu comercio (el que enviaste en el request).","example":150000},"feeAmount":{"type":"number","nullable":true,"description":"Fee on-top 0.05% que paga el pagador.","example":75},"currency":{"type":"string"},"status":{"type":"string","enum":["PENDING"]},"collectUrl":{"type":"string","format":"uri","description":"URL de pago para redirigir al cliente"},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}},"GetCollectOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string"},"reference":{"type":"string"},"amount":{"type":"number","description":"Monto que paga el pagador (baseAmount + feeAmount).","example":150075},"baseAmount":{"type":"number","nullable":true,"description":"Monto que recibe tu comercio.","example":150000},"feeAmount":{"type":"number","nullable":true,"description":"Fee on-top 0.05% que paga el pagador.","example":75},"currency":{"type":"string"},"description":{"type":"string"},"status":{"type":"string","enum":["PENDING","PROCESSING","WAITING_TRANSFER","COMPLETED","FAILED","EXPIRED"],"description":"Estado de la orden"},"selectedMethod":{"type":"string","enum":["PSE","BANK_TRANSFER","CRYPTO"],"nullable":true},"allowedMethods":{"type":"array","items":{"type":"string"}},"customer":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"documentType":{"type":"string"},"documentNumber":{"type":"string"}}},"collectUrl":{"type":"string","format":"uri"},"callbackUrl":{"type":"string","format":"uri","nullable":true},"metadata":{"type":"object"},"expiresAt":{"type":"string","format":"date-time"},"paidAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}},"CreatePayoutRequest":{"type":"object","required":["amount","recipientName","recipientDocType","recipientDocNumber"],"properties":{"amount":{"type":"number","description":"Monto a dispersar (COP).","example":100000},"currency":{"type":"string","enum":["COPM","USDT"],"description":"Moneda con la que pagas (default COPM)."},"recipientName":{"type":"string","description":"Nombre completo del beneficiario."},"recipientDocType":{"type":"string","description":"Tipo de documento (CC, CE, NIT, PP)."},"recipientDocNumber":{"type":"string","description":"Número de documento del beneficiario."},"network":{"type":"string","enum":["BANK","BREB"],"description":"Riel de dispersión: cuenta bancaria (BANK) o llave Bre-B (BREB).","default":"BANK"},"bankCanonicalId":{"type":"string","description":"ID del banco (requerido si network=BANK)."},"accountType":{"type":"string","enum":["SAVINGS","CHECKING"],"description":"Tipo de cuenta (requerido si network=BANK)."},"accountNumber":{"type":"string","description":"Número de cuenta (requerido si network=BANK)."},"keyValue":{"type":"string","description":"Llave Bre-B: alias (@usuario), teléfono, email o documento (requerido si network=BREB)."},"keyType":{"type":"string","enum":["PHONE","EMAIL","ALPHANUMERIC","ID","BCODE"],"description":"Tipo de llave Bre-B (requerido si network=BREB)."},"description":{"type":"string","description":"Descripción (máx 40 chars)."},"idempotencyKey":{"type":"string","description":"Clave de idempotencia (alternativa al header Idempotency-Key)."}}},"CreatePayoutResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"payoutId":{"type":"string"},"status":{"type":"string","enum":["PENDING","PROCESSING","COMPLETED","FAILED","REFUNDED"]},"amount":{"type":"number","description":"Monto dispersado al beneficiario."},"feeAmount":{"type":"number","description":"Fee on-top que pagas tú."},"recipientName":{"type":"string"},"network":{"type":"string","nullable":true},"providerPayoutId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time","nullable":true}}}}},"GetPayoutResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/CreatePayoutResponse/properties/data"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","description":"Código de error"},"message":{"type":"string","description":"Mensaje descriptivo"},"details":{"type":"object","description":"Detalles adicionales"}}}}},"WebhookPayload":{"type":"object","description":"Payload enviado a tu webhook URL","properties":{"event":{"type":"string","enum":["payment.completed","payment.failed"],"description":"Tipo de evento"},"data":{"type":"object","properties":{"id":{"type":"string"},"reference":{"type":"string"},"amount":{"type":"number","description":"Lo que pagó el pagador (baseAmount + feeAmount)."},"baseAmount":{"type":"number","nullable":true,"description":"Valor NETO acreditado a tu comercio (el monto que pediste al crear la orden). null en órdenes legacy."},"feeAmount":{"type":"number","nullable":true,"description":"Fee on-top retenido por NIIO. null en órdenes legacy."},"currency":{"type":"string"},"status":{"type":"string"},"paidAt":{"type":"string","format":"date-time","nullable":true},"metadata":{"type":"object"}}},"timestamp":{"type":"string","format":"date-time"}}}}}}