PAKDATAHUB
Docs · API reference

For AI agents: this page is available as raw Markdown at /docs/api-webhooks.md · every page in one file at /llms-full.txt · index at /docs/llms.txt

Webhooks

Register a URL and PakDataHub will POST to it when a series you care about gets new data, so you don't have to poll.

Plan limits (active webhooks): Free 0 · Developer 3 · Pro 50 · Business unlimited.

POST /v1/webhooks 🔑 / session

Field Type Notes
url string Required, https:// (or http://)
series_id string Subscribe to one series
module string …or to every series in a module (e.g. forex)

At least one of series_id or module is required.

curl -X POST -H "X-API-Key: pk_live_xxx" -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/hooks/pakdata", "series_id": "rates.kibor.3m"}' \
  "https://api.pakdatahub.com/v1/webhooks"
{ "success": true, "id": "3f1c…", "signing_secret": "whsec_…",
  "note": "store this signing secret now — it is shown only once" }

GET /v1/webhooks · DELETE /v1/webhooks/{id}

List your webhooks, or delete one.

The delivery

When an ingestion run adds or changes data for a matching series, you receive:

POST /hooks/pakdata HTTP/1.1
Content-Type: application/json
X-PakData-Signature: 5d41402abc4b2a76b9719d911017c592…
{ "event": "series.updated",
  "delivered_at": "2026-09-24T09:12:03Z",
  "series": [ { "series_id": "rates.kibor.3m",
                "latest": { "date": "2026-09-24", "value": 11.75, "dims": { "side": "offer" } } } ] }
  • latest is the newest stored observation of each matched series. Fetch the full update with /v1/series/{id}.
  • It fires on incremental updates only, never for historical backfills.
  • Delivery is best-effort with a short timeout. Respond with 2xx quickly and do the work asynchronously.

Verifying the signature

X-PakData-Signature is the hex HMAC-SHA256 of the raw request body, keyed with your signing_secret:

import hmac, hashlib

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)
import crypto from "node:crypto";
const ok = crypto.timingSafeEqual(
  Buffer.from(crypto.createHmac("sha256", secret).update(rawBody).digest("hex")),
  Buffer.from(req.headers["x-pakdata-signature"]));
View as Markdown (.md)