Integrations

Webhooks

Cleanmails fires real-time webhook events when things happen in your outreach. Use webhooks to sync with CRMs, trigger automation platforms (Zapier, Make, n8n), or build custom dashboards.

Event Types

EventFired When
lead.repliedA lead replies to a campaign email
lead.bouncedEmail bounces (hard or soft)
lead.openedRecipient opens the email (tracking pixel loaded)
lead.clickedRecipient clicks a tracked link
lead.unsubscribedLead clicks the unsubscribe link
campaign.startedCampaign status changes to active
campaign.pausedCampaign is paused (manual or auto due to bounce rate)
campaign.completedAll leads processed through all steps
meeting.bookedLead thread marked as "Meeting Booked" in unibox

Creating a Webhook

bash
curl -X POST https://YOUR_SERVER/api/v1/workspaces/1/webhooks \
  -H "Content-Type: application/json" \
  -H "Cookie: auth_token=YOUR_JWT_TOKEN" \
  -d '{
    "url": "https://your-app.com/webhook/cleanmails",
    "secret": "your-hmac-signing-secret",
    "events": ["lead.replied", "lead.bounced", "meeting.booked"]
  }'
Event filtering

Specify which events you want to receive. Only matching events will be delivered to your endpoint.

Webhook Payload

POST to your URL
{
  "event": "lead.replied",
  "workspace_id": "uuid-here",
  "timestamp": "2026-05-12T14:30:00Z",
  "data": {
    "lead_email": "john@example.com",
    "lead_name": "John Smith",
    "company": "Acme Inc",
    "campaign_name": "Q2 Outreach",
    "snippet": "Thanks for reaching out! I'd love to learn more about..."
  }
}

Signature Verification

Every delivery includes an HMAC-SHA256 signature header for payload verification:

text
X-Webhook-Signature: sha256=a1b2c3d4e5f6...

Verify it server-side:

Node.js verification
const crypto = require('crypto');

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

Retry & Auto-Deactivate

  • Retries: Automatic retry with exponential backoff on failure
  • Auto-deactivate: After 10 consecutive failures, the webhook is automatically deactivated
  • Delivery logs: Each delivery attempt is logged with status code and response body
  • Re-enable: Fix your endpoint, then update the webhook to re-activate

Delivery Logs

bash
# View delivery history for a webhook
curl https://YOUR_SERVER/api/v1/workspaces/1/webhooks/WEBHOOK_ID/logs \
  -H "Cookie: auth_token=YOUR_JWT_TOKEN"

Logs include: timestamp, event type, HTTP status code, response body, and delivery duration.

Webhook Dispatch

Webhook payloads are delivered as background jobs via the Asynq worker queue. This ensures:

  • Webhook delivery doesn't block the main request flow
  • Failed deliveries are retried automatically
  • High-volume events don't overwhelm your endpoint

API Endpoints

MethodEndpointDescription
GET/api/v1/workspaces/:wid/webhooksList all webhooks
POST/api/v1/workspaces/:wid/webhooksCreate webhook
PUT/api/v1/workspaces/:wid/webhooks/:idUpdate webhook
DELETE/api/v1/workspaces/:wid/webhooks/:idDelete webhook
GET/api/v1/workspaces/:wid/webhooks/:id/logsView delivery logs

Using with Automation Platforms

Webhooks are the bridge to automation platforms:

PlatformSetup
ZapierUse "Catch Hook" trigger → paste the Zap webhook URL into Cleanmails
Make (Integromat)Use "Custom Webhook" module → paste the Make webhook URL
n8nUse "Webhook" node → paste the n8n webhook URL
ActivepiecesUse "Webhook Trigger" → paste the webhook URL

This lets you push Cleanmails events into any of the 5,000+ apps these platforms support.