developers  · docsKonto
Pobierz token
Dokumentacja · Webhooki

Webhooki

Zaktualizowano Aug 2026 · API v3

Zarejestruj endpoint HTTPS, a pon zawoła Ciebie, gdy coś się wydarzy — bez pętli pollingu, bez zmarnowanych requestów. Webhookami zarządzasz na my.pon.app → Webhooki albo przez API.

Topiki

Topic Kiedy się uruchamia
list.changed Cokolwiek w liście się zmieniło (zgrubne, łączone — wartość domyślna)
item.added Produkt trafił na listę
item.removed Produkt został usunięty
item.checked Produkt został odhaczony podczas zakupów (cofnięcie odhaczenia uruchamia tylko list.changed)
list.members.changed Ktoś dołączył do listy albo ją opuścił

Subskrybuj to, czego faktycznie potrzebujesz. Opcjonalny filtr listIds (do 50, tylko Twoje własne listy — nieznane id odpowiadają 400 z invalidListIds) zawęża dostawy do konkretnych list.

Rejestracja

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

Odpowiedź zawiera Twój sekret do podpisów (whsec_…) — pokazany raz. Ponowna rejestracja tego samego URL-a aktualizuje subskrypcję i zachowuje sekret. Do 5 webhooków na konto.

Rejestracja od razu pinguje Twój URL.

pon wysyła podpisany event ping i oczekuje 2xx — odpowiedz na niego, zanim sprawdzisz podpis (sekret przychodzi dopiero w odpowiedzi). Martwy URL zostaje odrzucony z 422 WEBHOOK_UNREACHABLE.

Dostawy

Każda dostawa to POST z nagłówkami PON-Event: <topic> i PON-Signature: sha256=<hmac>:

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

Dostawy są best-effort, bez ponowień — jeśli Twój endpoint leży, kolejny event (albo fetch po Twojej stronie) nadrobi zaległości. Przekierowania nie są śledzone. Kilka pasujących zmian w jednym zapisie łączy się w jedną dostawę na subskrybowany topic.

Weryfikacja podpisu

Policz HMAC-SHA256 z surowego body requestu swoim sekretem i porównaj go — w stałym czasie — z nagłówkiem:

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

2xx potwierdza dostawę. Po 20 kolejnych niepowodzeniach (cokolwiek innego, łącznie z timeoutami) webhook automatycznie się pauzuje (status: paused, pausedReason: auto_failures). Napraw endpoint, a potem reaktywuj go na my.pon.app albo przez PATCH /v3/webhooks/{id} z { "status": "active" } — reaktywacja zeruje licznik. Ręczny testowy ping to POST /v3/webhooks/{id}/pings (nigdy nie liczy się jako niepowodzenie).

Webhooki wygrywają z pollingiem — zawsze.

Pętla pollingu co 5 minut robi ~8 600 requestów miesięcznie i liczy się jako intensywne użycie na wskaźniku fair use. Webhook robi ich dokładnie tyle, ile razy zmieniają się Twoje listy.