developers  · docsKonto
Hent dit token
Docs · Webhooks

Webhooks

Opdateret Aug 2026 · API v3

Registrér et HTTPS-endpoint, og pon kalder dig, når der sker noget — ingen polling-løkke, ingen spildte requests. Administrér webhooks på my.pon.app → Webhooks eller via API’et.

Topics

Topic Udløses, når
list.changed Noget som helst ved en liste er ændret (groft, sammenlagt — standarden)
item.added En vare er landet på en liste
item.removed En vare er blevet slettet
item.checked En vare er blevet hakket af under indkøb (at fjerne hakket udløser kun list.changed)
list.members.changed Nogen er kommet med på eller har forladt en liste

Abonnér på det, du faktisk har brug for. Et valgfrit listIds-filter (op til 50, kun dine egne lister — ukendte id’er svarer 400 med invalidListIds) begrænser leveringerne til bestemte lister.

Registrér

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"] }'

Svaret indeholder din signeringshemmelighed (whsec_…) — den vises én gang. Registrerer du den samme URL igen, opdateres abonnementet, og hemmeligheden bevares. Op til 5 webhooks pr. konto.

Registreringen pinger din URL med det samme.

pon sender et signeret ping-event og forventer et 2xx — svar på det, før du tjekker signaturen (hemmeligheden ankommer først i svaret). En død URL afvises med 422 WEBHOOK_UNREACHABLE.

Leveringer

Hver levering er et POST med headerne PON-Event: <topic> og PON-Signature: sha256=<hmac>:

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

Leveringer er best-effort uden retries — er dit endpoint nede, samler det næste event (eller et fetch fra din side) dig op igen. Redirects følges ikke. Flere matchende ændringer i én skrivning lægges sammen til én levering pr. abonneret topic.

Verificér signaturen

Beregn en HMAC-SHA256 over den rå request-body med din hemmelighed og sammenlign den — i konstant tid — med headeren:

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

Et 2xx kvitterer for en levering. Efter 20 fejl i træk (alt andet, inklusive timeouts) sætter webhooken sig selv på pause (status: paused, pausedReason: auto_failures). Reparér dit endpoint, og genaktivér det så på my.pon.app eller via PATCH /v3/webhooks/{id} med { "status": "active" } — genaktivering nulstiller tælleren. Et manuelt test-ping er POST /v3/webhooks/{id}/pings (tæller aldrig som en fejl).

Webhooks slår polling — altid.

En polling-løkke hvert 5. minut laver ~8.600 requests om måneden og tæller som tung brug på fair-use-måleren. En webhook laver præcis lige så mange, som dine lister ændrer sig.