Aller au contenu

Vue d'ensemble des webhooks

Les webhooks poussent les événements d’e-mail vers votre serveur au fur et à mesure, vous n’avez donc pas à interroger GET /emails/{id}. SpacePost signe chaque requête selon le schéma Standard Webhooks (celui de Svix et de Resend) : le code de vérification existant fonctionne donc sans changement.

  1. Créez un endpoint qui accepte POST avec un corps JSON et répond 2xx rapidement.

  2. Enregistrez-le

    create-webhook.ts
    import { SpacePost } from "@spacepost/node";
    const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);
    const { data: webhook, error } = await spacepost.webhooks.create({
    endpoint: "https://acme.com/webhooks/spacepost",
    events: ["email.delivered", "email.bounced", "email.complained"],
    });
    if (error) throw new Error(`${error.name}: ${error.message}`);
    // Store this secret: you need it to verify signatures. It starts with "whsec_".
    console.log(webhook.id, webhook.signing_secret);
    Response
    {
    "object": "webhook",
    "id": "0192e1c4-0000-7000-8000-0000000000aa",
    "endpoint": "https://acme.com/webhooks/spacepost",
    "events": ["email.delivered", "email.bounced", "email.complained"],
    "status": "enabled",
    "created_at": "2026-10-23T14:00:00.000Z",
    "signing_secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
    }
  3. Vérifiez la signature de chaque requête. Voir Vérifier les signatures.

  4. Renvoyez 2xx. Toute autre réponse (redirections et délais dépassés compris) est retentée. Voir Nouvelles tentatives.

Chaque distribution est un POST avec Content-Type: application/json et ces en-têtes :

En-tête Valeur
webhook-id Id unique de cette distribution. Le même id à chaque nouvelle tentative : utilisez-le pour dédupliquer.
webhook-timestamp Heure Unix en secondes à laquelle cette tentative a été envoyée.
webhook-signature v1,<base64 HMAC-SHA256>. Une liste séparée par des espaces s’il y a plusieurs signatures.
svix-id, svix-timestamp, svix-signature Doublons identiques des trois en-têtes ci-dessus, pour que les bibliothèques Svix fonctionnent telles quelles.

Le corps est { "type": "...", "created_at": "...", "data": { ... } }. Voir Types d’événements.

POST /webhooks, GET /webhooks, GET /webhooks/{id}, PATCH /webhooks/{id} (modifie endpoint, events ou status : enabled ou disabled) et DELETE /webhooks/{id}. Le signing_secret est renvoyé à la création d’un webhook ou lorsque vous en récupérez un seul, pas dans les listes.

manage-webhooks.ts
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);
const id = "0192e1c4-0000-7000-8000-0000000000aa";
// Subscribe to more events and temporarily disable delivery.
await spacepost.webhooks.update({ id, events: ["email.delivered", "email.bounced", "email.opened"], status: "disabled" });
const { data } = await spacepost.webhooks.list({ limit: 20 });
console.log(data?.data.map((w) => `${w.id} ${w.status} ${w.endpoint}`));
await spacepost.webhooks.remove(id);
  • https:// en production (http:// simple n’est accepté qu’en développement).
  • L’hôte doit résoudre vers une adresse publique. Localhost et les réseaux privés sont rejetés. En développement local, utilisez un tunnel comme ngrok ou Cloudflare Tunnel.
  • Répondez en moins de 15 secondes.
  • Les redirections ne sont pas suivies.