> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart : recevoir votre premier webhook

> Choisissez entre le Webhook Tester, un endpoint webhook enregistré et un event sink — puis montez un récepteur tunnélisé, vérifiez la signature et rejouez les livraisons depuis la console.

## Note de langue

Cette version française est une traduction abrégée : la section « Step 6 — Move to an event sink when you outgrow HTTP receivers » n'existe qu'en anglais : [/en/guides/first-webhook-quickstart](https://docs.orbit.devotel.io/en/guides/first-webhook-quickstart). Les blocs de code, chemins d'endpoints, noms de champs API et codes d'erreur restent en anglais.

# Quickstart : recevoir votre premier webhook

Trois surfaces de livraison sortent les événements Orbit de la plateforme ; ce guide vous aide à en choisir une, puis parcourt la boucle complète de l'endpoint enregistré — tunnel, enregistrement, vérification, replay.

## Step 1 — Choisir une surface de livraison

| Surface | Ce que c'est | Choisissez-la quand |
| - | - | - |
| **Webhook Tester** | Outil du dashboard (**Developer → Webhook Tester**) qui tire un événement synthétique non signé vers n'importe quelle URL HTTPS et montre le statut, les en-têtes et le corps rendus par votre serveur | Vous itérez sur la forme des payloads ou le traitement des réponses avant d'enregistrer un vrai endpoint |
| **Endpoint webhook enregistré** | Un abonnement durable : signé, rejoué, dédupliqué et placé en dead-letter, pointant vers votre récepteur HTTPS | Tout ce qui compte en production |
| **Event sink** | Stream chaque événement abonné vers votre propre topic Kafka ou collecteur HTTP par lot | Consommation à fort volume vers une infrastructure que vous exploitez déjà |

Commencez avec le Tester pendant vos expérimentations. Passez à un endpoint enregistré dès que l'intégration devient réelle — le tester ne signe pas les requêtes et n'exerce donc jamais votre logique de vérification.

## Step 2 — Exposer un endpoint local avec un tunnel

```bash theme={null}
# any tunnel works — ngrok, localtunnel, cloudflared
ngrok http 3000
```

Copiez l'URL HTTPS de transfert — c'est l'adresse que vous enregistrerez à l'étape suivante. Gardez le tunnel actif pendant l'enregistrement et le replay.

## Step 3 — Enregistrer l'endpoint dans la console (ou via l'API)

Dans le dashboard, allez à **Developer → Webhooks → Add endpoint**. Collez l'URL de votre tunnel, abonnez-vous à un ou deux types d'événements et enregistrez. La console montre le secret de signature en clair (`whsec_...`) exactement une fois — copiez-le maintenant dans une variable d'environnement.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/webhooks \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-tunnel-url.ngrok.io/webhooks/orbit",
    "events": ["message.delivered"]
  }'
```

La réponse porte l'identifiant de votre endpoint (`wh_...`) et le secret en clair à usage unique (`whsec_...`) — persistez-le maintenant, car tout `GET` ultérieur sur l'endpoint ne rend qu'une valeur masquée. Des listes `events` étroites gardent le trafic de test raisonnable ; `*` est une décision de production, pas de développement.

## Step 4 — Recevoir et vérifier la signature

Les livraisons enregistrées arrivent signées avec un en-tête `X-Orbit-Signature` au format `t=<unix>,v1=<hex>`. Votre récepteur doit vérifier `HMAC_SHA256(secret, "<t>.<raw body>")` sur les octets bruts de la requête — avant tout middleware JSON — et rejeter les horodatages de plus de 5 minutes. Une vérification Node minimale :

```javascript theme={null}
import crypto from "node:crypto";

function verifySignature(rawBody, header, secret) {
  if (!header) return false;
  let t = null;
  const v1s = [];
  for (const part of header.split(",")) {
    const [key, value] = part.trim().split("=");
    if (key === "t") t = value;
    else if (key === "v1") v1s.push(value);
  }
  if (!t || v1s.length === 0) return false;

  const ageSec = Math.floor(Date.now() / 1000) - Number(t);
  if (!Number.isFinite(ageSec) || ageSec < 0 || ageSec > 5 * 60) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody.toString("utf8")}`, "utf8")
    .digest("hex");

  return v1s.some((candidate) => {
    const a = Buffer.from(candidate, "hex");
    const b = Buffer.from(expected, "hex");
    return a.length === b.length && crypto.timingSafeEqual(a, b);
  });
}
```

Rendez `2xx` dans la fenêtre de livraison de 30 secondes et dédupliquez sur l'`id` de l'enveloppe — reprises et replays relivrent le même id. Le contrat complet (calendrier de reprises, dead-letter queue) est sur [Webhooks overview](https://docs.orbit.devotel.io/webhooks/overview.md).

## Step 5 — Rejouer les livraisons depuis la console

Chaque tentative de livraison est inspectable sous **Developer → Webhooks → Events** — choisissez une ligne pour voir le payload et la réponse rendue par votre serveur. Une livraison échouée se renvoie avec **Replay** sur la ligne, ce qui vous permet de corriger votre récepteur et de retiquer le même événement signé sans déclencher de nouveau trafic.

Les livraisons qui épuisent le calendrier de reprises atterrissent dans la dead-letter queue sous **Developer → Webhooks → Dead-letter queue**, rejouables pendant 7 jours.

## Voir aussi

* [Test webhooks with the Webhook Tester](https://docs.orbit.devotel.io/guides/webhook-tester.md) — envois synthétiques non signés pour itérer
* [Build your first webhook receiver](https://docs.orbit.devotel.io/webhooks/first-receiver.md) — parcours complet du récepteur en Node et Python
* [Build a durable webhook consumer](https://docs.orbit.devotel.io/guides/webhook-consumer.md) — récepteur de production avec traitement en file


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.