Para desenvolvedores
API da Vira
Ligue a Vira à sua loja ou ao sistema que sua empresa já usa: ele cria a cobrança, mostra o Pix ao cliente e fica sabendo quando o pagamento entra. Sem mensalidade, você só paga a tarifa quando recebe.
1. Criar sua chave
Entre no painel, abra Configurações → Integrações e clique em Nova chave. A chave aparece uma única vez: copie e guarde em local seguro (no servidor da sua loja, nunca no navegador ou em aplicativo). Se perder, revogue e crie outra. Só o dono ou um administrador da conta mexe nas chaves.
Toda chamada leva o cabeçalho Authorization: Bearer vira_sk_…. A empresa é identificada pela chave; você nunca informa o código da empresa.
2. Criar uma cobrança Pix
POST /api/v1/charges. O valor vai em centavos (R$ 129,90 = 12990; mínimo R$ 5,00). A referência é o número do pedido no seu sistema e não pode se repetir. O cabeçalho Idempotency-Key evita cobrança dobrada: se a chamada falhar no meio do caminho, repita com a mesma chave e você recebe a mesma cobrança.
curl -X POST https://virapagamento.com.br/api/v1/charges \
-H "Authorization: Bearer vira_sk_SUA_CHAVE" \
-H "Idempotency-Key: pedido-1042-tentativa-1" \
-H "Content-Type: application/json" \
-d '{
"reference": "pedido-1042",
"description": "Pedido 1042 - Camiseta azul",
"amountCents": 12990,
"method": "PIX",
"dueDate": "2026-12-31",
"customer": {
"name": "Maria da Silva",
"document": "12345678909",
"email": "maria@exemplo.com.br",
"phone": "11999998888"
}
}'Resposta (201): mostre o QR Code ou o “copia e cola” em pix, ou mande o cliente para o paymentUrl, a fatura da Vira com Pix, cartão e boleto.
{
"id": "0b6f4c1e-8d52-4e0c-9a57-2f3c7b8e1a10",
"reference": "pedido-1042",
"status": "PENDING",
"amountCents": 12990,
"dueDate": "2026-12-31",
"paidAt": null,
"pix": {
"payload": "00020126...",
"image": "iVBORw0KGgo...",
"expiresAt": "2026-12-31T23:59:59.000Z"
},
"paymentUrl": "https://virapagamento.com.br/c/AbCdEf123456"
}3. Consultar uma cobrança
GET /api/v1/charges/{id}. Enquanto a cobrança está em aberto, a Vira confere o pagamento direto no banco parceiro a cada chamada (no máximo uma vez a cada 5 segundos).
curl https://virapagamento.com.br/api/v1/charges/0b6f4c1e-8d52-4e0c-9a57-2f3c7b8e1a10 \
-H "Authorization: Bearer vira_sk_SUA_CHAVE"Situações possíveis no campo status:
PENDINGAguardando pagamento.PROCESSINGPagamento em análise.CONFIRMEDPagamento confirmado; o dinheiro ainda não foi liquidado (comum em cartão).PAIDPago e liquidado. É este o status que libera o pedido.OVERDUEVenceu sem pagamento.CANCELLEDCancelada.REFUND_PENDINGEstorno em andamento.REFUNDEDEstornada.CHARGEBACKContestada pelo pagador (chargeback).
Libere o pedido só quando o status for PAID. A Vira nunca marca como pago por conta própria: o status vem do banco parceiro.
4. Receber avisos (webhook)
Em vez de ficar perguntando, cadastre um endereço e a Vira avisa quando uma cobrança mudar. O endereço precisa ser HTTPS e público. A resposta traz o segredo de assinatura, que aparece uma única vez.
curl -X PUT https://virapagamento.com.br/api/v1/webhook-endpoint \
-H "Authorization: Bearer vira_sk_SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{ "url": "https://sualoja.com.br/avisos/vira" }'Cada aviso é um POST com este corpo. Ele só diz qual cobrança mudou; para saber o estado, consulte-a (passo 3). Assim, um aviso falso ou repetido não muda nada sozinho. Responda com qualquer status 2xx em até 5 segundos.
Atenção: por enquanto cada aviso é enviado uma vez, sem reenvio automático. Se o seu servidor estiver fora do ar nessa hora, o aviso se perde; por isso, consulte também as cobranças em aberto de tempos em tempos (passo 3).
{
"id": "5c0e1c7a-...",
"type": "charge.updated",
"chargeId": "0b6f4c1e-8d52-4e0c-9a57-2f3c7b8e1a10",
"createdAt": "2026-10-22T14:03:11.000Z"
}O cabeçalho X-Vira-Signature: t=<unix>,v1=<hex> traz a assinatura: v1 = HMAC-SHA256(segredo, "t.corpo"). Confira antes de usar o aviso:
// Node.js — confira a assinatura ANTES de confiar no aviso
import { createHmac, timingSafeEqual } from "node:crypto";
function assinaturaValida(segredo, cabecalho, corpoBruto) {
const partes = Object.fromEntries(cabecalho.split(",").map((p) => p.split("=")));
const t = partes.t;
const esperado = createHmac("sha256", segredo).update(t + "." + corpoBruto).digest("hex");
const a = Buffer.from(esperado);
const b = Buffer.from(partes.v1 ?? "");
const recente = Math.abs(Date.now() / 1000 - Number(t)) < 300; // 5 minutos
return recente && a.length === b.length && timingSafeEqual(a, b);
}5. Erros
Os erros voltam em JSON, no formato { "error": { "code", "message" } }.
- 401
unauthorizedChave ausente, errada ou revogada. - 403
pj_onlyA API é exclusiva para contas de empresa (CNPJ). - 403
org_inactiveA conta está suspensa ou recusada. - 400
idempotency_key_requiredFaltou o cabeçalho Idempotency-Key (8 a 100 caracteres). - 409
duplicate_referenceJá existe uma cobrança com essa referência. - 409
idempotency_mismatchA mesma Idempotency-Key foi usada com outro conteúdo. - 404
not_foundCobrança não encontrada. - 422
invalid_requestAlgum campo está inválido; a resposta lista quais. - 422
invalid_urlEndereço de avisos inválido (use HTTPS público).
Boas práticas
- Guarde a chave e o segredo do aviso só no servidor, em variáveis de ambiente.
- Use uma chave por sistema (loja, ERP…) para poder revogar uma sem parar as outras.
- Chave vazou? Revogue em Configurações → Integrações: ela deixa de funcionar na hora.
- Sempre confira a assinatura dos avisos e consulte a cobrança antes de liberar o pedido.
Dúvidas ou precisa de ajuda na integração? Fale com o suporte dentro do painel. Criar conta de empresa