Webhooks
Aktualisiert Aug 2026 · API v3Registriere einen HTTPS-Endpunkt, und pon ruft dich an, wenn etwas passiert — keine Polling-Schleife, keine verschwendeten Requests. Webhooks verwaltest du unter my.pon.app → Webhooks oder über die API.
Topics
| Topic | Feuert, wenn |
|---|---|
list.changed |
Sich irgendetwas an einer Liste geändert hat (grob, gebündelt — der Standard) |
item.added |
Ein Artikel auf einer Liste gelandet ist |
item.removed |
Ein Artikel gelöscht wurde |
item.checked |
Ein Artikel beim Einkaufen abgehakt wurde (das Enthaken feuert nur list.changed) |
list.members.changed |
Jemand einer Liste beigetreten oder sie verlassen hat |
Abonniere, was du wirklich brauchst. Ein optionaler listIds-Filter (bis
zu 50, nur deine eigenen Listen — unbekannte IDs antworten 400 mit
invalidListIds) beschränkt die Zustellungen auf bestimmte Listen.
Registrieren
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"] }'
Die Antwort enthält dein Signing-Secret (whsec_…) — es wird einmal
angezeigt. Dieselbe URL erneut zu registrieren aktualisiert das Abo und
behält das Secret. Bis zu 5 Webhooks pro Account.
Die Registrierung pingt deine URL sofort an.
pon schickt ein signiertesping-Event und erwartet ein 2xx — beantworte es, bevor du die Signatur prüfst (das Secret kommt erst in der Antwort an). Eine tote URL wird mit 422 WEBHOOK_UNREACHABLE abgelehnt.Zustellungen
Jede Zustellung ist ein POST mit den Headern PON-Event: <topic> und
PON-Signature: sha256=<hmac>:
{ "event": "item.checked", "listId": "6led…", "cursor": 123, "at": "2026-08-09T19:00:00.000Z" }
Zustellungen sind best-effort, ohne Retries — ist dein Endpunkt down, holt dich das nächste Event (oder ein Fetch auf deiner Seite) wieder ab. Redirects werden nicht gefolgt. Mehrere passende Änderungen in einem Schreibvorgang bündeln sich zu einer Zustellung pro abonniertem Topic.
Die Signatur prüfen
Berechne einen HMAC-SHA256 über den rohen Request-Body mit deinem Secret und vergleiche ihn — zeitkonstant — mit dem 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
Ein 2xx quittiert eine Zustellung. Nach 20 Fehlschlägen in Folge
(alles andere, auch Timeouts) pausiert sich der Webhook automatisch
(status: paused, pausedReason: auto_failures). Repariere deinen
Endpunkt und reaktiviere ihn dann auf my.pon.app oder via
PATCH /v3/webhooks/{id} mit { "status": "active" } —
das Reaktivieren setzt den Zähler zurück. Ein manueller Test-Ping ist
POST /v3/webhooks/{id}/pings (zählt nie als
Fehlschlag).
Webhooks schlagen Polling — immer.
Eine 5-Minuten-Polling-Schleife macht ~8.600 Requests im Monat und gilt auf der Fair-Use-Anzeige als starke Nutzung. Ein Webhook macht genau so viele, wie sich deine Listen ändern.