Docs / More

Webhooks

Webhooks push events to your server — bulk.completed / bulk.failed / bulk.item, quota.warning / quota.exceeded, request.error, key.created / key.disabled / key.deleted, and webhook.test. Manage endpoints at Dashboard → Webhooks. Every delivery is signed: X-Zpi-Signature: sha256=<hex(hmac_sha256(secret, body))>, with the event name in X-Zpi-Event.

zpi-sdk/webhooks verifies and parses deliveries in one call — Web Crypto with a timing-safe compare, so the same code runs on Node, Bun, Deno, and edge runtimes:

webhook.ts
import { parseWebhook } from "zpi-sdk/webhooks"; // In your HTTP handler — pass the RAW body string, not parsed JSON:const event = await parseWebhook(rawBody, {  signature: req.headers["x-zpi-signature"],  secret: process.env.ZPI_WEBHOOK_SECRET,});// → { id, event: "bulk.completed" | ..., data, deliveredAt }// Throws ZpiWebhookVerifyError on a bad signature or malformed payload. switch (event.event) {  case "bulk.completed":    console.log("job done:", event.data);    break;  case "quota.warning":    console.log("almost out of quota");    break;}
import { parseWebhook } from "zpi-sdk/webhooks"; // In your HTTP handler — pass the RAW body string, not parsed JSON:const event = await parseWebhook(rawBody, {  signature: req.headers["x-zpi-signature"],  secret: process.env.ZPI_WEBHOOK_SECRET,});// → { id, event: "bulk.completed" | ..., data, deliveredAt }// Throws ZpiWebhookVerifyError on a bad signature or malformed payload. switch (event.event) {  case "bulk.completed":    console.log("job done:", event.data);    break;  case "quota.warning":    console.log("almost out of quota");    break;}
Edit this page on GitHubWas this page helpful? ·