Eventos
Webhooks
O Mapogos envia um POST para a URL do seu sistema quando um evento acontece — sem você precisar consultar a API o tempo todo.
Configurando
- Publique no seu sistema um endereço https público que aceite
POSTcom JSON. - No painel: API do Sistema → Webhooks → Novo webhook. Escolha a chave, informe a URL e marque os eventos (só aparecem os de módulos que a chave pode ler).
- Copie o segredo do webhook (exibido uma vez) e guarde em
MAPOGOS_WEBHOOK_SECRET. - Use o botão Testar para receber o evento
teste.ping.
Eventos disponíveis
| Evento | Quando acontece | Exige leitura em |
|---|---|---|
locacao.criada | Novo contrato de locação ou venda criado. | Locações |
locacao.encerrada | Contrato encerrado/finalizado. | Locações |
pagamento.criado | Nova cobrança gerada. | Pagamentos |
pagamento.confirmado | Cobrança baixada como paga (PIX, manual ou banco). | Pagamentos |
pagamento.vencido | Cobrança pendente passou do vencimento (disparado no dia seguinte ao vencimento). | Pagamentos |
pagamento.cancelado | Cobrança cancelada. | Pagamentos |
veiculo.criado | Veículo cadastrado. | Veículos |
veiculo.bloqueado | Rastreador passou para bloqueado. | Veículos |
veiculo.desbloqueado | Rastreador passou para desbloqueado. | Veículos |
cliente.criado | Cliente cadastrado. | Clientes |
cliente.atualizado | Cadastro do cliente alterado. | Clientes |
os.criada | Ordem de serviço aberta. | Ordens de Serviço |
os.concluida | Ordem de serviço concluída. | Ordens de Serviço |
vistoria.concluida | Vistoria validada. | Vistorias |
acordo.criado | Acordo/parcelamento criado. | Acordos |
acordo.quitado | Acordo quitado. | Acordos |
acordo.parcela_paga | Parcela de acordo paga. | Acordos |
multa.criada | Multa registrada para um veículo. | Multas |
Formato do aviso
| Cabeçalho | Conteúdo |
|---|---|
X-Mapogos-Evento | Nome do evento |
X-Mapogos-Evento-Id | Id único do evento (use para não processar duas vezes) |
X-Mapogos-Entrega | Número da entrega |
X-Mapogos-Timestamp | Momento do envio (epoch) |
X-Mapogos-Assinatura | sha256= + HMAC-SHA256 de timestamp.corpo |
O campo dados traz o registro no mesmo formato da API, respeitando as carteiras e a permissão LGPD da chave.
Corpo do POST enviado ao seu sistema200 OK
{
"id": "evt_88231_1a2b3c",
"evento": "pagamento.confirmado",
"modulo": "pagamentos",
"criado_em": "2026-10-08T14:30:00-03:00",
"ambiente": "live",
"dados": {
"id": 1024,
"rental_id": 512,
"amount": "150.00",
"original_amount": "150.00",
"status": "pago",
"method": "pix",
"due_date": "2026-10-15",
"paid_at": "2026-10-08T14:30:00-03:00",
"note": "Aluguel semanal"
}
}Validando a assinatura
- Leia o corpo bruto da requisição (antes de converter o JSON).
- Calcule
HMAC-SHA256(segredo, timestamp + "." + corpo). - Compare com
X-Mapogos-Assinaturausando comparação de tempo constante. - Rejeite timestamps com mais de 5 minutos de diferença.
Receptor com validação
<?php
// webhook.php — recebe avisos do Mapogos
$segredo = getenv('MAPOGOS_WEBHOOK_SECRET');
$corpo = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_MAPOGOS_TIMESTAMP'] ?? '';
$assin = $_SERVER['HTTP_X_MAPOGOS_ASSINATURA'] ?? '';
$esperado = 'sha256=' . hash_hmac('sha256', $ts . '.' . $corpo, $segredo);
if (!hash_equals($esperado, $assin) || abs(time() - (int)$ts) > 300) {
http_response_code(401);
exit;
}
$evento = json_decode($corpo, true);
if (!jaProcessado($evento['id'])) { // evita processar duas vezes
enfileirar($evento); // processe depois, responda rápido
}
http_response_code(200);import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/webhooks/mapogos', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-Mapogos-Timestamp');
const assin = req.get('X-Mapogos-Assinatura') || '';
const esperado = 'sha256=' + crypto
.createHmac('sha256', process.env.MAPOGOS_WEBHOOK_SECRET)
.update(`${ts}.${req.body}`)
.digest('hex');
const valido = assin.length === esperado.length &&
crypto.timingSafeEqual(Buffer.from(assin), Buffer.from(esperado));
if (!valido || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const evento = JSON.parse(req.body);
enfileirar(evento); // processe depois
res.sendStatus(200);
});import hmac, hashlib, os, time, json
from flask import Flask, request, abort
app = Flask(__name__)
@app.post("/webhooks/mapogos")
def mapogos():
corpo = request.get_data()
ts = request.headers.get("X-Mapogos-Timestamp", "")
assin = request.headers.get("X-Mapogos-Assinatura", "")
esperado = "sha256=" + hmac.new(os.environ["MAPOGOS_WEBHOOK_SECRET"].encode(),
ts.encode() + b"." + corpo, hashlib.sha256).hexdigest()
if not hmac.compare_digest(esperado, assin) or abs(time.time() - int(ts or 0)) > 300:
abort(401)
evento = json.loads(corpo)
enfileirar(evento) # processe depois
return "", 200Entregas e novas tentativas
| Tentativa | Quando |
|---|---|
| 1ª | Em até 1 minuto após o evento |
| 2ª | 1 min depois da falha |
| 3ª | 5 min depois |
| 4ª | 30 min depois |
| 5ª | 2 h depois |
| 6ª (última) | 12 h depois |
Considera-se entregue quando seu sistema responde 2xx em até 10 segundos. Depois da última tentativa a entrega fica como falha e pode ser reenviada pelo painel (histórico de entregas). A entrega é "pelo menos uma vez": use o id do evento para ignorar repetições.