Cash-out · stablecoin → PIX

API USDT para PIX

Você envia cripto para um endereço que nasce por ordem. Uma chave PIX recebe reais, com comprovante que a contraparte confere sozinha. Cotação, aceite e depósito — três chamadas.

Criar chave sandbox Falar com integração Documentação completa

Para quem é

O problema

Vender cripto e fazer o PIX cair na conta certa costuma ser um processo manual: alguém envia para uma corretora, espera a venda, saca para um banco e transfere. Cada passo tem um horário, um limite e um humano. Quando falha, o dinheiro fica num lugar que ninguém consegue apontar.

Aqui a ordem tem estado. Você sabe onde ela está, o valor é travado na cotação que você aceitou, e uma falha tem destino definido: a cripto volta para o endereço de devolução que você informou.

O fluxo, ponta a ponta

  1. Cote com POST /cash-outs/preview nos dois sentidos: por valor em reais ou por quantidade de cripto. Nada é criado.
  2. Crie a ordem com POST /cash-outs informando a chave PIX que recebe — ou o copia e cola de uma cobrança.
  3. Aceite com POST /cash-outs/{id}/accept. A resposta traz o endereço de depósito, o valor exato e o expires_at.
  4. Envie exatamente a quantidade cotada, na rede cotada. Em redes de endereço compartilhado, inclua o deposit_tag.
  5. O PIX sai sozinho. cashout.completed traz o pix_e2e e a URL do comprovante.

Endpoints usados

EndpointPara quê
POST /cash-outs/previewCotação nos dois sentidos, sem criar ordem nem consumir limite. Serve para tela que cota a cada tecla.
POST /cash-outsCria a cotação com a chave PIX de destino, ou com br_code para pagar uma cobrança.
POST /cash-outs/{id}/acceptTrava a cotação e devolve o endereço de depósito e o memo quando a rede exige.
GET /cash-outs/{id}Estado, linha do tempo carimbada pelo servidor e comprovante.
GET /pix/keys/lookup?key=Titular da chave antes do aceite: mostre "você vai pagar Fulano · Banco" e evite recusa.
GET /catalogAtivos, redes e mínimos por rota. Fonte da verdade, muda sozinho.

Exemplo que roda

# 1. cotação (não cria ordem)
curl -X POST https://api.luniumpay.com/cash-outs/preview \
  -H "X-API-Key: $LUNIUM_KEY" -H "Content-Type: application/json" \
  -d '{"asset":"USDT","network":"polygon","brl_amount":"500.00"}'

# 2. cria a ordem e aceita
ID=$(curl -sX POST https://api.luniumpay.com/cash-outs \
  -H "X-API-Key: $LUNIUM_KEY" -H "Content-Type: application/json" \
  -d '{"asset":"USDT","network":"polygon","brl_amount":"500.00",
       "pix_key":"loja@exemplo.com","pix_key_type":"email",
       "external_id":"saque-4412"}' | jq -r .cashout_id)

curl -X POST https://api.luniumpay.com/cash-outs/$ID/accept -H "X-API-Key: $LUNIUM_KEY"
const cabecalho = { "X-API-Key": process.env.LUNIUM_KEY, "Content-Type": "application/json" };

const previa = await (await fetch(`${API}/cash-outs/preview`, {
  method: "POST", headers: cabecalho,
  body: JSON.stringify({ asset: "USDT", network: "polygon", brl_amount: "500.00" }),
})).json();

const ordem = await (await fetch(`${API}/cash-outs`, {
  method: "POST", headers: cabecalho,
  body: JSON.stringify({
    asset: "USDT", network: "polygon", brl_amount: "500.00",
    pix_key: "loja@exemplo.com", pix_key_type: "email", external_id: "saque-4412",
  }),
})).json();

const aceita = await (await fetch(`${API}/cash-outs/${ordem.cashout_id}/accept`, {
  method: "POST", headers: cabecalho,
})).json();

console.log(aceita.deposit_address, aceita.deposit_tag, aceita.expires_at);
import os, requests

API = "https://api.luniumpay.com"
h = {"X-API-Key": os.environ["LUNIUM_KEY"]}

previa = requests.post(f"{API}/cash-outs/preview", headers=h, timeout=30, json={
    "asset": "USDT", "network": "polygon", "brl_amount": "500.00"}).json()

ordem = requests.post(f"{API}/cash-outs", headers=h, timeout=30, json={
    "asset": "USDT", "network": "polygon", "brl_amount": "500.00",
    "pix_key": "loja@exemplo.com", "pix_key_type": "email",
    "external_id": "saque-4412"}).json()

aceita = requests.post(f"{API}/cash-outs/{ordem['cashout_id']}/accept",
                       headers=h, timeout=60).json()
print(aceita["deposit_address"], aceita.get("deposit_tag"), aceita["expires_at"])

Sandbox: teste antes de gastar

Uma chamada, sem cadastro, sem cartão. A chave lun_test_ exercita a superfície inteira sem mover dinheiro nenhum.

curl -X POST https://api.luniumpay.com/keys/sandbox \
  -H "Content-Type: application/json" \
  -d '{"name":"meu-teste"}'

O que o sandbox não prova: liquidação real. Nenhuma cripto se move e nenhum PIX é pago — ele serve para acertar o contrato, não para medir o trilho.

Ativos e redes

Instantâneo (trilho próprio): USDT na Polygon e USDC na Polygon — liquidação em segundos, sem corretora no caminho.

Via corretora: 1.478 ativos em 241 redes na venda (1.668 pares ativo×rede) e 1.795 rotas na compra. O prazo é o número de confirmações que a rede exige, não uma escolha nossa.

Redes de endereço compartilhado (ALGO, ATOM, EOS, HBAR, KAVA, LUNA, TON, XLM, XRP): o depósito precisa levar o memo. Na venda ele vem em deposit_tag no aceite; na compra você manda payout_tag junto do endereço.

O catálogo muda sozinho conforme redes entram e saem. Leia de GET /catalog e GET /cashin/catalog em vez de manter lista no código.

Limites e retenções

O quêValor
Compra (cash-in) e saque PIX, por operaçãoR$ 1,00 a R$ 6.000,00
Venda (cash-out), por operaçãoa partir de R$ 6,00
Validade do QR15 minutos
Escada por pagador (CPF/CNPJ de quem paga)R$ 60,00 na estreia → R$ 200,00 nas primeiras 24 h → R$ 6.000,00/dia
Acima da escadao QR ainda é aceito e o provedor retém 24 h (D+1), até R$ 6.000,00/dia por pagador

A escada é por documento de quem paga, não por conta que recebe: dez pagadores são dez limites independentes. É isso que faz o produto servir a e-commerce e marketplace. Consulte o disponível de um pagador antes de cobrar em GET /cashin/limits?payer_tax=, e leia os limites da sua chave em GET /keys/me — tetos acima do tier são contratados.

Medições, não promessas

Medido em produção, janela de 90 dias, em 07/09/2026:

TrechoMedianap90Amostra
PIX recebido → stablecoin entregue (Polygon)6 s70 s112 operações
Aceite da cotação → PIX pago (Polygon)81 s580 s27 operações

Fora da Polygon o relógio é o da rede: o prazo é o número de confirmações que a corretora exige, e está em eta no catálogo. Não prometemos “instantâneo” fora do trilho próprio.

Idempotência

Mande external_id em toda operação que move dinheiro. Repetir a mesma chamada devolve a mesma operação, nunca uma segunda; os mesmos parâmetros com id diferente criam duas, e o mesmo id com parâmetros diferentes responde 409 external_id_divergente em vez de adivinhar.

Timeout não é recusa. Se a chamada não respondeu, consulte pelo external_id antes de repetir — a operação pode existir.

Webhooks e reconciliação

Cada transição dispara um evento assinado em HMAC SHA-256 com timestamp (header X-Lunium-Signature, formato t=…,v1=…) — o timestamp é o que impede replay de uma entrega capturada. Confira a assinatura antes de confiar no corpo.

Webhook é o sinal principal; polling é opcional. Quando precisar pesquisar, o status traz a timeline carimbada pelo servidor — desenhe a etapa a partir dela, porque o cronômetro do seu polling mede a sua rede, não a operação.

Não respondeu 2xx? A entrega é retentada com backoff. Você reenvia à mão em POST /webhooks/deliveries/{event_id}/retry e testa a sua URL em POST /webhooks/test.

Quando dá errado

Depósito com valor diferente do cotado: a ordem não casa e vai para revisão em vez de pagar um valor que ninguém reconhece. Envie o amount exato da resposta.

Rede errada ou depois do expires_at: o depósito chega órfão e vira revisão manual. Sempre deposite antes do vencimento, na rede cotada.

O banco recusa a chave: a cripto volta para o refund_address que você informou, com o estado REFUNDED e o hash da devolução — não fica saldo pendurado com a gente.

Rede com memo sem o memo: o valor cai na corretora sem dono. Por isso o aceite devolve deposit_tag nessas redes e a documentação insiste: se veio preenchido, ele é obrigatório.

Segurança

A verificação aberta é a que mais importa numa negociação: a sua contraparte confere o PIX sozinha, sem chave e sem depender da nossa palavra.

Tempo até a primeira integração

Três chamadas e um depósito. Quem só quer ver o preço para na primeira, que não cria nada e não consome limite nenhum.

O trilho próprio (Polygon) é o previsível: mediana de 81 s e p90 de 580 s do aceite ao PIX pago. Nas outras redes o relógio é o das confirmações — está em eta no catálogo.

Perguntas que os integradores fazem

O valor pode mudar entre a cotação e o depósito?

Não. O aceite trava a cotação e o expires_at diz até quando ela vale. Depositar depois disso é o que quebra o casamento — não uma variação de preço.

Consigo pagar um QR code em vez de uma chave?

Sim. Mande br_code (o copia e cola inteiro) no lugar de pix_key, com USDT ou USDC em qualquer rede do catálogo. O brl_amount da ordem passa a ser exatamente o valor do QR, e você vê o lojista antes de confirmar mandando o mesmo br_code na prévia.

Como a outra ponta confere que o PIX foi pago?

Pelo EndToEndId, no verificador aberto: GET /v1/verificar/{e2e} responde sem chave nenhuma. A contraparte não precisa confiar na sua palavra nem na nossa.

Posso pagar para terceiros?

Sim, a chave não precisa ser sua. O limite diário de recebimento é por CPF/CNPJ de quem recebe e está em GET /keys/me.

Quais redes liquidam mais rápido?

Polygon, no trilho próprio, em segundos. Fora dela o prazo é o das confirmações que a corretora exige, listado por rota em GET /catalog.

Criar chave sandbox Falar com integração

Contrato OpenAPI 1.25.0 · fatos desta página em product-truth.json · status