WantsPay WantsPay API DOCS
API v1 · Produção & Sandbox

A API de liquidação PIX ↔ cripto que a WantsPay integra

Liquidação instantânea entre PIX e stablecoins (USDT/USDC) por API: receba por PIX e entregue cripto, receba cripto e pague PIX, mantenha saldo em reais em custódia e faça payouts — tudo idempotente, com webhooks assinados e sandbox determinístico.

🔑 Já tem (ou vai ter) a API? No portal do parceiro você faz login com Google, Twitter ou X, gera chaves de sandbox e produção, configura webhooks e acompanha suas transações — atende B2B (empresa/CNPJ) e B2C (pessoa/CPF).

BASE https://api.luniumpay.com AUTH X-API-Key FORMAT JSON · OpenAPI 3.1

⚙️ Sobre esta API: a documentação abaixo descreve a API de pagamentos da Lunium Pay — o provedor de liquidação PIX ↔ cripto que a WantsPay integra como cliente (a WantsPay é consumidora, não a emissora desta API). As requisições vão para api.luniumpay.com com autenticação da Lunium; credenciais, limites e catálogo são a fonte de verdade — consulte-os por API, nunca fixe valores no código.

1 Visão geral

Uma única API cobre os dois sentidos do fluxo e a custódia entre eles. Todos os valores em reais trafegam em centavos (amount_cents); quantidades de cripto são strings decimais.

📥 Cash-in

O cliente paga por PIX e você entrega USDT/USDC on-chain — ou mantém o valor como saldo em reais na custódia para decidir a saída depois.

📤 Cash-out

Recebe cripto de uma carteira externa e liquida em PIX, com cotação de validade explícita e endereço de depósito por operação.

🏦 Custódia BRL

Receba PIX e guarde como saldo real, organizado por subconta (cliente). Escolha a saída — PIX ou cripto — quando quiser.

⚡ Payouts

Envie PIX direto a partir do saldo, via API, sem passar por cripto. Ideal para repasses e saques dos seus clientes.

💡
Fonte de verdade é a API. Ativos, redes, limites, taxas e prazos mudam — leia sempre /catalog, /cashin/limits e /keys/me em vez de assumir valores fixos. Cotações são devolvidas antes de cada operação, já com a taxa aplicada.

2 Autenticação

Toda requisição autenticada envia a sua chave no header X-API-Key. Requisições com corpo usam Content-Type: application/json.

bashrequisição autenticada
curl --fail-with-body https://api.luniumpay.com/keys/me \
  -H "X-API-Key: $LUNIUM_API_KEY"
🔒
A chave é secreta e só vive no servidor. Nunca a exponha no bundle do front-end, em repositório ou em .env commitado. Na WantsPay ela fica em variável de ambiente e o navegador nunca fala direto com a API — passa sempre pelos route handlers do servidor.

Verificar a chave e o saldo

GET/keys/melimites, taxas e config
GET/saldosaldo da conta

3 Ambientes & chaves

Existe um ambiente de sandbox (determinístico, sem dinheiro real) e o de produção. Distinga-os pelo prefixo da chave e mantenha-os totalmente separados.

AmbienteComo obter a chavePrefixo
SandboxPOST /keys/sandbox — sem e-mail obrigatóriolun_test_…
ProduçãoPOST /keys — com e-mail de operaçãolun_live_…

Criar chave de sandbox

bashsandbox
curl --fail-with-body https://api.luniumpay.com/keys/sandbox \
  -H 'Content-Type: application/json' \
  -d '{"name":"Minha integração de teste"}'

Criar chave de produção

bashprodução
curl --fail-with-body https://api.luniumpay.com/keys \
  -H 'Content-Type: application/json' \
  -d '{"name":"Integração de produção","email":"operacao@wantspay.pro"}'

A resposta traz api_key, limits e uma monitor_url (painel privado de acompanhamento operacional). Guarde a api_key como LUNIUM_API_KEY no ambiente do servidor.

4 Comece agora

Do zero à primeira cobrança em quatro passos.

Gere a chave de sandbox

Uma chamada a POST /keys/sandbox devolve uma chave lun_test_…. Exporte como LUNIUM_API_KEY.

Confira chave e saldo

GET /keys/me e GET /saldo validam a autenticação e mostram limites e taxas vigentes.

Crie uma cobrança PIX de teste

POST /cashin/charge gera o QR (copia-e-cola + imagem). Em sandbox você simula o pagamento.

Acompanhe até liquidar

GET /cashin/{id}/status — ou receba o webhook. Crédito confirmado quando status=paid e settlement_status=sent.

bashprimeira cobrança (custódia em BRL)
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": 5000,
    "payer_tax_number": "00000000191",
    "destino": "saldo",
    "customer_ref": "cliente-42",
    "external_id": "deposito-cliente42-001"
  }'
✓
Em sandbox, use POST /sandbox/cashin/{id}/pay para simular o pagamento do PIX e ver o ciclo completo sem transferir dinheiro real.

5 Cash-in · PIX → cripto / custódia

Uma única cobrança (POST /cashin/charge) atende dois destinos, controlados pelo campo destino:

💰 destino: "saldo"

O PIX vira saldo em reais na custódia (opcionalmente numa subconta via customer_ref). A saída fica para depois.

🪙 destino: "cripto"

Entrega imediata de USDT/USDC no endereço informado. Requer asset, chain e payout_address.

POST/cashin/chargecria a cobrança PIX
jsonentrega direta em cripto
{
  "amount_cents": 10000,
  "payer_tax_number": "00000000191",
  "destino": "cripto",
  "asset": "usdt",
  "chain": "polygon",
  "payout_address": "0x1111111111111111111111111111111111111111",
  "external_id": "compra-cripto-001",
  "allow_hold": false
}

A resposta traz cashin_id, qr_copypaste, qr_image_url e expires_at. Gerar o QR confirma a criação — não o recebimento.

Acompanhar o status

GET/cashin/{cashin_id}/statusestado da cobrança
CampoValores
statuspending delayed under_review paid expired refunded failed
settlement_statuspending sending entregando sent incerto failed
⚠️
Só considere o crédito concluído quando status = paid E settlement_status = sent. Um paid com liquidação sending/incerto ainda não está entregue — não mostre "entregue" ao cliente nem reenvie a operação.

Antes de cobrar, você pode estimar com POST /cashin/preview e checar o teto do pagador com GET /cashin/limits?payer_tax=CPF. Redes e ativos disponíveis para entrega vêm de GET /cashin/catalog (campo entregavel: true).

6 Cash-out · cripto → PIX

Quando alguém envia cripto de uma carteira externa e você precisa pagar em PIX, o fluxo tem três passos: cotar, aceitar (recebe o endereço de depósito) e acompanhar.

Cotar — POST /cash-outs

Informe asset, network, a chave PIX de destino e um entre amount (cripto) ou brl_amount. Recebe cashout_id, deposit_address e a validade.

Aceitar — POST /cash-outs/{id}/accept

Confirma os termos e devolve o endereço/estado atualizados para o depósito.

Acompanhar — GET /cash-outs/{id}

Ao concluir, a resposta traz pix_e2e, pix_paid_at e receipt_url.

jsonPOST /cash-outs
{
  "asset": "USDT",
  "network": "polygon",
  "amount": "10.00",
  "pix_key": "recebedor@example.com",
  "pix_key_type": "email",
  "external_id": "cashout-001"
}

Ciclo de estados

QUOTE_CREATED→AWAITING_DEPOSIT→DEPOSIT_DETECTED→DEPOSIT_CONFIRMED→SELLING→SOLD→PAYING_OUT→COMPLETED

Estados terminais: COMPLETED, MANUAL_REVIEW, REFUNDING_CRYPTO, REFUNDED, EXPIRED, FAILED. Estimativa sem criar ordem: POST /cash-outs/preview.

7 Custódia & saldo

O saldo em reais fica organizado por subconta (customer_ref) sobre a "casa". Consulte, extraia, transfira entre subcontas e saque como cripto.

GET/saldocasa ou ?customer_ref=
GET/saldo/consolidadocasa + subcontas
GET/saldo/extratolançamentos
POST/saldo/transferirentre subcontas
POST/saldo/sacar-criptosaque em USDT/USDC
GET/saldo/clientessaldos por cliente
🧮
O saldo distingue total_cents, disponivel_cents (sacável, após retenções) e bloqueado_cents/held. Respeite carencia_horas/carencia_ate — mostre ao cliente a data prevista de liberação em vez de tratar como erro.

Sacar saldo como cripto

jsonPOST /saldo/sacar-cripto — amount_cents em BRL
{
  "amount_cents": 10000,
  "asset": "usdt",
  "chain": "polygon",
  "payout_address": "0x1111111111111111111111111111111111111111",
  "tax_number": "00000000191",
  "customer_ref": "cliente-42",
  "external_id": "saque-cripto-cliente42-001"
}

amount_cents é o valor em reais a debitar, não a quantidade de cripto. Para redes que exigem memo, envie payout_tag. Use max_debited_cents para limitar o débito total (com taxas). Acompanhe por GET /cashin/{id}/status.

8 Payouts · PIX via API

Envie PIX direto a partir do saldo em custódia — sem intermediar cripto. Requer payout.enabled na chave e saldo suficiente (valor + taxas).

POST/payoutsenvia o PIX
GET/payouts/{payout_id}acompanha
jsonPOST /payouts
{
  "amount_cents": 5000,
  "pix_key": "recebedor@example.com",
  "pix_key_type": "email",
  "tax_number": "00000000191",
  "customer_ref": "cliente-42",
  "external_id": "saque-pix-cliente42-001"
}

Estados: processing → sent / failed / refunded. Quando disponível, o comprovante traz e2e, paid_at, receiver_name e verify_url. As taxas estimadas saem de GET /saldo (saque_taxa_estimada_cents).

10 Comissão (partner fee)

Você pode embutir uma comissão própria sobre cada operação, definida em basis points (partner_fee_bps; 200 = 2%). Ela é calculada sobre a base após a taxa fixa e creditada num saldo de comissão separado.

jsonPATCH /keys/me
{ "partner_fee_bps": 200 }   // 2%
GET/comissao
GET/comissao/extrato
POST/comissao/sacar

A comissão é apurada após status=paid e settlement_status=sent. Consulte disponivel_cents, min_saque_cents e pode_sacar_agora antes de sacar. Fórmula: floor(base_cents × (10000 − lunium_bps − partner_bps) / 10000).

11 Webhooks

Configure a URL de recepção em PATCH /keys/me. A resposta devolve o webhook_secret uma única vez — guarde com segurança.

jsonPATCH /keys/me
{ "webhook_url": "https://wantspay.pro/api/webhook" }

Assinatura (HMAC-SHA256)

Cada entrega traz o header X-Lunium-Signature: t=1700000000,v1=<hmac_hex>. Valide o HMAC-SHA256 de timestamp.raw_body — capture o corpo bruto antes de fazer o parse do JSON.

javascriptverificação da assinatura
const crypto = require('crypto');

function verify(header, rawBody, secret) {
  const [, sigPart] = header.split(',');        // "v1=..."
  const t = header.split(',')[0].split('=')[1];
  const v1 = sigPart.split('=')[1];
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(v1), Buffer.from(expected)      // comparação em tempo constante
  );
}

Outros headers: X-Lunium-Event-Id (dedupe por ele), X-Lunium-Delivery-Id e X-Lunium-Attempt (até 12 tentativas em ~7h).

Formato do evento

jsonexemplo
{
  "event": "cashin.settled",
  "event_id": "evt_exemplo",
  "created_at": "2026-09-17T20:00:00.000Z",
  "data": {
    "cashin_id": "ci_exemplo",
    "destino": "saldo",
    "status": "paid",
    "settlement_status": "sent"
  }
}
GrupoEventos
cashinpaid · settled · settlement_failed · expired · refunded · failed · delayed · held
cashoutawaiting_deposit · deposit_detected · processing · confirming · under_review · refunding · completed · refunded · expired · failed
payoutsent · failed · refunded
saldoliberado · congelado · transferido
webhooktest
📌
Boas práticas de recepção: valide assinatura + timestamp antes do parse; persista por event_id com restrição de unicidade (dedupe); responda 2xx em até 10s e faça o trabalho pesado de forma assíncrona; releia o estado canônico com um GET no recurso antes de atualizar a UI. Recupere entregas falhas em GET /webhooks/deliveries e reenvie com POST /webhooks/deliveries/{event_id}/retry. Dispare um teste com POST /webhooks/test.

12 Idempotência & erros

Envie external_id em toda operação financeira (cash-in, cash-out, payout, transferência). Em retry, reutilize o mesmo external_id com o corpo idêntico.

🔁
Perdeu a resposta depois do POST? Não recrie às cegas. Consulte pelo external_id no endpoint de listagem (/cashin/charges, /cash-outs, /payouts). Se existir, acompanhe; se não, repita com o mesmo corpo/ID respeitando backoff.

Códigos de erro

HTTPCampoSignificadoAção
401/403—Autenticação / permissão da chaveVerifique a chave, limites e política
402saldo_insuficienteSaldo insuficienteCheque disponível, subconta e taxas
409external_id_divergenteID já usado com parâmetros diferentesNão repita com o mesmo ID
423carencia_primeiro_depositoTrava de carênciaMostre o liberar_em retornado
429—Rate limitRespeite o header Retry-After
5xx—Erro de servidor / timeoutConsulte a operação antes de repetir

O corpo de erro inclui erro, acao, detail, request_id e agent_guidance. Ao pedir suporte, informe ambiente, id da operação, external_id, horário com fuso e request_id — nunca a chave, o segredo do webhook ou o CPF/CNPJ completo.

13 Referência de endpoints

Resumo das rotas mais usadas. Base: https://api.luniumpay.com.

MétodoEndpointDescrição
POST/cashin/chargeCria cobrança PIX (custódia ou cripto)
GET/cashin/{id}/statusEstado da cobrança
POST/cashin/previewEstimativa de cash-in
GET/cashin/catalogAtivos/redes entregáveis
GET/cashin/limitsLimites do pagador
POST/cash-outsCota cripto → PIX (passo 1)
POST/cash-outs/{id}/acceptAceita e recebe endereço (passo 2)
GET/cash-outs/{id}Acompanha (passo 3)
POST/cash-outs/previewCotação sem criar ordem
POST/payoutsEnvia PIX do saldo
GET/payouts/{id}Acompanha o payout
GET/saldoSaldo (casa ou subconta)
GET/saldo/extratoLançamentos
POST/saldo/transferirTransferência interna
POST/saldo/sacar-criptoSaque do saldo em cripto
GET/keys/meConfig, limites e taxas da chave
PATCH/keys/meWebhook, comissão etc.
GET/comissaoSaldo de comissão
POST/comissao/sacarSaca a comissão em cripto
POST/webhooks/testDispara webhook de teste
GET/webhooks/deliveriesLog de entregas
GET/pingHealth check

14 Suporte

🟢 Status

luniumpay.com/status — disponibilidade da infraestrutura.

✉️ WantsPay

suporte@wantspay.pro — integração e dúvidas comerciais.

📘 Especificação

OpenAPI 3.1 em /openapi.json.

🚀
Checklist de produção: chave em variável de ambiente e sandbox separado de produção; webhook validando HMAC + timestamp, deduplicando e respondendo em 10s; IDs persistidos e retries preservando corpo + external_id; UI lendo catálogo/limites atuais e distinguindo PIX pago de cripto entregue; conciliação tratando carência, rota, taxa e erros de saldo sem duplicar operações.