Desenvolvedores
Webhooks e Zapier
Os webhooks enviam uma solicitação HTTP ao seu servidor no momento em que algo acontece no seu espaço de trabalho, como quando um app é pausado ou um link inteligente é clicado. Use-os para atualizar seus próprios sistemas, publicar no Slack ou conectar o mapps.one ao Zapier, ao Make ou ao n8n sem escrever um servidor. Os webhooks estão disponíveis no plano Studio, com até 10 endpoints por espaço de trabalho.
Adicione um endpoint
- No painel, abra Desenvolvedores → Webhooks e escolha Adicionar endpoint. Proprietários e admins do espaço de trabalho podem fazer isso.
- Digite uma URL
httpspública, escolha os eventos que serão enviados (ou todos os eventos) e adicione uma descrição. - Copie o segredo de assinatura e guarde-o junto com os outros segredos do seu servidor.
- Escolha Enviar evento de teste para verificar se o seu endpoint responde.
A página do endpoint mostra as entregas recentes com o status da resposta, os primeiros 2.000 caracteres do corpo da resposta e quanto tempo cada tentativa levou. Você também pode criar e excluir endpoints com a API.
Eventos
| Tipo | Enviado quando |
|---|---|
app.created | Um app foi adicionado ao espaço de trabalho. |
app.updated | Os detalhes, os links ou as configurações de página de um app foram alterados. |
app.deleted | Um app foi excluído. |
app.status_changed | Um app ficou ativo, foi pausado ou foi suspenso. |
app.metadata_fetched | Os metadados da loja foram importados para um app. |
legal.published | Uma política de privacidade ou um documento de termos foi publicado. |
domain.verified | Um domínio personalizado foi verificado. |
link.clicked | Cada clique no link inteligente. Isso pode gerar muitas solicitações para um app popular. |
analytics.daily_summary | Os totais de cliques do dia anterior para cada app, enviados uma vez por dia. |
Formato da solicitação
Cada evento é enviado como uma solicitação POST com um corpo JSON.
| Cabeçalho | Valor |
|---|---|
Content-Type | application/json |
User-Agent | mapps.one-Webhooks/1.0 |
X-Mapps-Event | O tipo do evento, como link.clicked |
X-Mapps-Delivery | O ID do evento. Ele continua o mesmo em todas as novas tentativas. |
X-Mapps-Timestamp | Horário Unix desta tentativa de entrega |
X-Mapps-Signature | t={timestamp},v1={signature} |
O corpo é um envelope com o mesmo formato para todos os eventos:
{
"id": "evt_01j8c3m9t5v2x7z4b6d8f0h2k4",
"type": "app.status_changed",
"created_at": "2026-09-14T09:41:07+00:00",
"workspace": {
"id": "01j8a0f4c7d2e9h6k3m5n8q1r4",
"name": "Habitly Labs"
},
"data": {
"app": {
"id": "01j8b2k6r3xq9v7m4n5p0s1t2w",
"slug": "habitly",
"name": "Habitly"
},
"status": "paused"
}
}
O conteúdo de data depende do evento. Eventos sobre um app incluem um objeto app com o id, o slug e o name dele.
link.clicked
"data": {
"app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly", "name": "Habitly" },
"click": {
"occurred_at": "2026-09-14 09:41:07",
"os": "iOS",
"device_type": "mobile",
"country": "TR",
"source": "instagram",
"destination": "app_store",
"utm_source": "instagram",
"utm_medium": "social",
"utm_campaign": "launch"
}
}
occurred_at está em UTC. device_type é mobile, tablet ou desktop. destination é uma chave de loja, web ou landing. Campos desconhecidos são null. Visitas de bots nunca disparam este evento.
app.metadata_fetched
"data": {
"app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly", "name": "Habitly" },
"source": "app_store"
}
Verifique as assinaturas
Verifique a assinatura de cada solicitação, para ter certeza de que ela veio do mapps.one e não foi alterada no caminho:
- Leia
tev1do cabeçalhoX-Mapps-Signature. - Calcule um HMAC-SHA256 de
{t}.{raw request body}usando o segredo de assinatura do seu endpoint, em hexadecimal minúsculo. - Compare o resultado com
v1usando uma comparação em tempo constante. - Rejeite a solicitação se
testiver a mais de cinco minutos do relógio do seu servidor, para bloquear solicitações reenviadas por terceiros.
PHP
<?php
$secret = getenv('MAPPS_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_X_MAPPS_SIGNATURE'] ?? ''), $parts);
$timestamp = (int) ($parts['t'] ?? 0);
$expected = hash_hmac('sha256', $timestamp.'.'.$body, $secret);
if (! hash_equals($expected, (string) ($parts['v1'] ?? '')) || abs(time() - $timestamp) > 300) {
http_response_code(400);
exit;
}
$event = json_decode($body, true);
if ($event['type'] === 'link.clicked') {
// Store $event['data']['click'] ...
}
http_response_code(200);
No Laravel, leia o corpo com $request->getContent() e o cabeçalho com $request->header('X-Mapps-Signature'), e exclua a rota da proteção CSRF.
Node.js (Express)
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const secret = process.env.MAPPS_WEBHOOK_SECRET;
app.post('/webhooks/mapps', express.raw({ type: 'application/json' }), (req, res) => {
const header = req.get('X-Mapps-Signature') ?? '';
const parts = Object.fromEntries(header.split(',').map((pair) => pair.split('=')));
const timestamp = Number(parts.t);
const body = req.body.toString('utf8');
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest();
const received = Buffer.from(parts.v1 ?? '', 'hex');
const valid = received.length === expected.length && crypto.timingSafeEqual(received, expected);
if (!valid || Math.abs(Date.now() / 1000 - timestamp) > 300) {
return res.sendStatus(400);
}
const event = JSON.parse(body);
if (event.type === 'link.clicked') {
// Store event.data.click ...
}
res.sendStatus(200);
});
app.listen(3000);
Respostas e novas tentativas
- Responda com qualquer status 2xx em até 10 segundos. Faça o trabalho demorado em um job em segundo plano depois de responder.
- Redirecionamentos não são seguidos, então use a URL final.
- A URL deve ser
httpspública. Endereços de redes privadas e locais são recusados. - Se o seu endpoint exceder o tempo limite ou retornar qualquer coisa diferente de 2xx, tentamos novamente até mais cinco vezes: depois de cerca de 1 minuto, 5 minutos, 30 minutos, 2 horas e 6 horas. Cada tentativa tem um novo timestamp e uma nova assinatura.
- O mesmo evento pode chegar mais de uma vez, e os eventos podem chegar fora de ordem. Use
X-Mapps-Delivery, oiddo evento, para ignorar duplicatas, ecreated_atpara ordená-los. - Depois de 20 tentativas seguidas com falha, o endpoint é desativado e nada mais é enviado para ele. Corrija o problema e depois reative-o no painel.
Zapier, Make e n8n
Você pode conectar o mapps.one a milhares de apps sem manter um servidor.
Zapier
- Crie um Zap com Webhooks by Zapier como gatilho e escolha Catch Hook.
- Copie a URL de webhook que o Zapier fornecer.
- No mapps.one, adicione um endpoint com essa URL e escolha os eventos que você quer, por exemplo
app.status_changedouanalytics.daily_summary. - Escolha Enviar evento de teste no mapps.one e depois Test trigger no Zapier. Os campos do payload, como
data.app.name, agora podem ser usados nas próximas etapas.
Exemplos: publicar uma mensagem no Slack quando um app for pausado, adicionar os cliques de cada dia a uma planilha do Google Sheets ou enviar um e-mail para um cliente quando o domínio dele for verificado.
Make e n8n
No Make, use o gatilho Webhooks → Custom webhook. No n8n, use o nó Webhook com o método POST. Depois, adicione a URL como endpoint no mapps.one, como descrito acima.
Como criar uma integração
Se você está criando uma integração do mapps.one para outras pessoas, faça a inscrição com a API quando um usuário se conectar (POST /api/v1/webhooks), cancele a inscrição quando ele se desconectar (DELETE /api/v1/webhooks/{id}), use GET /api/v1/events para o seletor de eventos e use GET /api/v1/workspace para testar a conexão. Veja a referência da API.