Webhooks

Receive real-time notifications when events happen in your newsletter.

Setting Up Webhooks

Via Dashboard

  1. Go to your newsletter → Settings → Webhooks
  2. Click "Add Webhook"
  3. Enter your endpoint URL
  4. Select events to subscribe to
  5. Save the webhook

Via API

POST /api/v1/webhook_subscriptions

{
  "url": "https://your-app.com/webhooks/dailydraft",
  "events": ["subscription.created", "issue.sent"]
}

Available Events

Event Description
subscription.created New subscriber added
subscription.unsubscribed Subscriber unsubscribed
subscription.bounced Email bounced (hard bounce)
issue.sent Issue finished sending
email.opened Subscriber opened email
email.clicked Subscriber clicked a link

Webhook Payload

All webhooks follow this format:

{
  "event": "subscription.created",
  "timestamp": "2025-01-10T12:00:00Z",
  "newsletter_id": 123,
  "data": {
    // Event-specific data
  }
}

Event Payloads

subscription.created

{
  "event": "subscription.created",
  "timestamp": "2025-01-10T12:00:00Z",
  "newsletter_id": 123,
  "data": {
    "subscription_id": 456,
    "email": "[email protected]",
    "name": "New User",
    "tags": [],
    "source": "api"
  }
}

subscription.unsubscribed

{
  "event": "subscription.unsubscribed",
  "timestamp": "2025-01-10T12:00:00Z",
  "newsletter_id": 123,
  "data": {
    "subscription_id": 456,
    "email": "[email protected]",
    "reason": "user_request"
  }
}

issue.sent

{
  "event": "issue.sent",
  "timestamp": "2025-01-10T12:00:00Z",
  "newsletter_id": 123,
  "data": {
    "issue_id": 42,
    "subject": "Weekly Newsletter #42",
    "total_sent": 1500,
    "sent_at": "2025-01-10T09:00:00Z"
  }
}

email.opened

{
  "event": "email.opened",
  "timestamp": "2025-01-10T12:05:00Z",
  "newsletter_id": 123,
  "data": {
    "issue_id": 42,
    "subscription_id": 456,
    "email": "[email protected]",
    "opened_at": "2025-01-10T12:05:00Z"
  }
}

email.clicked

{
  "event": "email.clicked",
  "timestamp": "2025-01-10T12:10:00Z",
  "newsletter_id": 123,
  "data": {
    "issue_id": 42,
    "subscription_id": 456,
    "email": "[email protected]",
    "link_url": "https://example.com/article",
    "clicked_at": "2025-01-10T12:10:00Z"
  }
}

Webhook Security

Signature Verification

Each webhook includes a signature header for verification:

X-DailyDraft-Signature: sha256=abc123...

Verify the signature:

require 'openssl'

def verify_webhook(payload, signature, secret)
  expected = "sha256=" + OpenSSL::HMAC.hexdigest(
    'sha256',
    secret,
    payload
  )

  Rack::Utils.secure_compare(expected, signature)
end

IP Allowlisting

DailyDraft webhooks come from these IP addresses:

34.102.136.0/24
35.190.0.0/24

Retry Policy

Failed webhooks are retried with exponential backoff:

  • 1st retry: 1 minute
  • 2nd retry: 5 minutes
  • 3rd retry: 30 minutes
  • 4th retry: 2 hours
  • 5th retry: 24 hours

After 5 failed attempts, the webhook is marked as failed.

Success Response

Return a 2xx status code to acknowledge receipt:

HTTP/1.1 200 OK
{"received": true}

Managing Webhooks via API

List Webhooks

GET /api/v1/webhook_subscriptions

Create Webhook

POST /api/v1/webhook_subscriptions

{
  "url": "https://your-app.com/webhooks",
  "events": ["subscription.created", "subscription.unsubscribed"]
}

Delete Webhook

DELETE /api/v1/webhook_subscriptions/:id

Testing Webhooks

Use the dashboard to send test events:

  1. Go to Settings → Webhooks
  2. Click "Test" on any webhook
  3. Select an event type
  4. Click "Send Test"

Or use a tool like webhook.site to inspect payloads.

Still need help?

Can't find what you're looking for? Chat with our AI assistant or create a support ticket.

Sign in to get support