Integración de Lunium

Sandbox: PIX, custodia y cripto

Probar ahoraDescargar kit

Usa la misma base https://api.luniumpay.com con una clave lun_test_. Toda operación financiera es ficticia. El QR de entrada contiene SANDBOX:NAO_PAGAVEL:: no es un PIX bancario. Confirma el pago mediante la API de simulación. No se envía ningún retiro al exchange asociado ni a la blockchain.

Probar ahora

Abre la integración guiada, elige el flujo, indica tu correo electrónico y ejecuta la demostración. Mediante la conexión pública de IA, usa lunium_start_sandbox_demo con flow igual a custody, cashin, payout o cashout, además de un request_id aleatorio y estable y del email de quien hará las pruebas (opcional en las herramientas MCP, pero muy recomendable: con él, LuniumPay envía a la persona la guía de integración —qué es LuniumPay, manual, diagrama de flujo y próximos pasos— una sola vez; sin él, crea la clave igualmente y recoge el correo después mediante lunium_contact). Continúa con lunium_get_sandbox_demo; puede crear el retiro ficticio ya previsto en el recorrido después de confirmar el crédito.

Para probar tu backend, descarga el kit:

node sandbox.mjs all
# o Python 3.9+, sin dependencias:
python3 sandbox.py all

El kit crea una clave en memoria con el correo de quien hará las pruebas (define LUNIUM_SANDBOX_EMAIL=voce@empresa.com; sin él, el kit se detiene con un mensaje claro), confirma GET /keys/me antes de operar y rechaza las credenciales de producción. También acepta LUNIUM_API_KEY que contenga exclusivamente una clave de prueba. No imprime credenciales. Selecciona custody, cashin, payout o cashout en lugar de all para un recorrido específico.

Recorridos y finalización

Recorrido Crear Confirmar y seguir Éxito
PIX → custodia BRL POST /cashin/charge, destino: "saldo" POST /sandbox/cashin/{cashin_id}/pay, después /cashin/{cashin_id}/status y /saldo status=paid, settlement_status=sent; disponible en la subcuenta correcta
PIX → BTC, USDC u otra ruta del catálogo de prueba POST /cashin/charge, destino: "cripto", asset, chain, payout_address La misma confirmación de PIX y consulta de cash-in paid y sent; el hash comienza por sandbox:, sin transacción real
Custodia → criptomonedas POST /saldo/sacar-cripto, amount_cents, tax_number, asset, chain, payout_address /cashin/{cashin_id}/status paid y sent; el débito incluye fee_cents
Custodia → PIX POST /payouts, amount_cents, pix_key GET /payouts/{payout_id} status=sent; E2E ficticio con ISPB 00000000
Transferencia interna POST /saldo/transferir, from_customer_ref, to_customer_ref, amount_cents /saldo/extrato, /saldo/clientes, /saldo/consolidado Débito y crédito atómicos; total en custodia conservado
DePix/Liquid → PIXPOST /cash-outs, asset: "DEPIX", network: "liquid", destinatario Pix y, si quieres, refund_addressPOST /cash-outs/{cashout_id}/accept, después GET /cash-outs/{cashout_id}state=COMPLETED; depósito y PIX simulados
Criptomonedas externas → PIX POST /cash-outs, después POST /cash-outs/{cashout_id}/accept GET /cash-outs/{cashout_id} state=COMPLETED; depósito también simulado

La custodia no requiere una billetera fija. El saldo es BRL. Elige la moneda, la red, la dirección y el memo solo al retirar. El kit recorre BTC nativo, USDC en Polygon y retiro de USDC en Base; el catálogo de pruebas ofrece otras rutas identificadas. En cash-in y retiro usa chain; en cash-out usa network.

Probar PIX → DePix/Liquid

Usa una clave lun_test_ y confirma key.sandbox=true en GET /keys/me. La ruta DEPIX/liquid aparece en instant en GET /cashin/catalog?asset=depix&network=liquid. La prueba cubre PIX → DePix; el retiro de la custodia hacia Liquid sigue sin estar disponible.

Envía asset: "depix", chain: "liquid", delivery_mode: "split" y una dirección Liquid en payout_address. Sustituye SEU_ENDERECO_LIQUID a continuación por la dirección de tu billetera. El CPF del ejemplo es sintético, exclusivo de sandbox. La dirección no recibe monedas: este flujo no usa Liquid mainnet ni testnet.

Consulta POST /cashin/preview con los mismos parámetros antes de crear la solicitud de cobro. La tarifa básica de compra de DePix es del 2% + R$ 1,00, con un mínimo de R$ 2,00 por PIX, salvo condiciones propias de la clave. La parte fija se descuenta antes del porcentaje: R$ 500,00 dan como resultado 489,02 DePix con la política estándar. Comprueba net_cents y fee_total_cents devueltos; la tarifa de compra de USDC/USDT y la comisión del socio no se suman a DePix.

curl --fail-with-body https://api.luniumpay.com/cashin/charge \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"amount_cents":50000,"payer_tax_number":"12345678901","destino":"cripto","asset":"depix","chain":"liquid","delivery_mode":"split","payout_address":"SEU_ENDERECO_LIQUID","external_id":"sandbox-depix-001"}'

# Usa el cashin_id devuelto al crear la operación:
curl --fail-with-body -X POST "https://api.luniumpay.com/sandbox/cashin/$CASHIN_ID/pay" \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' -d '{}'

curl --fail-with-body "https://api.luniumpay.com/cashin/$CASHIN_ID/status" \
  -H "X-API-Key: $LUNIUM_API_KEY"

Confirma el pago mediante la ruta /sandbox/cashin/{cashin_id}/pay y consulta el estado hasta paid y sent. La API y los webhooks cashin.paid/cashin.settled conservan delivery_mode, net_cents y fee_total_cents. El hash comienza por sandbox: y settlement_tx_url es null. No pagues el QR en un banco: no se realiza ningún PIX ni envío en blockchain.

Probar DePix/Liquid → PIX

Usa asset: "DEPIX", network: "liquid" y una clave lun_test_. Consulta GET /catalog?asset=DEPIX&network=liquid: la ruta aparece en fast. Indica amount en DePix o brl_amount para cotizar a partir del PIX deseado, sin combinar ambos. La paridad es 1 DePix = R$ 1,00 antes de las tarifas; comprueba el importe efectivo devuelto, también en la cotización inversa.

La venta usa su propia tarifa vigente en la clave, indicada en fee_bps, fee_fixed_cents, fee_total_cents y net_cents. Con la política estándar de venta del 1,5% + R$ 1,00, enviar 100,00 DePix da como resultado un PIX de R$ 97,51. La tarifa de compra de DePix es independiente.

Al crear la orden, indica la clave Pix. refund_address, una billetera Liquid de devolución confirmada por el cliente, es opcional desde la API 1.44.0: sin ella, una venta que deba devolverse se detiene en AWAITING_REFUND_ADDRESS hasta que indiques la billetera en POST /cash-outs/{cashout_id}/refund-address. Para una clave Pix de correo electrónico, teléfono o aleatoria, payee_tax_number es obligatorio; para CPF/CNPJ, el documento procede de la propia clave. El ejemplo usa un destinatario y un CPF sintéticos. Sustituye SUA_CARTEIRA_LIQUID_DE_DEVOLUCAO por una dirección Liquid válida (o elimina el campo); el sandbox no le envía ningún activo.

# Vista previa: no crea una orden ni exige destinatario o billetera de devolución.
curl --fail-with-body https://api.luniumpay.com/cash-outs/preview \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"asset":"DEPIX","network":"liquid","amount":"100.00"}'

# Crear la cotización simulada:
curl --fail-with-body https://api.luniumpay.com/cash-outs \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"asset":"DEPIX","network":"liquid","amount":"100.00","pix_key":"depix@example.invalid","pix_key_type":"email","payee_tax_number":"12345678901","refund_address":"SUA_CARTEIRA_LIQUID_DE_DEVOLUCAO","external_id":"sandbox-depix-pix-001","sandbox_scenario":"success"}'

# Usa el cashout_id devuelto al crear la operación:
curl --fail-with-body -X POST "https://api.luniumpay.com/cash-outs/$CASHOUT_ID/accept" \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' -d '{}'

curl --fail-with-body "https://api.luniumpay.com/cash-outs/$CASHOUT_ID" \
  -H "X-API-Key: $LUNIUM_API_KEY"

La aceptación inicia automáticamente el depósito simulado. deposit_address comienza por SANDBOX:LIQUID:NAO_ENVIAR: y no es una dirección que admita pagos. No envíes monedas ni busques una red testnet: la simulación ocurre en la API. Consulta la orden hasta COMPLETED, normalmente unos 14 segundos después de aceptar. Recorre AWAITING_DEPOSIT → DEPOSIT_DETECTED → PROCESSING → COMPLETED. El pix_e2e final usa el ISPB ficticio 00000000; la verificación también identifica el sandbox. No hay pago bancario, comprobante bancario real ni transacción Liquid.

Los eventos son cashout.awaiting_deposit, cashout.deposit_detected, cashout.processing y cashout.completed. En una devolución, también hay cashout.refunding y cashout.refunded; el hash de devolución comienza por sandbox:. Configura el callback antes de crear la operación o inspecciona GET /sandbox/events.

Para DePix → PIX, elige sandbox_scenario: success, delayed (unos 54 segundos), failed, expired (deja la cotización sin aceptar durante más de 5 segundos), refunded, settlement_uncertain, provider_unavailable (503 sin crear una orden), route_unavailable o no_deposit (sin depósito hasta caducar). El escenario explícito prevalece sobre los activadores por centavos descritos a continuación; sin escenario explícito, esos activadores siguen activos.

Para probar la devolución sin billetera, crea la cotización sin refund_address y con el escenario refunded. Después de aceptar, la orden pasa por REFUNDING y se detiene en AWAITING_REFUND_ADDRESS (webhook cashout.awaiting_refund_address), con refund_amount, refund_asset y refund_network completados. Indica una billetera Liquid en POST /cash-outs/{cashout_id}/refund-address: la orden continúa hacia REFUNDING y, unos 4 segundos después, REFUNDED, con un hash de devolución que comienza por sandbox:. Repetir la misma billetera responde 200; otra billetera, 409 refund_address_imutavel.

En settlement_uncertain, la orden permanece en PROCESSING. Resuelve con POST /sandbox/operations/{cashout_id}/resolve y {"outcome":"sent"} para completar, o {"outcome":"failed"} para simular la devolución (REFUNDING → REFUNDED tras unos 4 segundos; sin refund_address, la orden se detiene en AWAITING_REFUND_ADDRESS, como se indicó antes). Repetir la misma resolución o aceptación no duplica la operación. Repetir external_id con un destinatario, documento, billetera, importe o escenario distintos devuelve 409. Recupera la intención mediante GET /cash-outs?external_id=....

Este flujo de DePix usa clave PIX; br_code es una función de las rutas USDT/USDC. sandbox_scenario y /sandbox/operations/.../resolve se rechazan con una clave de producción. Consulta también GET /sandbox, dentro de scenarios_by_flow.cashout_depix.

Recibir en custodia sin billetera

Crea la clave con POST /keys/sandbox, enviando el email de quien hará las pruebas (obligatorio: es a quien enviamos el manual, el diagrama de flujo y los pasos de integración), y guarda api_key en LUNIUM_API_KEY solo en el backend. Confirma key.sandbox=true en GET /keys/me antes de las llamadas siguientes. El documento de este ejemplo es sintético y sirve únicamente para sandbox.

curl --fail-with-body https://api.luniumpay.com/cashin/charge \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"amount_cents":100000,"payer_tax_number":"12345678901","destino":"saldo","customer_ref":"cliente-teste","external_id":"sandbox-deposito-001"}'

Guarda cashin_id. Para simular el pago:

curl --fail-with-body -X POST "https://api.luniumpay.com/sandbox/cashin/$CASHIN_ID/pay" \
  -H "X-API-Key: $LUNIUM_API_KEY" -H 'Content-Type: application/json' -d '{}'

Consulta /cashin/{cashin_id}/status hasta paid y sent, generalmente unos 6 segundos. Después consulta /saldo?customer_ref=cliente-teste. El crédito es neto de las tarifas de la clave; no compares el saldo con el importe bruto de la solicitud de cobro. Repetir el pago no duplica el crédito.

Escenarios deterministas de cash-in, custodia y payout

Envía sandbox_scenario al crear la operación. Consulta GET /sandbox para ver la matriz de escenarios por flujo.

Escenario Resultado
success Éxito; predeterminado cuando se omite
delayed Retención/demora de aproximadamente 30 segundos antes de continuar
held Solo depósito en custodia: crédito bloqueado durante 30 segundos y después disponible
expired El cash-in caduca al intentar simular el pago
payer_mismatch Cash-in devuelto por discrepancia del pagador, sin crédito/entrega
refunded Cash-in devuelto sin crédito; payout devuelto con una única reversión
failed Fallo de pago; el payout devuelve el débito una vez
settlement_failed El pago puede estar confirmado, pero falla la entrega; el retiro revierte el débito y las tarifas
settlement_uncertain La entrega permanece incerto; el payout sigue processing. No se revierte antes de la conciliación
route_unavailable Creación rechazada, sin débito
provider_unavailable HTTP 503 simulado, sin operación creada; mientras continúe el escenario, continúa el rechazo

Para resolver una incertidumbre solo en pruebas, llama a POST /sandbox/operations/{operation_id}/resolve con {"outcome":"sent"} o {"outcome":"failed"}. Repetir la misma resolución es idempotente. La ruta exige una operación incierta de la propia clave. No existe confirmación ficticia en producción.

Prueba también payloads no válidos, mínimos por moneda/red, saldo insuficiente, gasto simultáneo, cuenta bloqueada, ID de otra clave y external_id reutilizado con parámetros distintos. Usa una intención y un external_id estables para los reintentos; se rechazan los parámetros divergentes. La solicitud de cobro y el retiro en cripto comparten el espacio de referencias. Tras un timeout, recupera mediante el ID o las listas filtradas por external_id.

Escenarios de cripto → PIX

El cash-out mantiene los activadores en los dos decimales de amount (o brl_amount en la cotización inversa): .00 éxito, .01 retraso, .02 fallo, .03 caducidad, .04 límite, .05 lento, .06 rechazo del proveedor, .07 el primer intento de aceptación devuelve 503 y el segundo funciona, .08 límite del pagador. En la vista previa no se crea ningún registro. Nunca envíes cripto a la dirección devuelta por el simulador.

Billetera USDT/USDC

La clave de prueba usa el simulador de la billetera: las mismas rutas /carteira-usdt, las mismas estructuras y estados de producción, sin nada real. El depósito devuelve una dirección ficticia (SANDBOX-NAO-ENVIE-FUNDOS; nunca envíes fondos) y se acredita automáticamente en unos 15 segundos. El PIX pagado con el saldo de prueba se completa en unos 15 segundos, con E2E de prueba y receipt_url: null. Activadores por centavos: el depósito .02 no llega y caduca en aproximadamente 1 minuto; el PIX .01 pasa unos 40 segundos en revisao, .02 falla antes del envío y devuelve la reserva, .05 tarda unos 2 minutos. Los webhooks wallet.deposit_credited, wallet.payment_completed y wallet.payment_failed llegan con sandbox: true.

Webhooks reales sobre eventos ficticios

Configura una URL HTTPS pública que controles en PATCH /keys/me con webhook_url y guarda webhook_secret de forma segura. Los eventos del sandbox usan la misma cola de entrega y firma del producto; incluyen sandbox:true. Valida el HMAC sobre el cuerpo sin procesar, el timestamp, event_id y la tolerancia a duplicados según el manual. No confundas un evento ficticio entregado por HTTP real con una liquidación financiera real.

Usa GET /sandbox/events para inspeccionar los eventos generados, incluso sin callback configurado. GET /webhooks/deliveries muestra intentos y POST /webhooks/deliveries/{event_id}/retry reenvía. Los eventos anteriores a la configuración del callback no se envían retroactivamente: crea una operación nueva o usa /webhooks/test. Cash-in publica cashin.paid, cashin.settled o el fallo correspondiente. La retención/liberación y las transferencias tienen sus propios eventos. Payout publica su resultado final; cash-out publica su progreso y finalización.

Persistencia, precios y límites de las pruebas

Cash-in, custodia, payout y transferencias persisten aislados del libro financiero real, incluso después de reiniciar. Cash-out también se guarda, con una retención de dos horas. Hay un límite de 1.000 operaciones por clave para los nuevos recorridos y 1.000 cash-outs. POST /sandbox/reset con {"confirm":true} elimina únicamente el estado ficticio de tu clave; las entregas de webhook ya encoladas conservan su historial.

Las cotizaciones y los catálogos son instantáneas sintéticas identificadas en la respuesta. Los precios, mínimos, disponibilidad y análisis de riesgo de producción pueden cambiar. El sandbox no llama al exchange asociado, a los bancos ni a las billeteras. El coste del proveedor del payout de prueba se fija en 100 centavos y se indica en /saldo; no representa la tarifa real. La escala por CPF no consulta el historial de personas; /cashin/limits indica esta diferencia. Las pruebas de retención tienen tiempos reducidos.

El simulador cubre activos identificados de su catálogo; no simula tokens DEX arbitrarios por contrato, lectura bancaria de QR dinámicos, la red blockchain ni políticas privadas de cada proveedor. En producción, vuelve a leer /keys/me, /saldo, los límites y los catálogos con la clave real. Un piloto con PIX realmente pagado y cripto enviada por el exchange asociado es una operación real, con importe y destinatario autorizados. Completar el sandbox valida la integración del software, no certifica la liquidez ni la ejecución de los proveedores.