Webhooks

Push delivery-related events to your own HTTPS endpoint for automation and alerting.

Register an endpoint

Open Webhooks → Register Webhook. Give the endpoint a name (e.g. Slack alerts), enter a publicly reachable HTTPS URL, and select which event types you care about. After saving, Piisend delivers JSON payloads when those events occur.

Edit later

Open a webhook’s detail page and choose Edit to change its name or subscribed events (delivery, bounce, complaint, open, click). The destination URL is fixed after registration — delete and recreate if you need a new URL.

Slack Incoming Webhooks

Paste a Slack Incoming Webhook URL (from your Slack app → Incoming Webhooks). Piisend detects hooks.slack.com URLs automatically and posts human-readable messages to the channel instead of the signed JSON envelope.

  • Example URL: https://hooks.slack.com/services/T…/B…/…
  • Deliveries use Slack Block Kit (subject, to, from, email id). HMAC signing headers are not sent — Slack authenticates via the secret token in the URL path.
  • Use Send test event on the webhook to confirm the channel receives messages before going live.

Event types

Subscribe to one or more of these when creating a webhook:

  • delivery
  • bounce
  • complaint
  • open
  • click

Payload shape

Each delivery is a POST with a JSON body:

{
  "type": "delivery",
  "data": { /* event-specific fields */ },
  "timestamp": "2026-05-19T12:00:00.000000"
}

Security

Webhook deliveries are signed. Open a webhook’s Details page to view or rotate the signing secret. Validate every request before trusting the body.

Request headers:

  • X-Webhook-Signature — HMAC-SHA256 hex digest of the raw JSON body
  • X-Webhook-Timestamp — UTC ISO timestamp when the delivery was sent
  • X-Webhook-Delivery-Id — unique id for this delivery attempt (support and logs)
  • User-AgentPiisend-Webhooks/1.0 (not your app server fingerprint)
import crypto from "crypto";

function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Source IP and egress

Outbound webhooks are HTTPS POSTs from Piisend infrastructure. The TCP source IP your server logs is our egress address, not something to use for authentication.

  • Verify signatures, not source IP. IPs can change when we scale or rotate egress.
  • Self-hosted operators can set WEBHOOK_HTTP_PROXY so deliveries exit through a dedicated proxy or NAT (stable Elastic IP) instead of the main API/worker hosts.
  • Redirects are not followed on delivery; register the final HTTPS URL you intend to receive events on.

Testing

Use the test action from the webhooks table to send a sample payload to your URL and confirm connectivity, TLS, and signature verification in your environment.

See also

Logs for in-app timelines in addition to outbound webhooks.

Documentation

Integrate with the REST API

Quickstart, API reference, and webhooks—everything you need to send from your app.