developers  · docsKonto
Token holen
Docs · Webhooks

Webhooks

Aktualisiert Aug 2026 · API v3

Registriere 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 signiertes ping-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.