Documentação API

Referência técnica para integração com a VeniPay — v1

Visão Geral

A API VeniPay permite criar e gerenciar cobranças via PIX, cartão de crédito, débito e boleto de forma programática, além de realizar saques (cash-out) via Pix. Todas as requisições e respostas utilizam JSON sobre HTTPS.

Base URL

https://api.venipay.com.br/api/v1

Todos os endpoints descritos nesta página são relativos à base URL acima. Por exemplo, POST /transactions corresponde a https://api.venipay.com.br/api/v1/transactions.

Sandbox: as chaves de API e o modo sandbox são gerenciados pela área logada. Ative o modo sandbox no painel para testar sem transações reais.

Autenticação

Todas as requisições autenticadas devem incluir sua API key no header Authorization com o esquema Bearer.

Header
Authorization: Bearer sk_live_SuaChaveAqui

Suas chaves de API estão disponíveis em Painel → Integrações → Chaves de API. Cada chave é vinculada ao seu merchant e registra IP e data/hora do último uso.

Importante: nunca exponha sua API key em código client-side (JavaScript do navegador, apps móveis, repositórios públicos). Todas as chamadas devem partir do seu servidor.

Códigos de Erro

A API retorna erros com um objeto JSON contendo o campo error. Os status HTTP mais comuns:

StatusSignificado
401API key ausente, inválida ou expirada.
403Conta do merchant inativa.
404Recurso não encontrado.
422Erro de validação ou regra de negócio (ex.: saldo insuficiente, status inválido para a operação).
500Erro interno do servidor. Tente novamente ou contate o suporte.
Exemplo de resposta de erro
{ "error": "API key required" }

Transações

POST /transactions Criar transação

Cria uma nova cobrança. Se idempotency_key for fornecida e já existir uma transação com a mesma chave, retorna a transação existente com status 200 em vez de criar uma nova.

Parâmetros (body)

CampoTipoObrigatórioDescrição
amountnumbersimValor em reais. Mínimo: 0.01
payment_methodstringsimpix, credit, debit ou boleto
descriptionstringnãoDescrição da cobrança. Máx: 255
installmentsintegernãoParcelas (1–12). Aplicável a credit
payer_namestringnãoNome do pagador. Máx: 255
payer_documentstringnãoCPF ou CNPJ do pagador. Máx: 18
payer_emailstringnãoE-mail do pagador
payer_phonestringnãoTelefone do pagador. Máx: 20
external_idstringnãoIdentificador do seu sistema. Máx: 255
metadataobjectnãoDados adicionais livres (JSON)
idempotency_keystringnãoChave de idempotência. Máx: 255
Exemplo curl
curl -X POST https://api.venipay.com.br/api/v1/transactions \ -H "Authorization: Bearer sk_live_SuaChaveAqui" \ -H "Content-Type: application/json" \ -d '{ "amount": 150.00, "payment_method": "pix", "payer_name": "João Silva", "payer_document": "123.456.789-00", "description": "Pedido #1042", "external_id": "pedido-1042" }'

Retorna 201 Created com o objeto da transação.

GET /transactions Listar transações

Retorna uma lista paginada das transações do seu merchant.

Query Parameters

CampoTipoObrigatórioDescrição
statusstringnãoFiltrar por status (ex.: approved, pending)
payment_methodstringnãoFiltrar por método: pix, credit, debit, boleto
date_fromstringnãoData inicial (formato: YYYY-MM-DD)
date_tostringnãoData final (formato: YYYY-MM-DD)
per_pageintegernãoItens por página. Padrão: 20
Exemplo
curl https://api.venipay.com.br/api/v1/transactions?status=approved&per_page=10 \ -H "Authorization: Bearer sk_live_SuaChaveAqui"

Retorna 200 OK com paginação Laravel padrão (data, current_page, last_page, total, etc.).

GET /transactions/{id} Consultar transação

Retorna os detalhes de uma transação específica.

Exemplo
curl https://api.venipay.com.br/api/v1/transactions/abc123 \ -H "Authorization: Bearer sk_live_SuaChaveAqui"
POST /transactions/{id}/capture Capturar transação

Captura uma transação previamente autorizada. Somente transações com status authorized podem ser capturadas.

Exemplo
curl -X POST https://api.venipay.com.br/api/v1/transactions/abc123/capture \ -H "Authorization: Bearer sk_live_SuaChaveAqui"

Retorna 200 OK com a transação atualizada (status captured).

POST /transactions/{id}/void Cancelar transação

Cancela uma transação com status pending ou authorized.

Exemplo
curl -X POST https://api.venipay.com.br/api/v1/transactions/abc123/void \ -H "Authorization: Bearer sk_live_SuaChaveAqui"

Retorna 200 OK com a transação atualizada (status cancelled).

POST /transactions/{id}/refund Reembolsar transação

Solicita reembolso total ou parcial de uma transação com status approved ou captured. Se amount não for informado, será reembolsado o valor total.

CampoTipoObrigatórioDescrição
amountnumbernãoValor do reembolso. Mínimo: 0.01. Não pode exceder o saldo reembolsável.
reasonstringnãoMotivo do reembolso. Máx: 500
Exemplo — reembolso parcial
curl -X POST https://api.venipay.com.br/api/v1/transactions/abc123/refund \ -H "Authorization: Bearer sk_live_SuaChaveAqui" \ -H "Content-Type: application/json" \ -d '{ "amount": 50.00, "reason": "Produto devolvido" }'

Retorna 201 Created com o objeto de reembolso.

PIX

POST /pix/qrcode Gerar QR Code PIX

Gera uma cobrança PIX com QR Code. É um atalho para criar uma transação com payment_method: pix e retorna diretamente os dados do QR Code.

CampoTipoObrigatórioDescrição
amountnumbersimValor em reais. Mínimo: 0.01
descriptionstringnãoDescrição. Máx: 255
payer_namestringnãoNome do pagador. Máx: 255
payer_documentstringnãoCPF/CNPJ do pagador. Máx: 18
expiration_minutesintegernãoMinutos até expiração (5–1440). Padrão definido pelo gateway.
external_idstringnãoIdentificador do seu sistema. Máx: 255
Exemplo
curl -X POST https://api.venipay.com.br/api/v1/pix/qrcode \ -H "Authorization: Bearer sk_live_SuaChaveAqui" \ -H "Content-Type: application/json" \ -d '{ "amount": 89.90, "description": "Assinatura mensal" }'
Resposta 201
{ "transaction_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "txid": "VNP1042abc", "qrcode": "00020126580014br.gov.bcb.pix...", "qrcode_url": "https://app.venipay.com.br/pix/qr/VNP1042abc", "expiration": "2026-03-25T15:30:00-03:00", "amount": 89.90, "status": "pending" }
GET /pix/qrcode/{txid} Consultar status PIX

Consulta o status de uma cobrança PIX pelo txid.

Resposta 200
{ "transaction_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "txid": "VNP1042abc", "amount": 89.90, "status": "approved", "paid_at": "2026-03-25T14:22:10-03:00" }

Financeiro / Cash-out

GET /balance Consultar saldo

Retorna o saldo atual do merchant em reais.

Resposta 200
{ "available": 12450.00, "pending": 3200.50, "blocked": 0.00, "total": 15650.50, "currency": "BRL" }
CampoDescrição
availableDisponível para saque imediato.
pendingValores em liquidação (aguardando D+N).
blockedBloqueado por saques em processamento, disputas ou medidas de segurança.
totalSoma: available + pending + blocked.
POST /payouts Solicitar saque (Cash-out)

Solicita transferência do saldo disponível via Pix. O valor é movido de available para blocked até a conclusão.

Pré-requisitos: a funcionalidade API Cash-out deve estar habilitada para o seu merchant (painel administrativo). O destino do Pix pode ser informado no corpo da requisição (pix_key + pix_key_type) ou escolhido entre os destinos cadastrados no painel (Saldo → Destinos Pix), via bank_account_id ou destino principal.
Dois modos de destino

1) Chave no JSON (recomendado para integrações estilo carteira): envie pix_key e pix_key_type junto com amount. Opcionalmente holder_name e holder_document para o adquirente (ex.: MisticPay). Se pix_key for enviada, ela tem prioridade sobre bank_account_id.

2) Destino no painel: omita pix_key e use bank_account_id (ou deixe em branco para o destino principal). É necessário ter um destino com chave Pix válida.

CampoTipoObrigatórioDescrição
amountnumbersimValor em reais. Limites: mínimo 5, máximo 15000 (configuráveis na plataforma).
methodstringnãoApenas pix (padrão). Saques são sempre por Pix.
pix_keystringcondicionalChave Pix de recebimento. Se informada, exige pix_key_type e dispensa destino cadastrado no painel.
pix_key_typestringcondicionalcpf, cnpj, email, phone ou random (chave aleatória). Obrigatório quando pix_key é enviada.
holder_namestringnãoNome do favorecido (opcional, para gateways que exigem).
holder_documentstringnãoCPF/CNPJ do favorecido, só dígitos (opcional).
bank_account_idintegernãoID do destino Pix no painel. Usado apenas quando pix_key não é enviada. Se omitido, usa o destino principal.
Exemplo (chave Pix no corpo)
curl -X POST https://api.venipay.com.br/api/v1/payouts \ -H "Authorization: Bearer sk_live_SuaChaveAqui" \ -H "Content-Type: application/json" \ -d '{ "amount": 100.00, "pix_key": "email@exemplo.com", "pix_key_type": "email" }'
Exemplo (destino cadastrado no painel)
curl -X POST https://api.venipay.com.br/api/v1/payouts \ -H "Authorization: Bearer sk_live_SuaChaveAqui" \ -H "Content-Type: application/json" \ -d '{ "amount": 5000.00, "method": "pix" }'

Retorna 201 Created com o objeto do saque. A chave Pix informada no body não é devolvida por completo: use payout_pix_key_masked (últimos dígitos). A taxa aplicável (se houver) é calculada automaticamente conforme seu plano de taxas.

Resposta 201 (trecho)
{ "id": 42, "merchant_id": 1, "bank_account_id": null, "payout_pix_key_masked": "************.com", "amount": "100.00", "fee_amount": "4.00", "net_amount": "96.00", "method": "pix", "status": "processing", "processed_at": "2026-03-25T14:22:10.000000Z", "completed_at": null, "created_at": "2026-03-25T14:22:10.000000Z", "updated_at": "2026-03-25T14:22:10.000000Z" }

Erros específicos do Cash-out

As respostas de erro incluem os campos code (identificador estável), error (mensagem curta em inglês), message (explicação em português) e, quando aplicável, hints (lista de orientações).

StatuscodeCausa
403CASHOUT_API_DISABLEDAPI Cash-out não habilitada no painel admin para este merchant.
422NO_PAYOUT_DESTINATIONSem pix_key no body e sem destino no painel (ou bank_account_id inválido).
422DESTINATION_NO_PIX_KEYO destino selecionado não possui chave Pix.
422INSUFFICIENT_BALANCESaldo disponível insuficiente para o valor solicitado.
GET /payouts/{id} Consultar saque

Retorna os detalhes de um saque específico.

Exemplo
curl https://api.venipay.com.br/api/v1/payouts/42 \ -H "Authorization: Bearer sk_live_SuaChaveAqui"

Webhooks

Webhooks permitem que seu servidor receba notificações automáticas quando eventos ocorrem (ex.: pagamento aprovado). Configure URLs de callback e selecione quais eventos deseja receber.

GET /webhooks Listar webhooks

Retorna todos os webhooks ativos do seu merchant.

POST /webhooks Criar webhook
CampoTipoObrigatórioDescrição
urlstringsimURL HTTPS que receberá os eventos. Máx: 500
eventsarraysimLista de eventos (ao menos 1). Veja eventos disponíveis.
Exemplo
curl -X POST https://api.venipay.com.br/api/v1/webhooks \ -H "Authorization: Bearer sk_live_SuaChaveAqui" \ -H "Content-Type: application/json" \ -d '{ "url": "https://seu-servidor.com/webhooks/venipay", "events": ["transaction.approved", "transaction.refunded"] }'

Retorna 201 Created com o webhook criado, incluindo o campo secret (prefixo whsec_). Guarde o secret com segurança — ele será usado para verificar assinaturas.

DELETE /webhooks/{id} Remover webhook

Remove um webhook. Retorna 204 No Content.

Eventos Disponíveis

transaction.created transaction.approved transaction.declined transaction.refunded transaction.chargeback settlement.completed settlement.failed

Formato do payload

Cada notificação é enviada como POST para a URL cadastrada com os seguintes headers e corpo:

HeaderDescrição
Content-Typeapplication/json
X-VeniPay-EventTipo do evento (ex.: transaction.approved)
X-VeniPay-SignatureHMAC-SHA256 do corpo para verificação de autenticidade
Exemplo de payload — transaction.approved
{ "event": "transaction.approved", "data": { "transaction_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "external_id": "pedido-1042", "type": "cash_in", "payment_method": "pix", "status": "approved", "amount": 150.00, "fee_amount": 2.25, "net_amount": 147.75, "currency": "BRL", "paid_at": "2026-03-25T14:22:10-03:00", "created_at": "2026-03-25T14:20:00-03:00" }, "timestamp": "2026-03-25T14:22:11-03:00" }

Retentativas

Se seu servidor retornar um status HTTP diferente de 2xx, a VeniPay reenvia a notificação com backoff progressivo:

  1. 30 segundos
  2. 2 minutos
  3. 10 minutos
  4. 1 hora
  5. 24 horas

Após 10 falhas consecutivas, o webhook é automaticamente desativado. Reative-o pelo painel ou crie um novo via API.

Verificação de Assinatura

Para garantir que a notificação veio da VeniPay e não foi adulterada, valide o header X-VeniPay-Signature comparando-o com o HMAC-SHA256 do corpo bruto da requisição usando o secret do seu webhook.

A assinatura é calculada sobre o JSON serializado do corpo (json_encode do objeto { event, data, timestamp }). Use o corpo bruto da requisição (raw body) para a comparação, sem reparseá-lo.

PHP
$payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_VENIPAY_SIGNATURE'] ?? ''; $secret = 'whsec_SeuSecretAqui'; $expected = hash_hmac('sha256', $payload, $secret); if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Assinatura inválida'); } $data = json_decode($payload, true); // Processar evento...
Node.js
const crypto = require('crypto'); app.post('/webhooks/venipay', (req, res) => { const payload = JSON.stringify(req.body); const signature = req.headers['x-venipay-signature']; const secret = 'whsec_SeuSecretAqui'; const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); if (expected !== signature) { return res.status(401).send('Assinatura inválida'); } // Processar evento... res.sendStatus(200); });
Python
import hmac, hashlib, json from flask import Flask, request app = Flask(__name__) @app.route('/webhooks/venipay', methods=['POST']) def webhook(): payload = request.get_data(as_text=True) signature = request.headers.get('X-VeniPay-Signature', '') secret = 'whsec_SeuSecretAqui' expected = hmac.new( secret.encode(), payload.encode(), hashlib.sha256 ).hexdigest() if not hmac.compare_digest(expected, signature): return 'Assinatura inválida', 401 data = json.loads(payload) # Processar evento... return '', 200
Atenção: sempre use comparação segura contra timing attacks (hash_equals em PHP, hmac.compare_digest em Python, crypto.timingSafeEqual em Node.js). Comparação direta com === pode ser vulnerável.

Precisa de ajuda com a integração?

Falar com o suporte técnico Criar conta