API REST v1
Integre a Eleva Payments ao seu sistema
Com a API você cria cobranças Pix e no cartão, recebe em reais ou em USDT, divide o valor com parceiros (split), consulta transações, faz saques via Pix e é avisado de tudo por webhook. Funciona com qualquer linguagem que faça requisições HTTPS com JSON.
Como funciona uma venda
-
1
Seu sistema cria a cobrança
POST /payments/pix com valor e dados do pagador. Guarde o transaction_uuid junto do pedido.
-
2
Você mostra o Pix ao cliente
Use qr_code_base64 (imagem pronta) e pix_code (copia e cola). A cobrança expira em expires_in_seconds.
-
3
O cliente paga
Nós recebemos a confirmação da adquirente e creditamos o valor líquido no seu saldo.
-
4
Você é avisado
Enviamos o webhook deposit.completed para a sua URL. Valide a assinatura e libere o pedido.
Base URL
https://app.elevapayments.live/api/v1
Formato
JSON (UTF-8), só HTTPS
Especificação
OpenAPI 3 (YAML)O arquivo OpenAPI pode ser importado no Postman, Insomnia ou em geradores de SDK. Não existe ambiente de testes separado: teste em produção com valores baixos (ex.: R$ 5,00).
Em 10 minutos
Início rápido
Do zero até receber o primeiro Pix e o aviso de pagamento no seu servidor.
1. Gere as credenciais
Em Chave API crie uma credencial. Você recebe um Client ID e um Token. O token só aparece uma vez: guarde em variável de ambiente do servidor. Na mesma tela informe a URL de webhook.
2. Crie uma cobrança Pix
curl -X POST "https://app.elevapayments.live/api/v1/payments/pix" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "X-Client-ID: SEU_CLIENT_ID" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"amount": 49.90,
"payer_name": "Maria Souza",
"payer_email": "[email protected]",
"payer_cpf": "52998224725",
"description": "Pedido #1042"
}'3. Mostre o QR Code ao cliente
A resposta traz tudo pronto. Guarde o transaction_uuid no seu pedido.
{
"success": true,
"data": {
"transaction_uuid": "9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10",
"amount": 49.90,
"fee": 1.50,
"amount_net": 48.40,
"status": "pending",
"qr_code": "00020101021226870014br.gov.bcb.pix2565...6304ABCD",
"pix_code": "00020101021226870014br.gov.bcb.pix2565...6304ABCD",
"qr_code_base64": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...",
"expires_at": "2026-10-01T14:35:00-03:00",
"expires_in_seconds": 300,
"settlement": "brl"
}
}<!-- QR Code pronto: use o qr_code_base64 direto na tag img -->
<img src="{qr_code_base64}" alt="QR Code Pix" width="240" height="240">
<!-- Copia e cola -->
<input value="{pix_code}" readonly>
<button onclick="navigator.clipboard.writeText('{pix_code}')">Copiar código Pix</button>4. Receba o webhook e libere o pedido
Quando o Pix for pago, enviamos deposit.completed para a sua URL. antes de liberar. Sem webhook, consulte GET /payments/{uuid} a cada 5 a 10 segundos enquanto o cliente está na tela.
Segurança
Autenticação
Toda requisição leva o token no header Authorization e o Client ID em X-Client-ID.
Authorization: Bearer SEU_TOKEN
X-Client-ID: SEU_CLIENT_ID
Content-Type: application/json
Accept: application/jsonBoas práticas
- • Chame a API só do seu servidor. Nunca exponha o token em site, app ou repositório.
- • Crie uma credencial por sistema/loja: fica fácil revogar uma sem afetar as outras.
- • Cadastre o IP do servidor na credencial: chamadas de outros IPs são recusadas (403).
- • O mesmo token é o segredo que assina os webhooks.
Quando a autenticação falha
- 401 token ausente, inválido, revogado ou expirado.
- 403 conta bloqueada, cadastro (KYC) não aprovado ou IP fora da lista da credencial.
Compatibilidade: o token também é aceito no header X-API-Token. Token na URL ou no corpo é recusado. O token aparece uma única vez ao criar a credencial (dá para trocar a qualquer momento no painel). Em saques, envie o header Idempotency-Key (8 a 80 caracteres): repetir o pedido com a mesma chave devolve o saque já criado, sem sacar de novo.
Antes de codar
Convenções e limites
Valores
Em reais, número decimal com ponto e até 2 casas: 49.90. Nas respostas: amount (bruto), fee (taxa) e amount_net (o que entra no seu saldo).
Datas
ISO 8601 com fuso, ex.: 2026-10-01T14:31:12-03:00. Filtros de data aceitam AAAA-MM-DD.
Identificadores
Cada cobrança tem um transaction_uuid (UUID v4). Use-o para consultar, estornar e casar com os webhooks.
Respostas
Sempre JSON com success (true/false). Em erro vem message e, na validação, errors por campo.
Limite de requisições
120 por minuto por token. Acima disso a resposta é 429 com o header Retry-After. Existe também um limite geral por IP contra abuso.
Repetição segura
Não há chave de idempotência. Se a criação der timeout, consulte a lista de transações antes de criar outra, para não cobrar duas vezes o mesmo pedido.
Paginação
page e per_page (1 a 100, padrão 20). A resposta traz pagination.total e last_page.
Tempo limite
Use 30 segundos de timeout. A criação de cobrança consulta a adquirente e pode levar alguns segundos.
Receber
Cobrança Pix
Gera um Pix com QR Code e copia e cola. O valor líquido entra no seu saldo assim que o pagamento é confirmado.
https://app.elevapayments.live/api/v1/payments/pixCorpo da requisição
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
amount | decimal | Sim | Valor da cobrança em reais (ex.: 49.90). |
payer_name | string | Sim | Nome completo do pagador (até 255). |
payer_email | string | Sim | E-mail do pagador. |
payer_cpf | string | Sim | CPF ou CNPJ do pagador (com ou sem pontuação). |
description | string | Não | Descrição que aparece para você (até 500). Ex.: "Pedido #1042". |
settlement | string | Não | "brl" (padrão) ou "usdt" para receber esta venda em USDT. Veja Pix em USDT. |
splits | array | Não | Divisão do valor com outros lojistas. Veja Split de pagamento. |
Resposta 201
{
"success": true,
"data": {
"transaction_uuid": "9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10",
"amount": 49.90,
"fee": 1.50,
"amount_net": 48.40,
"status": "pending",
"qr_code": "00020101021226870014br.gov.bcb.pix2565...6304ABCD",
"pix_code": "00020101021226870014br.gov.bcb.pix2565...6304ABCD",
"qr_code_base64": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...",
"expires_at": "2026-10-01T14:35:00-03:00",
"expires_in_seconds": 300,
"settlement": "brl"
}
}| Campo | O que é |
|---|---|
transaction_uuid | Identificador da cobrança. Guarde junto do pedido. |
pix_code / qr_code | Pix copia e cola (texto EMV). Os dois campos têm o mesmo valor. |
qr_code_base64 | Imagem do QR Code pronta (data URI SVG) para usar em <img src>. |
expires_at / expires_in_seconds | Quando a cobrança expira. Em geral 5 minutos (30 em USDT). Depois disso, crie outra. |
fee / amount_net | Taxa desta cobrança e o valor líquido que vai para o seu saldo. |
pending). Libere o pedido apenas com o webhook deposit.completed ou consultando o status completed.Depósito na própria conta
Para colocar saldo na sua conta (você é o pagador), use POST /cashin/pix com amount (mínimo R$ 1,00). A resposta traz transaction.uuid e qr_code.
Receber
Cartão de crédito
Cobre no cartão em até 12x. A venda aprovada vira parcelas que entram no seu saldo nas datas de liquidação. Precisa estar liberado para a sua conta (sem liberação a resposta é 403).
https://app.elevapayments.live/api/v1/payments/credit-cardCorpo da requisição
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
amount | decimal | Sim | Valor da compra (mínimo R$ 1,00). |
installments | integer | Não | Parcelas, de 1 a 12 (limite da sua conta). Padrão 1. |
card.number | string | Sim | Número do cartão (com ou sem espaços). |
card.holder | string | Sim | Nome impresso no cartão. |
card.expiration | string | Sim | Validade MM/AAAA ou MM/AA. |
card.cvv | string | Sim | Código de segurança (3 ou 4 dígitos). |
payer_name | string | Sim | Nome do comprador. |
payer_cpf | string | Não | CPF/CNPJ do comprador. Aumenta a aprovação. |
payer_email | string | Não | E-mail do comprador (análise de risco). |
payer_phone | string | Não | Telefone do comprador. |
billing | object | Não | Endereço de cobrança: zipcode, street, number, city, state (UF). |
three_ds | string | Não | "none", "auto" ou "required". Com 3DS o risco de chargeback por fraude passa ao banco emissor. |
return_url | string | Não | Para onde o cliente volta depois de autenticar no banco (use com 3DS). |
description | string | Não | Descrição da venda. |
Respostas
- 201 approved: aprovada. Traz
release_schedulecom as parcelas e datas. - 202 requires_authentication: redirecione o cliente para
authentication_url. Ele volta emreturn_url?transaction_uuid=...&status=approved|declined|pending. Confirme pelo webhook ou pela consulta, nunca só pela URL de volta. - 202 processing: a adquirente não respondeu a tempo. Consulte a transação em instantes.
- 402 declined: recusada pelo banco. Mostre
messagee vejadecline.retryableantes de tentar de novo.
curl -X POST "https://app.elevapayments.live/api/v1/payments/credit-card" \
-H "Authorization: Bearer SEU_TOKEN" -H "X-Client-ID: SEU_CLIENT_ID" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{
"amount": 250.00,
"installments": 3,
"card": { "number": "4111111111111111", "holder": "MARIA S SOUZA", "expiration": "12/2030", "cvv": "123" },
"payer_name": "Maria Souza",
"payer_cpf": "52998224725",
"payer_email": "[email protected]",
"three_ds": "auto",
"return_url": "https://sualoja.com/pedido/4471"
}'{
"success": true,
"data": {
"transaction_uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "approved",
"amount": 250.00, "fee": 18.50, "amount_net": 231.50,
"installments": 3,
"card": { "brand": "Visa", "last4": "1111" },
"release_schedule": [
{ "installment": 1, "amount": 77.16, "date": "2026-11-01" },
{ "installment": 2, "amount": 77.16, "date": "2026-12-01" },
{ "installment": 3, "amount": 77.18, "date": "2026-12-31" }
]
}
}Estorno
https://app.elevapayments.live/api/v1/payments/{transaction_uuid}/refundCorpo opcional { "amount": 50.00 } para estorno parcial; sem ele o estorno é total. A taxa da venda não volta. O valor sai primeiro das parcelas ainda não liberadas e depois do saldo. Resposta: refunded_amount, full e status. Também enviamos o webhook transaction.refunded.
Chargeback: se o cliente contestar a compra no banco, as parcelas futuras são canceladas, o que já foi liberado é debitado do saldo e você recebe transaction.chargeback.
Receber
Pix convertido em USDT
O cliente paga em Pix normalmente e você recebe USDT direto na sua carteira (BSC, Polygon ou Tron), assim que o Pix é confirmado.
- 1. Cadastre a carteira no painel em Cripto → Vendas Pix em USDT (pede PIN e 2FA). Carteira nova tem um período de segurança antes do primeiro envio.
- 2. Envie
"settlement": "usdt"emPOST /payments/pix(ou ligue o recebimento em USDT para todas as vendas no painel e use"brl"para exceções). - 3. Pago o Pix, o valor líquido é convertido na cotação do momento. Valores abaixo do mínimo de envio acumulam e seguem junto com a próxima venda.
{
"amount": 500.00,
"payer_name": "Joao Silva",
"payer_email": "[email protected]",
"payer_cpf": "52998224725",
"settlement": "usdt"
}Sem carteira cadastrada a resposta é 422. Na consulta GET /payments/{uuid}, o bloco settlement mostra status, amount_usdt, network e tx_hash. Webhooks: crypto_settlement.completed quando o USDT chega e crypto_settlement.failed se a conversão falhar (o valor fica em reais no seu saldo).
Receber
Split de pagamento
Divida uma cobrança Pix com outros lojistas cadastrados na Eleva Payments. Quando o Pix é pago, cada parceiro recebe o percentual dele e você fica com o restante.
{
"amount": 200.00,
"payer_name": "Maria Souza",
"payer_email": "[email protected]",
"payer_cpf": "52998224725",
"splits": [
{ "email": "[email protected]", "percentage": 10 },
{ "email": "[email protected]", "percentage": 5.5 }
]
}- •
emailprecisa ser de uma conta existente na plataforma; cada e-mail só uma vez. - •
percentagede 0,01 a 100; a soma não pode passar de 100%. - • Formato antigo para um único parceiro continua aceito:
split_email+split_percentage. - • Erros de split voltam como 422 no campo
splits.
Receber
Consultar e listar
Consultar uma cobrança pendente também confere o status na adquirente na hora, então serve como alternativa (ou reforço) ao webhook.
Uma cobrança
https://app.elevapayments.live/api/v1/payments/{transaction_uuid}curl "https://app.elevapayments.live/api/v1/payments/9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "X-Client-ID: SEU_CLIENT_ID" \
-H "Accept: application/json"{
"success": true,
"data": {
"uuid": "9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10",
"amount": "49.90",
"fee": "1.50",
"amount_net": "48.40",
"type": "pix",
"status": "completed",
"created_at": "2026-10-01T17:30:00.000000Z",
"updated_at": "2026-10-01T17:31:12.000000Z"
}
}Vendas no cartão trazem também card (bandeira, final, parcelas, valor estornado) e release_schedule. Vendas em USDT trazem settlement. Existe também GET /transactions/{uuid}, com os mesmos campos da listagem.
Listar transações
https://app.elevapayments.live/api/v1/transactions?status=completed&start_date=2026-10-01&per_page=50| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
status | string | Não | Filtra por status (veja Status). |
type | string | Não | "pix" ou "credit" (cartão). |
start_date / end_date | date | Não | Período pela data de criação (AAAA-MM-DD). |
page | integer | Não | Página (padrão 1). |
per_page | integer | Não | Itens por página, 1 a 100 (padrão 20). |
{
"success": true,
"data": [
{
"uuid": "9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10",
"amount": 49.9, "amount_gross": 49.9, "amount_net": 48.4, "fee": 1.5,
"type": "pix", "status": "completed", "payment_method": "pix", "settlement": "brl",
"description": "Pedido #1042",
"payer": { "name": "Maria Souza", "email": "[email protected]", "document": "52998224725" },
"created_at": "2026-10-01T17:30:00-03:00", "paid_at": "2026-10-01T17:31:12-03:00"
}
],
"pagination": { "current_page": 1, "last_page": 4, "per_page": 20, "total": 71 }
}Pagar
Saque via Pix
Transfere o seu saldo para uma chave Pix. Você informa quanto quer que chegue; a taxa é somada e debitada do saldo.
https://app.elevapayments.live/api/v1/cashout/pix| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
amount | decimal | Sim | Valor líquido que deve chegar na chave (mínimo R$ 20,00). |
pix_key | string | Sim | Chave Pix de destino: CPF, CNPJ, e-mail, telefone (+55...) ou aleatória. |
curl -X POST "https://app.elevapayments.live/api/v1/cashout/pix" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "X-Client-ID: SEU_CLIENT_ID" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "amount": 150.00, "pix_key": "[email protected]" }'{
"success": true,
"message": "Saque criado com sucesso. Aguardando aprovação manual.",
"withdrawal": {
"id": 3187,
"amount": 150.00,
"amount_gross": 152.50,
"fee": 2.50,
"status": "pending",
"pix_key": "[email protected]"
}
}Manual ou automático
Cada credencial tem um modo de saque. No manual o saque fica pending até a aprovação da equipe. No automático ele é enviado na hora, desde que a chamada venha de um IP cadastrado na credencial e com o header X-Client-ID.
Segurança
Chamadas de saque feitas por ferramentas de teste (Postman, Insomnia, Thunder Client) são recusadas com 403: faça do seu servidor. Saldo insuficiente volta como 400 com o valor necessário. Acompanhe o resultado pelos webhooks withdrawal.completed e withdrawal.failed.
Notificações
Webhooks
Enviamos um POST em JSON para a URL cadastrada na credencial sempre que algo acontece. Cada credencial ativa com URL recebe os eventos da conta.
Requisitos da URL
HTTPS em domínio público (porta 443 ou 8443). Redirecionamentos não são seguidos.
Resposta
Responda qualquer 2xx em até 10 segundos. Processe o evento depois (fila).
Reenvio
Se o seu servidor não responder ou devolver 5xx, tentamos de novo a cada 1 minuto, até 3 tentativas. Respostas 4xx não são reenviadas.
Requisição enviada
POST /seu-endpoint HTTP/1.1
Content-Type: application/json
User-Agent: Eleva Payments-Webhook/1.0
X-Webhook-Id: 1b4e28ba-2fa1-4d3b-a3f5-ef19b5a7633b
X-Webhook-Event: deposit.completed
X-Webhook-Timestamp: 1790871072
X-Webhook-Signature-V2: t=1790871072,v1=5f2b0c9e...a41
X-Webhook-Signature: 8c1d2e3f...9b0
{
"id": "1b4e28ba-2fa1-4d3b-a3f5-ef19b5a7633b",
"event": "deposit.completed",
"data": {
"transaction_uuid": "9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10",
"status": "completed",
"type": "pix",
"payment_method": "pix",
"amount": 49.9,
"amount_gross": 49.9,
"amount_net": 48.4,
"fee": 1.5,
"settlement": "brl",
"description": "Pedido #1042",
"payer": { "name": "Maria Souza", "email": "[email protected]", "document": "52998224725" },
"created_at": "2026-10-01T14:30:00-03:00",
"paid_at": "2026-10-01T14:31:12-03:00"
},
"created_at": "2026-10-01T14:31:12-03:00"
}Headers
| Header | Conteúdo |
|---|---|
X-Webhook-Id | ID único do evento (o mesmo do campo "id"). Igual em todas as tentativas: use para não processar duas vezes. |
X-Webhook-Event | Nome do evento, ex.: deposit.completed. |
X-Webhook-Timestamp | Momento do envio (Unix, segundos). |
X-Webhook-Signature-V2 | t={timestamp},v1={HMAC-SHA256 de "timestamp.corpo"}. Recomendado. |
X-Webhook-Signature | HMAC-SHA256 do corpo (formato antigo, mantido por compatibilidade). |
Eventos
| Evento | Quando | Principais campos em data |
|---|---|---|
deposit.completed |
Cobrança paga (Pix ou cartão aprovado). É o evento para liberar o pedido. | transaction_uuid, status, amount, amount_net, fee, payment_method, settlement, payer, paid_at |
transaction.waiting_payment |
A adquirente informou que a cobrança aguarda pagamento. | transaction_uuid, status, amount |
transaction.failed |
Cobrança expirou, foi cancelada ou recusada. | transaction_uuid, status, reason |
transaction.refunded |
Venda no cartão estornada (total ou parcial). | transaction_uuid, refund_amount, full_refund, refunded_amount |
transaction.chargeback |
Pagador contestou (MED no Pix / chargeback no cartão). | transaction_uuid, chargeback_amount |
transaction.completed |
Status alterado para pago manualmente pela equipe (raro). Trate igual a deposit.completed. | transaction_uuid, status, amount_net |
withdrawal.pending |
Saque criado, aguardando processamento. | withdrawal_id, amount, status |
withdrawal.completed |
Saque pago. | withdrawal_id, amount, status |
withdrawal.failed |
Saque recusado/falhou; o valor voltou ao saldo. | withdrawal_id, status, amount, refunded_to_balance |
pix_payment.pending |
Pagamento Pix para terceiros criado (pode ir para análise). | payment_id, amount, status |
pix_payment.completed |
Pagamento Pix para terceiros confirmado. | payment_id, amount, recipient_name |
pix_payment.failed |
Pagamento Pix para terceiros falhou; valor devolvido. | withdrawal_id, status, refunded_to_balance |
crypto_settlement.completed |
USDT entregue na sua carteira. | conversion_id, amount_brl, amount_crypto, network, tx_hash |
crypto_settlement.failed |
Conversão em USDT falhou; o valor ficou em reais no saldo. | withdrawal_id, status, refunded_to_balance |
checkout.order_paid |
Pedido do checkout próprio pago (produto digital entregue). | order_id, product_id, amount, method, buyer, transaction_uuid |
Eventos de cobrança (deposit.*, transaction.*) trazem sempre o bloco completo da transação: transaction_uuid, status, type, payment_method, amount, amount_net, fee, settlement, description, payer, card (no cartão), created_at, paid_at. Novos campos podem ser acrescentados a qualquer momento: ignore os que não conhecer.
Boas práticas
- • Valide a assinatura antes de qualquer coisa.
- • Guarde o
iddos eventos processados: o mesmo evento pode chegar mais de uma vez. - • A ordem de chegada não é garantida. Em caso de dúvida, consulte
GET /payments/{uuid}: a consulta é a fonte da verdade. - • Confira o valor (
amount) com o do seu pedido antes de liberar.
Notificações
Validar a assinatura
A assinatura prova que o webhook saiu da Eleva Payments e não foi alterado. O segredo é o token da credencial.
- 1. Leia o corpo cru da requisição (antes de converter o JSON; qualquer espaço diferente muda a assinatura).
- 2. Separe
tev1do headerX-Webhook-Signature-V2. - 3. Calcule
HMAC-SHA256(token, t + "." + corpo)em hexadecimal e compare comv1em tempo constante. - 4. Recuse se
ttiver mais de 5 minutos de diferença do seu relógio (protege contra reenvio de mensagens antigas).
<?php
// Laravel: Route::post('/webhooks/eleva', [ElevaWebhookController::class, '__invoke']);
// PHP puro: use file_get_contents('php://input') como $body e $_SERVER['HTTP_X_WEBHOOK_SIGNATURE_V2'].
$secret = getenv('ELEVA_API_TOKEN'); // o mesmo token usado na API
$body = file_get_contents('php://input'); // corpo CRU, antes de qualquer json_decode
$header = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE_V2'] ?? '';
parse_str(str_replace(',', '&', $header), $sig); // ['t' => '...', 'v1' => '...']
$expected = hash_hmac('sha256', ($sig['t'] ?? '') . '.' . $body, $secret);
if (empty($sig['v1']) || !hash_equals($expected, $sig['v1']) || abs(time() - (int) $sig['t']) > 300) {
http_response_code(401);
exit('assinatura inválida');
}
$event = json_decode($body, true);
// Idempotência: o mesmo evento pode chegar mais de uma vez.
if (jaProcessado($event['id'])) { http_response_code(200); exit; }
if ($event['event'] === 'deposit.completed') {
liberarPedido($event['data']['transaction_uuid'], $event['data']['amount']);
}
marcarProcessado($event['id']);
http_response_code(200);// Node.js + Express: use o corpo CRU (express.raw), não o JSON já convertido.
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhooks/eleva', express.raw({ type: 'application/json' }), (req, res) => {
const secret = process.env.ELEVA_API_TOKEN;
const body = req.body.toString('utf8');
const header = req.get('X-Webhook-Signature-V2') || '';
const sig = Object.fromEntries(header.split(',').map(p => p.split('=')));
const expected = crypto.createHmac('sha256', secret).update(`${sig.t}.${body}`).digest('hex');
const valid = sig.v1 && sig.v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected));
if (!valid || Math.abs(Date.now() / 1000 - Number(sig.t)) > 300) {
return res.status(401).send('assinatura inválida');
}
const event = JSON.parse(body);
res.sendStatus(200); // responda rápido; processe em seguida (fila)
if (event.event === 'deposit.completed') {
liberarPedido(event.data.transaction_uuid, event.id);
}
});# Python + Flask
import hmac, hashlib, json, os, time
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["ELEVA_API_TOKEN"].encode()
@app.post("/webhooks/eleva")
def eleva_webhook():
body = request.get_data() # bytes crus
parts = dict(p.split("=", 1) for p in request.headers.get("X-Webhook-Signature-V2", "").split(",") if "=" in p)
expected = hmac.new(SECRET, f"{parts.get('t', '')}.".encode() + body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, parts.get("v1", "")) or abs(time.time() - int(parts.get("t", 0))) > 300:
abort(401)
event = json.loads(body)
if event["event"] == "deposit.completed":
liberar_pedido(event["data"]["transaction_uuid"], event["id"])
return "", 200Integração antiga: X-Webhook-Signature = HMAC-SHA256(token, corpo). Continua sendo enviado, mas não protege contra reenvio; migre para a v2.
Referência
Status
Cobranças (Pix e cartão)
| Status | Significado | Final? |
|---|---|---|
| pending | Cobrança criada, aguardando o pagamento. | Não |
| waiting_payment | Aguardando pagamento (algumas adquirentes informam este estado). | Não |
| processing | Cartão em conferência na adquirente (resposta sem confirmação). Consulte de novo em instantes. | Não |
| completed | Pago. O valor líquido entrou (ou vai entrar, no cartão) no seu saldo. | Sim |
| failed | Recusado ou com falha na adquirente. | Sim |
| cancelled | Expirou sem pagamento ou foi cancelado. | Sim |
| refunded | Estornado integralmente. | Sim |
| chargeback | Contestação do pagador (MED no Pix, chargeback no cartão). | Sim |
| mediation | Em análise de contestação. | Não |
Um Pix expirado (cancelled) que for pago mesmo assim é reaberto e passa para completed, com webhook deposit.completed. No cartão, a resposta usa approved/declined e a transação fica completed/failed.
Saques
| Status | Significado |
|---|---|
| pending | Criado e aguardando aprovação manual (modo manual) ou envio. |
| processing | Enviado ao banco; aguardando confirmação. |
| paid | Pix enviado com sucesso. |
| rejected | Recusado (chave inválida, análise, adquirente). O valor volta ao saldo. |
| failed | Falhou no envio. O valor volta ao saldo. |
| cancelled | Cancelado. O valor volta ao saldo. |
Referência
Erros
Todo erro volta em JSON com success: false e uma message em português, que pode ser mostrada ao seu usuário.
{
"success": false,
"message": "O campo payer email deve ser um endereço de e-mail válido.",
"errors": {
"payer_email": ["O campo payer email deve ser um endereço de e-mail válido."]
}
}{ "success": false, "message": "Credenciais de API inválidas ou expiradas" }| Código | Nome | O que fazer |
|---|---|---|
| 200 | OK | Consulta ou ação concluída. |
| 201 | Created | Cobrança criada (Pix) ou cartão aprovado. |
| 202 | Accepted | Cartão aguardando autenticação 3DS ou em conferência. Não é aprovação. |
| 400 | Bad Request | Operação não pôde ser feita (saldo insuficiente, adquirente indisponível). |
| 401 | Unauthorized | Token ausente, inválido ou expirado. |
| 402 | Payment Required | Cartão recusado pelo banco emissor. |
| 403 | Forbidden | Conta bloqueada, KYC pendente, IP fora da lista ou recurso não liberado. |
| 404 | Not Found | Transação não existe ou não pertence a esta conta. |
| 422 | Unprocessable Entity | Campos inválidos. O corpo traz "errors" por campo. |
| 429 | Too Many Requests | Mais de 120 requisições por minuto neste token. Respeite o header Retry-After. |
| 500 | Server Error | Erro interno ou da adquirente. Consulte a transação antes de tentar de novo. |
Quando tentar de novo
Pode repetir: 429 (depois do Retry-After), 500 e erros de rede, com espera crescente (2s, 4s, 8s). Na criação de cobrança, consulte antes para não duplicar. Não repita sem corrigir: 400, 401, 403, 404, 422 e 402.
Referência
Exemplos completos
Cliente pronto para criar um Pix e consultar o status. Copie, ajuste as variáveis de ambiente e rode.
<?php
// Cliente mínimo em PHP (cURL nativo). Guarde token e client id em variáveis de ambiente.
final class ElevaClient
{
public function __construct(
private string $token,
private string $clientId,
private string $baseUrl = 'https://app.elevapayments.live/api/v1',
) {}
public function request(string $method, string $path, ?array $body = null): array
{
$ch = curl_init($this->baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->token,
'X-Client-ID: ' . $this->clientId,
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => $body ? json_encode($body) : null,
]);
$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$json = json_decode((string) $raw, true) ?? [];
if ($status >= 400 && $status !== 402) {
throw new RuntimeException($json['message'] ?? "Erro HTTP $status", $status);
}
return $json;
}
public function createPix(float $amount, string $name, string $email, string $cpf, string $description = ''): array
{
return $this->request('POST', '/payments/pix', [
'amount' => round($amount, 2),
'payer_name' => $name,
'payer_email' => $email,
'payer_cpf' => preg_replace('/\D/', '', $cpf),
'description' => $description,
])['data'];
}
public function payment(string $uuid): array
{
return $this->request('GET', '/payments/' . $uuid)['data'];
}
}
$eleva = new ElevaClient(getenv('ELEVA_API_TOKEN'), getenv('ELEVA_CLIENT_ID'));
$pix = $eleva->createPix(49.90, 'Maria Souza', '[email protected]', '529.982.247-25', 'Pedido #1042');
// Salve $pix['transaction_uuid'] junto do pedido e mostre $pix['qr_code_base64'] / $pix['pix_code'].// Node.js 18+ (fetch nativo)
const BASE = 'https://app.elevapayments.live/api/v1';
const headers = {
Authorization: `Bearer ${process.env.ELEVA_API_TOKEN}`,
'X-Client-ID': process.env.ELEVA_CLIENT_ID,
'Content-Type': 'application/json',
Accept: 'application/json',
};
async function eleva(method, path, body) {
const res = await fetch(BASE + path, { method, headers, body: body ? JSON.stringify(body) : undefined });
const json = await res.json().catch(() => ({}));
if (!res.ok && res.status !== 402) {
const err = new Error(json.message || `HTTP ${res.status}`);
err.status = res.status; err.errors = json.errors;
throw err;
}
return json;
}
const { data: pix } = await eleva('POST', '/payments/pix', {
amount: 49.90,
payer_name: 'Maria Souza',
payer_email: '[email protected]',
payer_cpf: '52998224725',
description: 'Pedido #1042',
});
console.log(pix.transaction_uuid, pix.pix_code);
const { data: status } = await eleva('GET', `/payments/${pix.transaction_uuid}`);
console.log(status.status); // pending | completed | cancelled ...# Python 3 + requests
import os, requests
BASE = "https://app.elevapayments.live/api/v1"
session = requests.Session()
session.headers.update({
"Authorization": f"Bearer {os.environ['ELEVA_API_TOKEN']}",
"X-Client-ID": os.environ["ELEVA_CLIENT_ID"],
"Accept": "application/json",
})
def eleva(method, path, **kwargs):
r = session.request(method, BASE + path, timeout=30, **kwargs)
data = r.json() if r.content else {}
if r.status_code >= 400 and r.status_code != 402:
raise RuntimeError(f"{r.status_code}: {data.get('message')} {data.get('errors', '')}")
return data
pix = eleva("POST", "/payments/pix", json={
"amount": 49.90,
"payer_name": "Maria Souza",
"payer_email": "[email protected]",
"payer_cpf": "52998224725",
"description": "Pedido #1042",
})["data"]
print(pix["transaction_uuid"], pix["pix_code"])
print(eleva("GET", f"/payments/{pix['transaction_uuid']}")["data"]["status"])curl -X POST "https://app.elevapayments.live/api/v1/payments/pix" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "X-Client-ID: SEU_CLIENT_ID" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"amount": 49.90,
"payer_name": "Maria Souza",
"payer_email": "[email protected]",
"payer_cpf": "52998224725",
"description": "Pedido #1042"
}'curl "https://app.elevapayments.live/api/v1/payments/9d3f1c1e-6a2b-4d7e-9a51-2f0c8b7e4a10" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "X-Client-ID: SEU_CLIENT_ID" \
-H "Accept: application/json"curl -X POST "https://app.elevapayments.live/api/v1/cashout/pix" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "X-Client-ID: SEU_CLIENT_ID" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "amount": 150.00, "pix_key": "[email protected]" }'Para receber os avisos, veja o código de . Plataformas prontas (Shopify, WooCommerce) têm integração no painel, em Integrações.
Referência
Checklist de produção
Confira antes de abrir a integração para os seus clientes.
Pronto para integrar?
Crie sua conta, aprove o cadastro e gere sua chave de API no painel.