developers  · docsCompte
Obtenir ton token
Docs · Webhooks

Webhooks

Mis à jour Aug 2026 · API v3

Enregistre un endpoint HTTPS et pon t’appelle toi quand quelque chose se passe — pas de boucle de polling, pas de requêtes gaspillées. Gère tes webhooks sur my.pon.app → Webhooks ou via l’API.

Topics

Topic Se déclenche quand
list.changed Quelque chose a changé sur une liste (grossier, regroupé — le défaut)
item.added Un article a atterri sur une liste
item.removed Un article a été supprimé
item.checked Un article a été coché pendant les courses (décocher ne déclenche que list.changed)
list.members.changed Quelqu’un a rejoint ou quitté une liste

Abonne-toi à ce dont tu as vraiment besoin. Un filtre listIds optionnel (jusqu’à 50, tes propres listes uniquement — des ids inconnus répondent 400 avec invalidListIds) restreint les livraisons à des listes précises.

Enregistrer

POST /v3/webhooks

curl -X POST https://api.pon.app/v3/webhooks \
  -H "Authorization: Bearer pon_pat_XXXX" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://hooks.example.com/pon",
        "events": ["item.checked"],
        "listIds": ["LIST_ID"] }'

La réponse contient ton secret de signature (whsec_…) — affiché une seule fois. Réenregistrer la même URL met à jour l’abonnement et conserve le secret. Jusqu’à 5 webhooks par compte.

L’enregistrement pinge ton URL immédiatement.

pon envoie un événement ping signé et attend un 2xx — réponds-y avant de vérifier la signature (le secret n’arrive que dans la réponse). Une URL morte est rejetée avec 422 WEBHOOK_UNREACHABLE.

Livraisons

Chaque livraison est un POST avec les headers PON-Event: <topic> et PON-Signature: sha256=<hmac> :

{ "event": "item.checked", "listId": "6led…", "cursor": 123, "at": "2026-08-09T19:00:00.000Z" }

Les livraisons sont best-effort, sans retries — si ton endpoint est hors service, l’événement suivant (ou un fetch de ton côté) te remet à jour. Les redirections ne sont pas suivies. Plusieurs changements correspondants dans une même écriture se regroupent en une seule livraison par topic abonné.

Vérifier la signature

Calcule un HMAC-SHA256 sur le corps brut de la requête avec ton secret et compare-le — en temps constant — au header :

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, header, secret) {
  const expected = "sha256=" +
    createHmac("sha256", secret).update(rawBody).digest("hex");
  return (
    header.length === expected.length &&
    timingSafeEqual(Buffer.from(header), Buffer.from(expected))
  );
}
import hashlib, hmac

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(header, expected)

Circuit breaker

Un 2xx acquitte une livraison. Après 20 échecs consécutifs (tout le reste, timeouts inclus) le webhook se met en pause automatiquement (status: paused, pausedReason: auto_failures). Répare ton endpoint, puis réactive-le sur my.pon.app ou via PATCH /v3/webhooks/{id} avec { "status": "active" } — la réactivation remet le compteur à zéro. Un ping de test manuel se fait via POST /v3/webhooks/{id}/pings (il ne compte jamais comme un échec).

Les webhooks battent le polling — toujours.

Une boucle de polling de 5 minutes fait environ 8 600 requêtes par mois et compte comme usage intensif sur la jauge fair-use. Un webhook en fait exactement autant que tes listes changent.