Sviluppatori
Webhook e Zapier
I webhook inviano una richiesta HTTP al tuo server nel momento in cui succede qualcosa nel tuo workspace, ad esempio quando un'app viene messa in pausa o qualcuno fa clic su uno smart link. Usali per aggiornare i tuoi sistemi, pubblicare su Slack o collegare mapps.one a Zapier, Make o n8n senza scrivere un server. I webhook sono disponibili con il piano Studio, con un massimo di 10 endpoint per workspace.
Aggiungi un endpoint
- Nella dashboard, apri Sviluppatori → Webhook e scegli Aggiungi endpoint. Possono farlo i proprietari e gli admin del workspace.
- Inserisci un URL
httpspubblico, scegli gli eventi da inviare (o tutti gli eventi) e aggiungi una descrizione. - Copia il segreto di firma e conservalo insieme agli altri segreti del tuo server.
- Scegli Invia evento di test per verificare che il tuo endpoint risponda.
La pagina dell'endpoint mostra le consegne recenti con lo stato della risposta, i primi 2.000 caratteri del corpo della risposta e la durata di ogni tentativo. Puoi anche creare ed eliminare endpoint con l'API.
Eventi
| Tipo | Inviato quando |
|---|---|
app.created | È stata aggiunta un'app al workspace. |
app.updated | Sono cambiati i dettagli, i link o le impostazioni della pagina di un'app. |
app.deleted | È stata eliminata un'app. |
app.status_changed | Un'app è andata online, è stata messa in pausa o è stata sospesa. |
app.metadata_fetched | Sono stati importati i metadati dello store per un'app. |
legal.published | È stata pubblicata un'informativa sulla privacy o un documento dei termini. |
domain.verified | Un dominio personalizzato è stato verificato. |
link.clicked | Ogni clic su uno smart link. Per un'app popolare possono essere molte richieste. |
analytics.daily_summary | I clic totali del giorno precedente per ogni app, inviati una volta al giorno. |
Formato della richiesta
Ogni evento viene inviato come richiesta POST con un corpo JSON.
| Header | Valore |
|---|---|
Content-Type | application/json |
User-Agent | mapps.one-Webhooks/1.0 |
X-Mapps-Event | Il tipo di evento, come link.clicked |
X-Mapps-Delivery | L'ID dell'evento. Resta lo stesso a ogni nuovo tentativo. |
X-Mapps-Timestamp | Ora Unix di questo tentativo di consegna |
X-Mapps-Signature | t={timestamp},v1={signature} |
Il corpo è un contenitore con la stessa struttura per tutti gli eventi:
{
"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"
}
}
Il contenuto di data dipende dall'evento. Gli eventi relativi a un'app includono un oggetto app con id, slug e name.
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 è in UTC. device_type è mobile, tablet o desktop. destination è una chiave dello store, web o landing. I campi sconosciuti sono null. Le visite dei bot non attivano mai questo evento.
app.metadata_fetched
"data": {
"app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly", "name": "Habitly" },
"source": "app_store"
}
Verifica le firme
Controlla la firma di ogni richiesta, così sai che proviene da mapps.one e che non è stata modificata lungo il percorso:
- Leggi
tev1dall'headerX-Mapps-Signature. - Calcola un HMAC-SHA256 di
{t}.{raw request body}usando il segreto di firma del tuo endpoint, in esadecimale minuscolo. - Confrontalo con
v1usando un confronto a tempo costante. - Rifiuta la richiesta se
tsi discosta di più di cinque minuti dall'orologio del tuo server, per bloccare le richieste riprodotte.
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);
In Laravel, leggi il corpo con $request->getContent() e l'header con $request->header('X-Mapps-Signature'), ed escludi la route dalla protezione 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);
Risposte e nuovi tentativi
- Rispondi con uno stato 2xx qualsiasi entro 10 secondi. Esegui le operazioni lente in un job in background dopo aver risposto.
- I reindirizzamenti non vengono seguiti, quindi usa l'URL finale.
- L'URL deve essere
httpspubblico. Gli indirizzi di reti private e locali vengono rifiutati. - Se il tuo endpoint va in timeout o restituisce qualcosa di diverso da 2xx, riproviamo fino ad altre cinque volte: dopo circa 1 minuto, 5 minuti, 30 minuti, 2 ore e 6 ore. Ogni tentativo ha un nuovo timestamp e una nuova firma.
- Lo stesso evento può arrivare più di una volta, e gli eventi possono arrivare fuori ordine. Usa
X-Mapps-Delivery, l'iddell'evento, per ignorare i duplicati, ecreated_atper ordinarli. - Dopo 20 tentativi falliti di fila, l'endpoint viene disattivato e non gli viene più inviato nulla. Risolvi il problema, poi riattivalo dalla dashboard.
Zapier, Make e n8n
Puoi collegare mapps.one a migliaia di app senza gestire un server.
Zapier
- Crea uno Zap con Webhooks by Zapier come trigger e scegli Catch Hook.
- Copia l'URL del webhook che ti fornisce Zapier.
- In mapps.one, aggiungi un endpoint con quell'URL e scegli gli eventi che ti interessano, ad esempio
app.status_changedoanalytics.daily_summary. - Scegli Invia evento di test in mapps.one, poi Test trigger in Zapier. Ora puoi usare nei passaggi successivi i campi del payload, come
data.app.name.
Esempi: pubblicare un messaggio su Slack quando un'app viene messa in pausa, aggiungere i clic di ogni giorno a un Google Sheet, o inviare un'email a un cliente quando il suo dominio viene verificato.
Make e n8n
In Make, usa il trigger Webhooks → Custom webhook. In n8n, usa il nodo Webhook con il metodo POST. Poi aggiungi l'URL come endpoint in mapps.one, come descritto sopra.
Creare un'integrazione
Se stai creando un'integrazione con mapps.one per altre persone, registra il webhook con l'API quando un utente si collega (POST /api/v1/webhooks), rimuovilo quando si scollega (DELETE /api/v1/webhooks/{id}), usa GET /api/v1/events per il selettore degli eventi e GET /api/v1/workspace per testare la connessione. Consulta il riferimento API.