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.
How Webhooks Work
Section titled “How Webhooks Work”- Add a
CALL_WEBHOOKstep to your campaign’s workflow definition - When the step executes, Pidgr POSTs delivery outcome data to the configured URL
- Your endpoint processes the payload and returns a 2xx status
Configuration
Section titled “Configuration”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": {}}Configuration Fields
Section titled “Configuration Fields”| Field | Description | Constraints |
|---|---|---|
name | Human-readable name for logging | Max 200 characters |
url | HTTPS endpoint to POST to | Max 2048 characters, HTTPS required |
headers | Additional HTTP headers | Max 20 entries |
Payload Format
Section titled “Payload Format”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 }}SSRF Protection
Section titled “SSRF Protection”Pidgr enforces strict SSRF (Server-Side Request Forgery) protections on webhook URLs:
Blocked Destinations
Section titled “Blocked Destinations”The following are rejected in production:
- Private IPs —
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 - Loopback —
127.0.0.0/8,::1 - Localhost —
localhost,0.0.0.0 - Link-local —
169.254.0.0/16
Requirements
Section titled “Requirements”- 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
Retry Behavior
Section titled “Retry Behavior”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
Handling Failures
Section titled “Handling Failures”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
Security Best Practices
Section titled “Security Best Practices”- Use HTTPS — Always use TLS-encrypted endpoints
- Verify the source — Include a secret in the
Authorizationheader 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_idas an idempotency key