Aller au contenu

Développeurs

Webhooks et Zapier

Les webhooks envoient une requête HTTP à votre serveur dès qu'un événement se produit dans votre espace de travail, par exemple lorsqu'une application est mise en pause ou qu'un lien intelligent est cliqué. Utilisez-les pour mettre à jour vos propres systèmes, publier dans Slack, ou connecter mapps.one à Zapier, Make ou n8n sans écrire de serveur. Les webhooks sont disponibles avec le forfait Studio, avec jusqu'à 10 points de terminaison par espace de travail.

Ajouter un point de terminaison

  1. Dans le tableau de bord, ouvrez Développeurs → Webhooks et choisissez Ajouter un point de terminaison. Les propriétaires et les administrateurs de l'espace de travail peuvent le faire.
  2. Saisissez une URL https publique, choisissez les événements à envoyer (ou tous les événements) et ajoutez une description.
  3. Copiez le secret de signature et conservez-le avec les autres secrets de votre serveur.
  4. Choisissez Envoyer un événement de test pour vérifier que votre point de terminaison répond.

La page du point de terminaison affiche les livraisons récentes avec le statut de la réponse, les 2 000 premiers caractères du corps de la réponse et la durée de chaque tentative. Vous pouvez aussi créer et supprimer des points de terminaison avec l'API.

Événements

TypeEnvoyé lorsque
app.createdUne application a été ajoutée à l'espace de travail.
app.updatedLes détails, les liens ou les paramètres de page d'une application ont changé.
app.deletedUne application a été supprimée.
app.status_changedUne application est passée en ligne, a été mise en pause ou a été suspendue.
app.metadata_fetchedLes métadonnées du store ont été importées pour une application.
legal.publishedUne politique de confidentialité ou des conditions d'utilisation ont été publiées.
domain.verifiedUn domaine personnalisé a été vérifié.
link.clickedChaque clic sur un lien intelligent. Cela peut représenter beaucoup de requêtes pour une application populaire.
analytics.daily_summaryLes totaux de clics de la veille pour chaque application, envoyés une fois par jour.

Format des requêtes

Chaque événement est envoyé sous forme de requête POST avec un corps JSON.

En-têteValeur
Content-Typeapplication/json
User-Agentmapps.one-Webhooks/1.0
X-Mapps-EventLe type d'événement, comme link.clicked
X-Mapps-DeliveryL'identifiant de l'événement. Il reste le même à chaque nouvelle tentative.
X-Mapps-TimestampL'heure Unix de cette tentative de livraison
X-Mapps-Signaturet={timestamp},v1={signature}

Le corps est une enveloppe qui a la même structure pour chaque événement :

{
  "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"
  }
}

Le contenu de data dépend de l'événement. Les événements qui concernent une application incluent un objet app avec son id, son slug et son 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 est exprimé en UTC. device_type vaut mobile, tablet ou desktop. destination est une clé de store, web ou landing. Les champs inconnus valent null. Les visites de robots ne déclenchent jamais cet événement.

app.metadata_fetched

"data": {
  "app": { "id": "01j8b2k6r3xq9v7m4n5p0s1t2w", "slug": "habitly", "name": "Habitly" },
  "source": "app_store"
}

Vérifier les signatures

Vérifiez la signature de chaque requête, pour vous assurer qu'elle provient de mapps.one et qu'elle n'a pas été modifiée en chemin :

  1. Lisez t et v1 dans l'en-tête X-Mapps-Signature.
  2. Calculez un HMAC-SHA256 de {t}.{raw request body} avec le secret de signature de votre point de terminaison, en hexadécimal minuscule.
  3. Comparez-le à v1 à l'aide d'une comparaison à temps constant.
  4. Rejetez la requête si t s'écarte de plus de cinq minutes de l'horloge de votre serveur, afin de bloquer les requêtes rejouées.
Utilisez le corps brut. Signez exactement les octets reçus, avant toute analyse du JSON. Réencoder le JSON peut modifier les barres obliques ou les caractères Unicode et invalider la signature.

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);

Dans Laravel, lisez le corps avec $request->getContent() et l'en-tête avec $request->header('X-Mapps-Signature'), et excluez la route de la protection 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);

Réponses et nouvelles tentatives

  • Répondez avec n'importe quel statut 2xx en moins de 10 secondes. Effectuez les traitements longs dans une tâche en arrière-plan, après avoir répondu.
  • Les redirections ne sont pas suivies, utilisez donc l'URL finale.
  • L'URL doit être une adresse https publique. Les adresses de réseaux privés et locaux sont refusées.
  • Si votre point de terminaison ne répond pas à temps ou renvoie autre chose qu'un statut 2xx, nous réessayons jusqu'à cinq fois de plus : après environ 1 minute, 5 minutes, 30 minutes, 2 heures et 6 heures. Chaque tentative a un nouvel horodatage et une nouvelle signature.
  • Un même événement peut arriver plusieurs fois, et les événements peuvent arriver dans le désordre. Utilisez X-Mapps-Delivery, l'id de l'événement, pour ignorer les doublons, et created_at pour les remettre dans l'ordre.
  • Après 20 tentatives échouées d'affilée, le point de terminaison est désactivé et plus rien ne lui est envoyé. Corrigez le problème, puis réactivez-le dans le tableau de bord.

Zapier, Make et n8n

Vous pouvez connecter mapps.one à des milliers d'applications sans faire tourner de serveur.

Zapier

  1. Créez un Zap avec Webhooks by Zapier comme déclencheur et choisissez Catch Hook.
  2. Copiez l'URL de webhook que Zapier vous fournit.
  3. Dans mapps.one, ajoutez un point de terminaison avec cette URL et choisissez les événements souhaités, par exemple app.status_changed ou analytics.daily_summary.
  4. Choisissez Envoyer un événement de test dans mapps.one, puis Test trigger dans Zapier. Les champs de la charge utile, comme data.app.name, sont alors utilisables dans les étapes suivantes.

Exemples : publier un message Slack lorsqu'une application est mise en pause, ajouter les clics de chaque jour à une feuille Google Sheets, ou envoyer un e-mail à un client lorsque son domaine est vérifié.

Make et n8n

Dans Make, utilisez le déclencheur Webhooks → Custom webhook. Dans n8n, utilisez le nœud Webhook avec la méthode POST. Ajoutez ensuite l'URL comme point de terminaison dans mapps.one, comme décrit ci-dessus.

Créer une intégration

Si vous créez une intégration mapps.one destinée à d'autres personnes, abonnez-vous avec l'API lorsqu'un utilisateur connecte son compte (POST /api/v1/webhooks), désabonnez-vous lorsqu'il le déconnecte (DELETE /api/v1/webhooks/{id}), utilisez GET /api/v1/events pour le sélecteur d'événements et GET /api/v1/workspace pour tester la connexion. Consultez la référence de l'API.