E-commerce · muitos pagadores

PIX no checkout, stablecoin na tesouraria

Cada comprador paga um PIX comum, no banco dele. A loja recebe stablecoin numa carteira corporativa. Como o limite é do CPF de quem paga, dez compradores são dez limites independentes.

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

Para quem é

O problema

O medo de todo e-commerce que liquida em cripto é o teto: "e se o volume do dia estourar o limite da conta?". Essa pergunta vem de um modelo errado do produto. O limite que manda aqui é o do documento de quem paga, e é por ticket — a conta que recebe não tem um teto diário próprio que some tudo.

O segundo problema é conciliação. PIX numa chave fixa cai sem dono: você vê o valor e não sabe de qual pedido é. Aqui cada cobrança nasce amarrada ao CPF do comprador e ao seu external_id, e um PIX pago por outro documento é devolvido em vez de virar um crédito órfão.

O fluxo, ponta a ponta

  1. No checkout, você chama POST /cashin/charge com o total, o CPF do comprador e o número do pedido em external_id.
  2. Mostre o qr_copypaste na tela. Ele vale 15 minutos — gere no momento de pagar, como Mercado Pago e bancos fazem.
  3. O comprador paga. Chega cashin.paid: é o gatilho para liberar o pedido.
  4. A stablecoin cai na carteira da empresa e chega cashin.settled com o hash.
  5. Conciliação: GET /cashin/charges?external_id= devolve a cobrança daquele pedido, sempre.

Endpoints usados

EndpointPara quê
POST /cashin/chargeUma cobrança por pedido, com o CPF do comprador e o seu número de pedido.
GET /cashin/limits?payer_tax=Quanto aquele comprador pode pagar agora — útil em ticket alto.
GET /cashin/chargesLista com filtro por external_id, status e período: é a conciliação.
POST /webhooks/testTesta a sua URL de webhook antes de a primeira venda depender dela.
GET /cashin/eventsFeed de operação da sua chave para uma tela interna, sem guardar estado.

Exemplo que roda

# um pedido = uma cobrança, identificada pelo CPF de quem compra
curl -X POST https://api.luniumpay.com/cashin/charge -H "X-API-Key: $LUNIUM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount_cents":34990,"asset":"usdt","chain":"polygon",
       "payout_address":"0xCarteiraDaEmpresa",
       "payer_tax_number":"12345678909",
       "payer_name":"Maria S.",
       "external_id":"pedido-2026-33871"}'
// checkout: gera o QR no momento em que o comprador vai pagar
app.post("/checkout/:pedido/pix", async (req, res) => {
  const { total_cents, cpf, nome } = req.body;
  const r = await fetch(`${API}/cashin/charge`, {
    method: "POST",
    headers: { "X-API-Key": process.env.LUNIUM_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({
      amount_cents: total_cents, asset: "usdt", chain: "polygon",
      payout_address: process.env.CARTEIRA_EMPRESA,
      payer_tax_number: cpf, payer_name: nome,
      external_id: `pedido-${req.params.pedido}`,
    }),
  });
  const c = await r.json();
  if (!r.ok) return res.status(r.status).json({ erro: c.erro, detalhe: c.detail });
  res.json({ copiaECola: c.qr_copypaste, expiraEm: c.expires_at });
});

// webhook: só marca o pedido como pago depois de conferir a assinatura
app.post("/webhooks/lunium", verificarAssinatura, async (req, res) => {
  if (req.body.event === "cashin.paid") await marcarPago(req.body.data.external_id);
  res.sendStatus(200);
});
import os, requests
from flask import Flask, request, jsonify

API, H = "https://api.luniumpay.com", {"X-API-Key": os.environ["LUNIUM_KEY"]}
app = Flask(__name__)

@app.post("/checkout/<pedido>/pix")
def cobrar(pedido):
    dados = request.get_json()
    r = requests.post(f"{API}/cashin/charge", headers=H, timeout=30, json={
        "amount_cents": dados["total_cents"], "asset": "usdt", "chain": "polygon",
        "payout_address": os.environ["CARTEIRA_EMPRESA"],
        "payer_tax_number": dados["cpf"], "payer_name": dados.get("nome"),
        "external_id": f"pedido-{pedido}"})
    c = r.json()
    if not r.ok:
        return jsonify(erro=c.get("erro"), detalhe=c.get("detail")), r.status_code
    return jsonify(copia_e_cola=c["qr_copypaste"], expira_em=c["expires_at"])

Sandbox: teste antes de gastar

Uma chamada, sem aprovação prévia, sem cartão; só o seu e-mail é obrigatório (é para ele que mandamos o manual, o fluxograma e o passo a passo da integraçã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 '{"email":"voce@empresa.com","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

O catálogo de entrada de cripto é GET /catalog; o de entrega após Pix é GET /cashin/catalog. Consulte o ativo e a rede do fluxo escolhido antes de cotar. Disponibilidade e mínimos podem mudar.

Use deposit_tag no depósito quando o aceite informar um memo. Na entrega, envie payout_tag quando exigido pela rota. O manual da API descreve cada campo.

Limites e retenções

Consulte GET /keys/me para os limites e as taxas da conta, GET /cashin/limits?payer_tax=... para o pagador e as prévias para o mínimo da rota. Não use um teto fixo compartilhado entre cash-in, cash-out e payout.

Uma cobrança paga pode aguardar retenção antes da liquidação. Use os estados, a linha do tempo e os eventos assinados para distinguir recebimento, saldo disponível e entrega final. A validade da operação vem em expires_at.

Medições, não promessas

O prazo depende do fluxo, da rota disponível, das confirmações da rede e de eventuais retenções. Acompanhe a operação até o estado final e consulte o status do serviço. O tempo de uma simulação não mede uma liquidação real.

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

Comprador estreante com ticket alto: a escada começa em R$ 100,00. Acima dela o QR ainda é aceito, com retenção de 24 h — o pedido pode esperar as 24 h ou você pede allow_hold: false e a cobrança é recusada já na criação, mostrando quanto cabe.

Pagou outra pessoa: PIX de documento diferente é devolvido automaticamente. É o caso que mais gera prejuízo em quem usa chave fixa, e aqui ele não acontece em silêncio.

QR venceu: a cobrança vira expired. Gere outra com um external_id novo — repetir o mesmo id devolveria o QR velho, já vencido.

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

Um endpoint no checkout e um handler de webhook. Os times que fizeram isso levaram uma tarde, porque não há onboarding: a chave de sandbox sai em uma chamada e o contrato é o mesmo da produção.

Perguntas que os integradores fazem

Existe um teto diário que trava a loja?

O limite que rege é o do CPF/CNPJ de quem paga, por ticket: R$ 100,00 na primeira operação, R$ 200,00 nas primeiras 24 h e R$ 6.000,00/dia depois. Não há teto diário por chave — os limites vigentes estão em GET /keys/me — e dez compradores continuam sendo dez limites separados.

Posso usar uma chave PIX fixa em vez de gerar um QR por pedido?

Não, e é de propósito. Chave fixa recebe de qualquer pessoa sem identificação: você não saberia de qual pedido é o valor, e é exatamente esse cenário que gera devolução e disputa. Uma cobrança por pedido é o que torna a conciliação automática.

O comprador precisa ter cripto ou carteira?

Não. Ele paga um PIX comum no aplicativo do banco dele. A parte cripto é sua.

Como devolvo um pedido cancelado?

A devolução do PIX ao comprador é operada por você, com o dinheiro que já liquidou; a API não estorna um PIX pago por decisão comercial. O que ela devolve sozinha é o PIX que veio do documento errado.

Criar chave sandbox Falar com integração

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

PIX no checkout, dólar no caixa. Comece com uma chave de teste.

A chave de teste sai em uma chamada, sem aprovação prévia e sem custo — e o seu caso vai direto para quem integra.

Receber sandbox e falar com integração Cash-in e payout com as taxas da sua chave · consulte a cotação · sem mensalidade

Outros caminhos

API PIX para USDTReceba em reais e entregue USDT na carteira do cliente.API USDT para PIXVenda stablecoin e pague qualquer chave PIX.API de payout PIXPague fornecedores e usuários em reais, por API.BRL ↔ USDT por APIConversão nos dois sentidos, com cotação e comprovante.On-ramp e off-ramp no BrasilEntrada e saída de cripto no país, numa integração só.PIX e stablecoin para walletsDê aos seus usuários um trilho de entrada e saída.Infraestrutura com a sua marcaO trilho inteiro operando por trás do seu produto.

Fala com quem construiu

A chave de teste sai em uma chamada, sem aprovação prévia — se é isso que você quer, comece pela documentação. Este formulário é para o resto: taxa por volume, um caso que a doc não cobre, ou uma dúvida antes de integrar.

Prefere e-mail direto? contato@luniumpay.com