Receber webhooks
A Avexus envia um POST para os endpoints registrados sempre que uma cobrança,
um saque ou uma disputa muda de estado. Para registrar, testar e remover
endpoints, veja a API de webhooks.
Eventos
Seção intitulada “Eventos”| Evento (assinatura) | Header x-webhook-event |
Quando dispara |
|---|---|---|
transaction |
TRANSACTION |
Mudanças de status de cobrança (CONFIRMED, FAILED, EXPIRED, REFUNDED…) |
withdraw |
WITHDRAW |
Mudanças de status de saque (PROCESSING, CONFIRMED, FAILED…) |
dispute |
DISPUTE |
Abertura e atualização de disputas (MED) |
Headers de cada entrega
Seção intitulada “Headers de cada entrega”| Header | Descrição |
|---|---|
x-webhook-signature |
HMAC SHA256 do corpo, em hexadecimal |
x-webhook-event |
Tipo do evento, em maiúsculas |
x-user-reference |
Identificador da sua conta na Avexus |
Content-Type |
application/json |
User-Agent |
Avexus-Webhooks/1.0 |
Payloads
Seção intitulada “Payloads”Cobrança
Seção intitulada “Cobrança”{ "data": { "magic_id": "rU1w01Ct6QL3", "amount": 197.0, "currency": "BRL", "status": "CONFIRMED", "decline_reason": null, "description": "Mentoria Pro", "payment_method": "Pix", "qr_code": "00020101021126700014br.gov.bcb.pix...", "end_to_end": "E60789431202607241838V2JYEP7TUZ6", "external_ref": "pedido_1042", "requester": { "name": "Maria Souza", "email": "maria@example.com", "phone": "11999999999", "document": "12468239008" }, "movement": { "payer": { "name": "Maria Souza", "document": "12468239008", "bank": "BANCO INTER S.A.", "agency": "0001", "account": "123456-7" }, "payee": { "name": "Sua Loja LTDA", "document": "12345678000190", "bank": "BANCO INTER S.A.", "agency": "0001", "account": "765432-1" } }, "created_at": "2026-07-24T18:38:25.688Z", "updated_at": "2026-07-24T18:41:06.467Z" }, "event": "TRANSACTION"}{ "data": { "magic_id": "wth_03UdoKvLNLHg", "amount": 300.0, "currency": "BRL", "status": "CONFIRMED", "fee": 0.15, "decline_reason": null, "description": "Repasse semanal", "transfer_method": "Pix", "end_to_end": "E60789431202607241838V2JYEP7TUZ6", "external_ref": "repasse_2026_30", "movement": { "payer": { "name": "Sua Loja LTDA", "document": "12345678000190", "bank": "BANCO INTER S.A.", "agency": "0001", "account": "765432-1" }, "payee": { "name": "Maria Souza", "document": "95876150096", "bank": "BANCO INTER S.A.", "agency": "0001", "account": "123456-7" } }, "created_at": "2026-07-24T20:44:25.618Z", "updated_at": "2026-07-24T20:46:11.902Z" }, "event": "WITHDRAW"}Verificação da assinatura
Seção intitulada “Verificação da assinatura”A assinatura é o HMAC SHA256 do corpo bruto da requisição, em hexadecimal,
usando o secret (whsec_…) devolvido ao registrar o
webhook.
const crypto = require('crypto');const express = require('express');
const app = express();
// express.raw() preserva os bytes originais — express.json() os perderia.app.post( '/webhooks/avexus', express.raw({ type: 'application/json' }), (req, res) => { const assinatura = req.get('x-webhook-signature') ?? ''; const esperada = crypto .createHmac('sha256', process.env.AVEXUS_WEBHOOK_SECRET) .update(req.body) .digest('hex');
const a = Buffer.from(assinatura, 'utf8'); const b = Buffer.from(esperada, 'utf8'); if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) { return res.sendStatus(401); }
const evento = JSON.parse(req.body.toString('utf8')); // processe de forma idempotente e responda 2xx rápido res.sendStatus(200); },);import hashlibimport hmacimport os
from flask import Flask, request
app = Flask(__name__)SEGREDO = os.environ['AVEXUS_WEBHOOK_SECRET'].encode()
@app.post('/webhooks/avexus')def receber(): assinatura = request.headers.get('x-webhook-signature', '') esperada = hmac.new(SEGREDO, request.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(assinatura, esperada): return '', 401
evento = request.get_json() # processe de forma idempotente e responda 2xx rápido return '', 200$assinatura = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';$corpo = file_get_contents('php://input');$esperada = hash_hmac('sha256', $corpo, getenv('AVEXUS_WEBHOOK_SECRET'));
if (!hash_equals($esperada, $assinatura)) { http_response_code(401); exit;}
$evento = json_decode($corpo, true);// processe de forma idempotente e responda 2xx rápidohttp_response_code(200);Entrega e reentrega
Seção intitulada “Entrega e reentrega”| Regra | Valor |
|---|---|
| Resposta considerada sucesso | Qualquer 2xx |
| Timeout da requisição | 10 segundos |
| Tentativas | Até 8 |
| Espera entre tentativas | Backoff exponencial a partir de 5 s, teto de 10 min, com jitter |
| Depois da última tentativa | A entrega vai para a dead-letter e pode ser reenviada pelo operador |
| Endpoint removido ou inativo | A entrega é descartada na hora, sem retentativa |
Idempotência no seu lado
Seção intitulada “Idempotência no seu lado”A mesma notificação pode chegar mais de uma vez (retentativa de rede, reenvio
manual, resend=true). Deixe o handler idempotente:
- Use o
magic_id— ou o parmagic_id+status— como chave de deduplicação. - Se o evento já foi processado, responda
2xxe não repita os efeitos colaterais. - Concilie pelo
external_refque você mesmo enviou.
Reenviar uma entrega
Seção intitulada “Reenviar uma entrega”Perdeu uma notificação? A consulta com resend=true reenfileira o webhook dos
registros retornados:
curl --request GET \ --url 'https://api.avexus.app/api/transactions?magic_id=rU1w01Ct6QL3&resend=true' \ --header 'x-api-key: <API_KEY>' \ --header 'x-token: <TOKEN>' \ --header 'x-timezone: America/Sao_Paulo'curl --request GET \ --url 'https://api.avexus.app/api/withdrawals?magic_id=wth_03UdoKvLNLHg&resend=true' \ --header 'x-api-key: <API_KEY>' \ --header 'x-token: <TOKEN>' \ --header 'x-timezone: America/Sao_Paulo'Para exercitar a integração sem esperar um pagamento, use a entrega de teste:
POST /api/webhooks/{magic_id}/test.
Veja também
Seção intitulada “Veja também”- API de webhooks — registrar, testar, listar e remover.
- Status de transação e Status de saque.
- Ambiente sandbox — provoque cada transição de propósito.
