Integrar PIX no checkout da sua loja é mais simples do que parece: um POST pra criar a cobrança e um webhook pra receber o status. Este guia mostra o caminho do zero — funciona em qualquer linguagem (Node, PHP, Python, Ruby, Go, .NET, Elixir) porque o contrato é só HTTP + JSON.

Passo 1 — Pegar sua chave de API

Depois de criar a conta e ter o cadastro aprovado, abra Projetos no painel e copie a API key do projeto Default. Você a usa como usuário em HTTP Basic; a senha fica em branco. Cada projeto tem a sua chave — separe ambientes (produção / staging) criando projetos diferentes.

Passo 2 — Criar uma cobrança

Faça um POST para o endpoint de criação. O valor é em centavos (R$ 19,90 = 1990) e o external_id deve ser único na sua loja — usamos pra idempotência (chamar a mesma criação duas vezes não duplica a cobrança).

curl -X POST 'https://vanillapag.com/v1/payment-transaction/create' \
  -H 'Authorization: Basic '$(echo -n 'sua-api-key:x' | base64) \
  -H 'Content-Type: application/json' \
  -d '{
    "amount": 1990,
    "external_id": "pedido-12345",
    "customer": {
      "name": "Cliente Exemplo",
      "email": "[email protected]",
      "document": "12345678901"
    }
  }'

A resposta traz o qr_code (payload copia-e-cola), a qr_code_image (URL pública do PNG do QR) e o id interno da transação. Tudo em menos de 300 ms.

Passo 3 — Renderizar o QR no checkout

No seu checkout, mostre o QR e o copia-e-cola lado a lado:

  • QR Code visual: use a qr_code_image direto numa <img>, ou gere um SVG localmente a partir do qr_code com qualquer lib de QR (qrcode.js no browser, qrcode em Node, endroid/qr-code em PHP).
  • Botão "Copiar código": copia o qr_code (a string PIX) — clientes em mobile preferem colar no app do banco em vez de escanear.
  • Polling opcional: chame GET /v1/payment-transaction/info/{id} a cada 3–5 s pra atualizar a tela se quiser feedback imediato. O webhook ainda é a fonte autoritativa.

Passo 4 — Receber o webhook (status final)

Exponha um endpoint público no seu servidor que aceite POST JSON. Configure a URL em Projetos → Webhook URL. Quando o cliente pagar (em segundos, normalmente), enviamos:

{
  "id": "tx_2sQfgT...",
  "status": "PAID",
  "amount": 1990,
  "payment_method": "pix",
  "customer": { "name": "...", "email": "...", "document": "..." },
  "paid_at": "2026-05-15T17:24:11Z"
}

Verifique o header X-Signature com HMAC-SHA256 usando o webhook_secret da sua credencial antes de processar — assim você sabe que o evento veio da gente, não de um atacante. Veja o tutorial de verificação HMAC com código pronto em Node, PHP e Python.

Responda 2xx em até 10 segundos. Em caso de falha (não-2xx ou timeout), tentamos de novo automaticamente com backoff: 30 s, 2 min, 8 min, 30 min, 2 h.

Idempotência: o detalhe que evita venda duplicada

Webhook pode chegar duas vezes (retry após timeout, replay de teste, etc.). Use o id da transação como chave única no seu banco antes de liberar o pedido:

// Pseudo-código
if (await db.findOrder({ vanillaTxId: event.id })) {
  return res.status(200).send("já processado");
}
await db.markOrderPaid(event.external_id);
await db.saveVanillaTx(event.id);

Próximos passos