API de Webhooks
Os webhooks permitem que sua aplicação receba notificações HTTP em tempo real quando eventos ocorrem na sua loja Mercozy. Em vez de consultar a API, registre uma URL e o Mercozy enviará automaticamente os dados do evento.
Início rápido
Comece em 3 passos:
Passo 1: Registre seu endpoint
Obtenha sua chave API em Configurações > Integração > Chaves API. Permissão de administrador necessária. O segredo de assinatura do webhook (whsec_xxx) é gerado automaticamente ao criar um endpoint e exibido apenas uma vez.
curl -X POST "https://api.mercozy.com/api/v1/external/webhooks" \
-H "X-API-Key: mk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "My ERP Integration",
"url": "https://your-app.com/webhooks/mercozy",
"events": ["order.created", "order.cancelled", "payment.received"]
}'Passo 2: Processe os eventos recebidos
app.post('/webhooks/mercozy', (req, res) => {
// 1. Verify signature (see below)
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// 2. Process the event
const { type, data } = req.body;
switch (type) {
case 'order.created':
syncOrderToERP(data);
break;
case 'payment.received':
updateAccountingSystem(data);
break;
}
// 3. Respond quickly with 200
res.status(200).json({ received: true });
});Passo 3: Teste seu endpoint
curl -X POST "https://api.mercozy.com/api/v1/external/webhooks/{id}/test" \
-H "X-API-Key: mk_live_your_key_here"Endpoints
/webhooks
Liste todos os endpoints de webhook registrados.
/webhooks
Registre um novo endpoint de webhook para receber notificacoes de eventos.
/webhooks/:id
Atualize um endpoint de webhook existente (URL, eventos ou status ativo).
/webhooks/:id
Exclua um endpoint de webhook. Os eventos nao serao mais entregues.
Referencia de Campos
| Campo | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
id | string | Nao | Identificador unico do webhook (somente leitura) |
name | string | Sim | Um nome descritivo para este endpoint |
url | string | Sim | URL do endpoint HTTPS para receber eventos de webhook |
events | string[] | Sim | Array de tipos de evento para assinar |
secret | string | Nao | Segredo de assinatura para verificacao de payload (somente leitura, gerado na criacao) |
isActive | boolean | Nao | Se o webhook esta ativo (padrao: true) |
createdAt | datetime | Nao | Timestamp ISO 8601 (somente leitura) |
Tipos de Evento Disponiveis
O Mercozy suporta 18 tipos de eventos de webhook em 6 categorias. Inscreva-se apenas nos eventos que você precisa.
Pedidos
- order.created
Disparado quando um novo pedido é realizado
- order.updated
Disparado quando os detalhes do pedido são modificados
- order.cancelled
Disparado quando um pedido é cancelado
- order.completed
Disparado quando um pedido é marcado como concluído
- order.status_changed
Disparado em qualquer mudança de status do pedido
Pagamentos
- payment.received
Disparado quando o pagamento é capturado ou cobrado na entrega
- payment.refunded
Disparado quando um pagamento é reembolsado ou cancelado
Produtos
- product.created
Disparado quando um novo produto é adicionado
- product.updated
Disparado quando os detalhes do produto mudam
- product.deleted
Disparado quando um produto é excluído
Estoque
- stock.low
Disparado quando o estoque fica abaixo do limite
- stock.updated
Disparado quando a quantidade em estoque muda
Clientes
- customer.created
Disparado quando um novo cliente é registrado
- customer.updated
Disparado quando as informações do cliente são atualizadas
Entregas
- delivery.batch_started
Disparado quando um lote de entregas é despachado
- delivery.batch_completed
Disparado quando todas as paradas do lote são concluídas
- delivery.completed
Disparado quando uma entrega individual é concluída
- delivery.failed
Disparado quando uma tentativa de entrega falha
Payload do Webhook
Cada entrega de webhook inclui o tipo de evento, timestamp e os dados do recurso relevante.
Dados do evento de pedido
{
"id": "evt_clx1abc2def3",
"type": "order.created",
"timestamp": "2026-03-19T10:30:00Z",
"data": {
"id": "clx9order123",
"orderNumber": "ORD-1042",
"status": "PENDING",
"total": 4999,
"currency": "USD"
}
}Dados do evento de pagamento
{
"id": "evt_clx2pay4ghi5",
"type": "payment.received",
"timestamp": "2026-03-19T10:35:00Z",
"data": {
"orderId": "clx9order123",
"orderNumber": "ORD-1042",
"amount": 4999,
"currency": "USD",
"paymentMethod": "CARD",
"status": "CAPTURED"
}
}Dados do evento de produto
{
"id": "evt_clx3prod6jkl",
"type": "product.created",
"timestamp": "2026-03-19T11:00:00Z",
"data": {
"id": "clx9prod789",
"name": "Organic Coffee Beans",
"sku": "COF-001",
"price": 1299,
"status": "ACTIVE"
}
}Dados do evento de entrega
{
"id": "evt_clx4del7mno",
"type": "delivery.completed",
"timestamp": "2026-03-19T14:22:00Z",
"data": {
"orderId": "clx9order123",
"orderNumber": "ORD-1042"
}
}Cabeçalhos HTTP
Cada requisição de webhook inclui os seguintes cabeçalhos:
| Campo | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
Content-Type | string | Sim | application/json |
X-Webhook-Signature | string | Sim | Assinatura HMAC-SHA256: sha256={resumo_hexadecimal} |
X-Webhook-Timestamp | string | Sim | Timestamp Unix em milissegundos |
X-Webhook-ID | string | Sim | ID de evento único para deduplicação |
User-Agent | string | Sim | Mercozy-Webhook/1.0 (+https://www.mercozy.com/docs/webhooks) |
Verificacao de Assinatura
Cada webhook inclui um cabeçalho X-Webhook-Signature contendo uma assinatura HMAC-SHA256. Sempre verifique esta assinatura antes de processar o evento para garantir que a requisição veio do Mercozy.
Node.js
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, timestamp, secret) {
// Signature is computed over "timestamp.body"
const message = timestamp + '.' + rawBody;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express middleware
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-webhook-signature'];
const ts = req.headers['x-webhook-timestamp'];
if (!verifyWebhook(req.body, sig, ts, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Process event...
res.status(200).json({ received: true });
});Python
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
# Signature is computed over "timestamp.body"
message = (timestamp + '.').encode() + payload
expected = 'sha256=' + hmac.new(
secret.encode(),
message,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# Flask example
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
sig = request.headers.get('X-Webhook-Signature')
ts = request.headers.get('X-Webhook-Timestamp')
if not verify_webhook(request.data, sig, ts, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.get_json()
# Process event...
return {'received': True}, 200PHP
<?php
function verifyWebhook(string $payload, string $signature, string $timestamp, string $secret): bool {
// Signature is computed over "timestamp.body"
$message = $timestamp . '.' . $payload;
$expected = 'sha256=' . hash_hmac('sha256', $message, $secret);
return hash_equals($expected, $signature);
}
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
if (!verifyWebhook($payload, $signature, $timestamp, $webhookSecret)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
// Process event...
http_response_code(200);
echo json_encode(['received' => true]);Política de retentativas
Se seu endpoint retornar um código de status diferente de 2xx ou expirar (10 segundos), o Mercozy retentará a entrega com backoff exponencial:
| Campo | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
Tentativa 1 | Nao | Imediato | |
Tentativa 2 | Nao | Após ~1s | |
Tentativa 3 | Nao | Após ~4s |
Após 3 tentativas com falha, a entrega é marcada como falha. Você pode retentar manualmente pelo painel ou pela API.
Melhores práticas
Responda em menos de 5 segundos — Retorne status 200 imediatamente e processe o evento de forma assíncrona. O timeout do Mercozy é de 10 segundos.
Sempre verifique assinaturas — Verifique o cabeçalho X-Webhook-Signature antes de processar qualquer evento para evitar requisições falsificadas.
Trate duplicatas (idempotência) — Use o cabeçalho X-Webhook-ID para deduplicar eventos. Armazene os IDs processados e pule os que já foram tratados.
Use endpoints HTTPS — O Mercozy exige URLs HTTPS em produção para proteger os dados do webhook em trânsito.
Registre e monitore — Registre todos os webhooks recebidos e monitore falhas. Use a API de logs de entrega para verificar o status.