Skip to content

Webhooks

Webhooks let you pipe campaign delivery outcomes to external systems. When a campaign completes (or at any configured workflow step), Pidgr POSTs delivery data to your endpoint.

  1. Add a CALL_WEBHOOK step to your campaign’s workflow definition
  2. When the step executes, Pidgr POSTs delivery outcome data to the configured URL
  3. Your endpoint processes the payload and returns a 2xx status

Webhooks are configured as workflow steps in the campaign’s workflow definition:

{
"id": "webhook-step",
"type": "CALL_WEBHOOK",
"config": {
"name": "Slack Notification",
"url": "https://hooks.example.com/pidgr-results",
"headers": {
"Authorization": "Bearer your-webhook-secret",
"X-Custom-Header": "custom-value"
}
},
"transitions": {}
}
FieldDescriptionConstraints
nameHuman-readable name for loggingMax 200 characters
urlHTTPS endpoint to POST toMax 2048 characters, HTTPS required
headersAdditional HTTP headersMax 20 entries

The webhook POST body contains the campaign delivery outcomes:

{
"campaign_id": "campaign-uuid",
"campaign_name": "Q1 Security Update",
"deliveries": [
{
"delivery_id": "delivery-uuid",
"user_id": "user-uuid",
"status": "ACKNOWLEDGED",
"sent_at": "2026-01-15T10:00:00Z",
"acknowledged_at": "2026-01-15T10:30:00Z"
},
{
"delivery_id": "delivery-uuid-2",
"user_id": "user-uuid-2",
"status": "MISSED",
"sent_at": "2026-01-15T10:00:00Z"
}
],
"summary": {
"total": 150,
"acknowledged": 120,
"missed": 25,
"failed": 5
}
}

Pidgr enforces strict SSRF (Server-Side Request Forgery) protections on webhook URLs:

The following are rejected in production:

  • Private IPs10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • Loopback127.0.0.0/8, ::1
  • Localhostlocalhost, 0.0.0.0
  • Link-local169.254.0.0/16
  • URLs must use HTTPS in production
  • URLs are validated at campaign creation time and again at execution time
  • DNS resolution is checked against the blocked IP ranges

Webhook calls follow a best-effort delivery model:

  • Timeout — 30 seconds per request
  • Retries — Failed calls are retried automatically with exponential backoff
  • Idempotency — Your endpoint should handle duplicate deliveries gracefully

If a webhook call fails after retries:

  • The workflow step is marked as failed
  • The campaign continues to completion (webhook failure doesn’t block other steps)
  • Failed webhook calls are visible in the campaign’s activity log
  • Use HTTPS — Always use TLS-encrypted endpoints
  • Verify the source — Include a secret in the Authorization header and validate it on your end
  • Validate payloads — Parse and validate the JSON structure before processing
  • Respond quickly — Return 2xx within the timeout period; process asynchronously if needed
  • Handle duplicates — Use delivery_id as an idempotency key