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:
deliverybouncecomplaintopenclick
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 bodyX-Webhook-Timestamp— UTC ISO timestamp when the delivery was sentX-Webhook-Delivery-Id— unique id for this delivery attempt (support and logs)User-Agent—Piisend-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_PROXYso 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.