VolgaPay — Guia de integração para merchants
API de pagamentos da VolgaPay: PIX, cartão, cripto, links de pagamento, saldo, saques e webhooks.
- Base URL (ambiente atual):
https://volgapay.com - Documentação interativa:
https://volgapay.com/docs - OpenAPI:
https://volgapay.com/openapi.yaml - Formato: JSON, UTF-8
- Valores: sempre em centavos, inteiros.
R$ 10,00=1000. - Autenticação: API key no header
Authorization: Bearer vp_...
A VolgaPay não possui sandbox separado. Testes são feitos em produção com valor baixo e dados reais do pagador.
1. Primeiros passos
- Crie a conta de merchant no painel VolgaPay.
- Ative o 2FA do titular. A criação de API keys exige 2FA.
- Crie uma API key em Configurações → Chaves de API.
- Guarde o token
vp_...: ele aparece uma única vez. - Cadastre os IPs permitidos da sua aplicação (opcional, mas recomendado).
- Cadastre um endpoint de webhook para receber
payment.succeeded,payment.failed, etc. - Consulte
GET /v1/methodspara ver métodos, moedas e taxas da sua conta.
Escopos
| Escopo | Para quê |
|---|---|
payments:read | Consultar pagamentos e listar |
payments:write | Criar, capturar, cancelar e reembolsar |
payouts:read | Consultar saques |
payouts:write | Solicitar saques |
balance:read | Consultar saldo |
kyc:read / kyc:write | Enviar e consultar KYC |
webhooks:read / webhooks:write | Gerenciar endpoints e entregas |
admin | Operações administrativas (não use no servidor do merchant) |
Use o menor escopo possível. Uma chave de produção não deve ser usada no navegador nem em aplicativos móveis.
2. Autenticação
Authorization: Bearer vp_<key_id>_<secret>
Content-Type: application/json
Accept: application/json
Exemplo:
curl https://volgapay.com/v1/balance \
-H "Authorization: Bearer vp_SEU_TOKEN"
IP allowlist
Cada API key pode ter uma lista de IPs/CIDRs. Se a lista estiver preenchida, requisições de outros IPs recebem 401.
Rotação
Revogue a chave antiga e crie outra. A revogação é imediata.
3. Idempotência
Envie Idempotency-Key em toda operação que cria dinheiro:
POST /v1/paymentsPOST /v1/payments/{id}/refundPOST /v1/payouts
Idempotency-Key: pedido-1001
Regras:
- A mesma chave + o mesmo corpo devolve o resultado original.
- A mesma chave + corpo diferente retorna
409. - Use uma chave nova por pedido; para repetir o mesmo pedido após timeout, use a mesma chave.
- Guarde a chave no seu banco junto com o pedido.
4. Criar pagamento PIX
POST /v1/payments
Corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
amount | inteiro | sim | Valor em centavos |
currency | string | sim | BRL para PIX |
method | string | sim | pix |
country | string | não | BR (inferido para PIX) |
description | string | não | Aparece no seu extrato/painel |
customer | objeto | sim no PIX | Pagador |
metadata | objeto | não | Dados seus, devolvidos na consulta |
capture | booleano | não | Só cartão; padrão true |
Pagador (customer) no PIX
A VolgaPay exige o pagador completo na produção:
| Campo | Obrigatório | Regra |
|---|---|---|
name | sim | Nome completo, mínimo 2 caracteres |
document | sim | CPF ou CNPJ válido (com ou sem pontuação) |
phone | sim | Telefone com DDD. Ex.: +5511999990000 |
email | recomendado | E-mail válido |
external_id | não | Seu identificador do cliente |
Sem nome, documento e telefone válidos, a cobrança é recusada com
422e códigocobranca_recusada_pelo_provedor.
Exemplo
curl -X POST https://volgapay.com/v1/payments \
-H "Authorization: Bearer vp_SEU_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-1001" \
-d '{
"amount": 1000,
"currency": "BRL",
"method": "pix",
"country": "BR",
"description": "Pedido 1001",
"customer": {
"name": "Cliente Exemplo",
"email": "[email protected]",
"phone": "+5511999990000",
"document": "529.982.247-25"
},
"metadata": { "order_id": "1001" }
}'
Resposta 201
{
"id": "01M760P713WDTJ7RF0W6DDZP9D",
"object": "payment",
"amount": 1000,
"fee": 30,
"net": 970,
"currency": "BRL",
"method": "pix",
"status": "requires_action",
"provider_reference": "13",
"description": "Pedido 1001",
"pix": {
"qr_code": "0002010102122664...6304D12B",
"copia_e_cola": "0002010102122664...6304D12B",
"expires_at": "2026-11-12T19:17:23Z"
},
"created_at": "2026-11-11T19:17:23Z"
}
pix.copia_e_colaé o PIX copia e cola.- Gere a imagem do QR code a partir dele (não dependa de
qr_codeser uma URL). - O status inicial é
requires_action. expires_até a validade informada pela adquirente.feeenetsão calculados pela sua tabela de taxas.
Status
| Status | Significado |
|---|---|
requires_action | Aguardando o pagador pagar o PIX |
processing | Em processamento |
succeeded | Pago e creditado no saldo líquido |
failed | Recusado/falhou |
canceled | Cancelado |
expired | Expirou sem pagamento |
refunded | Devolvido |
partially_refunded | Devolvido parcialmente |
chargeback | Contestação |
Libere o pedido somente com status = succeeded (e idealmente confirmando via GET /v1/payments/{id}).
5. Consultar pagamento
GET /v1/payments/{id}
curl https://volgapay.com/v1/payments/01M760P713WDTJ7RF0W6DDZP9D \
-H "Authorization: Bearer vp_SEU_TOKEN"
Retorna o pagamento completo, incluindo pix, fee, net, paid_at, failure e metadata.
Listar
GET /v1/payments?limit=20&before=<id>
Capturar cartão
POST /v1/payments/{id}/capture com {"amount": 1000} (opcional).
Cancelar
POST /v1/payments/{id}/cancel
No PIX, o cancelamento e a devolução podem não estar disponíveis pela API. Use o painel da VolgaPay para MED/devolução. O endpoint de cancelamento pode retornar erro para PIX.
Reembolsar
POST /v1/payments/{id}/refund
{ "amount": 1000, "reason": "Pedido cancelado" }
Sujeito ao método e ao provedor.
6. Webhooks
Cadastrar endpoint
POST /v1/webhook-endpoints
curl -X POST https://volgapay.com/v1/webhook-endpoints \
-H "Authorization: Bearer vp_SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://seu-sistema.com/webhooks/volgapay",
"events": ["payment.succeeded", "payment.failed", "payment.canceled", "payment.expired"]
}'
Resposta:
{
"id": "01...",
"object": "webhook_endpoint",
"url": "https://seu-sistema.com/webhooks/volgapay",
"events": ["payment.succeeded", "..."],
"secret": "whsec_...",
"_notice": "Guarde o secret agora; ele não será exibido novamente."
}
- O
secretaparece uma única vez. - Guarde-o em variável de ambiente, nunca no front-end.
- Use HTTPS com certificado válido.
- A VolgaPay não envia webhook para
localhost, IP privado ou rede interna.
Eventos
payment.succeededpayment.failedpayment.canceledpayment.expiredpayout.paidpayout.failed
Payload
{
"id": "01M...",
"type": "payment.succeeded",
"created_at": "2026-11-11T19:25:14+00:00",
"data": {
"payment_id": "01M760P713WDTJ7RF0W6DDZP9D",
"amount": 1000,
"currency": "BRL",
"method": "pix",
"status": "succeeded"
}
}
O payload do webhook é enxuto. Consulte
GET /v1/payments/{payment_id}para obterpix,fee,net,metadataepaid_at.
Assinatura
Headers:
X-VolgaPay-Event-Id: 01M...
X-VolgaPay-Signature: t=1791824530,v1=5d2f...64 hex...
A assinatura é:
HMAC-SHA256(secret, "<t>.<corpo cru>")
- Use o corpo cru, sem reserializar o JSON.
- Compare em tempo constante.
- Recuse
tcom mais de 5 minutos de diferença. - A assinatura cobre somente o corpo; não confie em headers para decidir o evento.
PHP
$raw = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_VOLGAPAY_SIGNATURE'] ?? '';
preg_match('/t=(\d+),v1=([0-9a-f]{64})/', $header, $m);
$expected = hash_hmac('sha256', $m[1] . '.' . $raw, getenv('VOLGAPAY_WEBHOOK_SECRET'));
if (! hash_equals($expected, $m[2])) {
http_response_code(401);
exit;
}
$event = json_decode($raw, true);
if ($event['type'] === 'payment.succeeded') {
// consulte GET /v1/payments/{$event['data']['payment_id']} antes de liberar
}
http_response_code(200);
Node.js
const crypto = require('crypto');
const raw = req.rawBody; // Buffer, corpo cru
const secret = process.env.VOLGAPAY_WEBHOOK_SECRET;
const [t, v1] = String(req.get('X-VolgaPay-Signature')).match(/t=(\d+),v1=([0-9a-f]{64})/).slice(1);
const expected = crypto.createHmac('sha256', secret).update(`${t}.`).update(raw).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) return res.status(401).end();
const event = JSON.parse(raw.toString('utf8'));
if (event.type === 'payment.succeeded') { /* confirmar na API */ }
res.status(200).end();
Retentativas e duplicatas
- Responda
2xxem até 15 segundos. - A VolgaPay tenta novamente em caso de falha (até 8 tentativas).
- O mesmo evento pode chegar mais de uma vez. Descarte por
X-VolgaPay-Event-Id. - Sempre confirme o pagamento na API antes de creditar saldo.
Consultar entregas
GET /v1/webhook-deliveries
Mostra status, tentativas, código HTTP e erro das últimas entregas.
7. Saldo
GET /v1/balance?currency=BRL
{
"object": "balance",
"currency": "BRL",
"available": 970,
"payout_hold": 0
}
available é o saldo disponível para saque, em centavos.
8. Saques (PIX-out)
Pré-requisitos:
- KYC aprovado.
- Saldo disponível suficiente.
- Chave PIX válida.
POST /v1/payouts
{
"amount": 1000,
"currency": "BRL",
"payout_method": "pix",
"pix_key_type": "cpf",
"pix_key": "529.982.247-25",
"reason": "Saque do merchant"
}
Resposta 201:
{
"id": "01...",
"object": "payout",
"amount": 1000,
"fee": 0,
"currency": "BRL",
"status": "pending_approval",
"payout_method": "pix",
"pix_key_type": "cpf",
"pix_key_last4": "7-25",
"requested_at": "2026-11-11T20:00:00Z"
}
Status:
pending_approval: aguardando aprovação do adminprocessing: enviado ao provedorpaid: pagofailed: falhourejected: recusado
Consulte GET /v1/payouts/{id}. O webhook payout.paid também é enviado.
Saques podem exigir aprovação manual. O saldo fica retido enquanto o saque está pendente.
9. Clientes
POST /v1/customers
{
"external_id": "cliente-123",
"name": "Cliente Exemplo",
"email": "[email protected]",
"phone": "+5511999990000",
"document": "529.982.247-25",
"country": "BR",
"metadata": { "plan": "pro" }
}
Depois use customer_id em POST /v1/payments.
GET /v1/customers/{id} consulta.
10. Links de pagamento
POST /v1/payment-links
{
"amount": 10000,
"currency": "BRL",
"description": "Plano anual",
"methods": ["pix", "card", "volgapay"],
"max_installments": 12
}
A resposta inclui url e token. Compartilhe a url com o cliente.
GET /v1/payment-linkslista.POST /v1/payment-links/{id}/deactivatedesativa.
11. Métodos e taxas
GET /v1/methods
Retorna os métodos ativos, moedas, países, campos e taxas da sua conta. Use catalog e fees para montar seu checkout.
12. Erros
Formato:
{
"error": {
"type": "unprocessable_entity",
"code": "unprocessable_entity",
"message": "Mensagem legível",
"details": {}
}
}
| HTTP | Significado |
|---|---|
400 | Requisição inválida |
401 | API key ausente/inválida ou IP não permitido |
403 | Sem escopo ou acesso negado |
404 | Recurso não encontrado |
409 | Conflito/idempotência |
422 | Regra de negócio (pagador inválido, saldo insuficiente, etc.) |
429 | Rate limit |
502 | Provedor recusou/falhou |
503 | Provedor indisponível |
Erros do provedor PIX podem vir com code:
provedor_indisponivel— conta/provedor ainda não ativo; nada foi cobrado.fora_do_horario— conta só gera cobranças em determinado horário.cobranca_recusada_pelo_provedor— dados do pagador/valor recusados.cobranca_vencida— reenvio de PIX vencido; use outra Idempotency-Key.
13. Boas práticas de segurança
- Nunca coloque a API key no front-end, no app mobile ou no repositório.
- Use HTTPS e valide o certificado.
- Guarde o webhook secret em variável de ambiente.
- Sempre verifique a assinatura do webhook.
- Sempre confirme o pagamento na API antes de liberar o pedido.
- Use
Idempotency-Keye guarde-a no seu banco. - Restrinja a API key por IP.
- Ative 2FA no titular.
- Rotacione chaves periodicamente.
- Não use dados fictícios do pagador em produção.
14. Exemplo completo de PIX
- Seu servidor cria o pagamento:
POST /v1/payments
Idempotency-Key: pedido-1001
- A resposta traz
id,pix.copia_e_colaeexpires_at.
- Seu checkout mostra o QR/copia-e-cola.
- O cliente paga.
- A VolgaPay envia
payment.succeededpara o seu webhook.
- Seu servidor verifica a assinatura, consulta
GET /v1/payments/{id}e confirmastatus = succeedede o valor.
- Seu servidor credita o pedido uma única vez.
- Se o webhook não chegar, o polling em
GET /v1/payments/{id}reconcilia.
15. Extensibilidade — novas adquirentes
A API é agnóstica de adquirente. Quando a VolgaPay adiciona um novo PSP ou uma nova rota interna:
- a base URL não muda;
- os endpoints
/v1/...não mudam; - sua API key continua a mesma;
- os webhooks continuam com o mesmo formato e assinatura;
GET /v1/methodspassa a refletir novos métodos/moedas/taxas.
A VolgaPay roteia internamente por método, moeda, país e grupo de risco. Você não precisa criar uma nova integração nem emitir novos tokens para cada adquirente.
16. Suporte
- Documentação:
https://volgapay.com/docs - OpenAPI:
https://volgapay.com/openapi.yaml - Suporte VolgaPay: pelo painel do merchant (único canal de suporte da integração)
Ao abrir suporte, informe:
- merchant id;
- id do pagamento;
- horário UTC;
- rota e método HTTP;
- código HTTP e
codedo erro; Idempotency-Keyusada.