← Help Center

Using Webhooks to Receive Real-Time Events

Create webhook endpoints in ColdSend, subscribe to email and lead events, verify signatures, and monitor deliveries

Automation & Webhooks9 min readUpdated Aug 9, 2026

Webhooks let ColdSend notify your own applications in real time whenever something happens in your workspace — an email is sent, a lead replies, a link is clicked, a lead unsubscribes, and more. Instead of polling the API, ColdSend sends an HTTP POST request to your endpoint the moment the event occurs.

This guide walks you through creating a webhook, choosing which events to receive, verifying that requests really come from ColdSend, and troubleshooting failed deliveries.

When to Use This

Use webhooks if you:

  • Want to sync lead/reply data into your CRM or internal tools the moment it happens
  • Need to trigger automations (e.g., notify Slack when a lead replies, update a spreadsheet when a lead unsubscribes)
  • Want to track engagement in real time (opens, clicks, bounces) without polling
  • Are building a custom integration on top of ColdSend's campaign engine

Prerequisites

  • A ColdSend account with access to Settings → Webhooks
  • A publicly reachable HTTPS endpoint that can accept POST requests (plain http:// URLs are not accepted)
  • Your endpoint must respond within 10 seconds with a 2xx status code for deliveries to count as successful

💡 Tip: Don't have an endpoint ready yet? You can use a service like webhook.site or RequestBin to inspect ColdSend's requests while you build your integration.


Step 1: Open the Webhooks Settings

  1. Log into your ColdSend account.
  2. In the left sidebar, go to Settings.
  3. Select the Webhooks tab.

You'll see a list of your existing webhooks (if any), along with each one's status and last delivery result.

Webhooks Settings Page


Step 2: Create a Webhook

  1. Click the Create Webhook button.

  2. Fill in the dialog:

    Field Description
    Name A friendly label for this webhook (e.g., "CRM Sync")
    Endpoint URL The HTTPS URL where ColdSend will POST events
    Event Types Which events this webhook should receive
  3. Select one or more event types, or use Select All Events to subscribe to everything.

Create Webhook Dialog

  1. Click Create Webhook.

Available Event Types

Event Sent When
Reply Received A lead replies to an email
Email Bounced An email bounces
Lead Unsubscribed A lead unsubscribes
Email Sent An email is successfully sent
Email Delivered Delivery is confirmed
Email Opened An email is opened
Link Clicked A link in an email is clicked
Lead Status Changed A lead's status changes

Step 3: Save Your Signing Secret

After the webhook is created, ColdSend shows your signing secret exactly once:

Signing Secret Dialog

⚠️ Important

The signing secret is only shown once and cannot be retrieved later. Copy it immediately and store it securely (e.g., in an environment variable or a secrets manager). You'll need it to verify that incoming requests genuinely come from ColdSend (see Step 5).

If you lose the secret, delete the webhook and create a new one to get a fresh secret.


Step 4: Send a Test Event

Before wiring up your integration, verify your endpoint works:

  1. Find your webhook in the list and click the Test action.
  2. ColdSend sends a ping event to your endpoint.
  3. The result shows the HTTP status code your endpoint returned.

Test Webhook

A test event looks like this:

{
  "event_type": "ping",
  "event_id": "a1b2c3d4-...",
  "occurred_at": "2026-08-09T10:00:00+00:00",
  "team_id": "your-team-id",
  "campaign_id": null,
  "data": { "message": "Webhook test from ColdSend" }
}

Your endpoint should return any 2xx status (e.g., 200 OK). Anything else is reported as a failure.


Step 5: Verify Request Signatures

Every webhook request includes an HMAC-SHA256 signature so you can confirm the request came from ColdSend and wasn't tampered with.

Request Headers

Header Description
X-ColdSend-Signature sha256= followed by the HMAC-SHA256 hex digest of the raw request body
X-ColdSend-Event The event type (e.g., reply_received)
X-ColdSend-Delivery-Id Unique ID for this delivery
X-ColdSend-Attempt Which delivery attempt this is (1 = first attempt)
User-Agent Always ColdSend-Webhooks/1

Verification Steps

  1. Read the raw request body as bytes (do not parse and re-serialize the JSON — formatting differences will break the signature).
  2. Compute HMAC-SHA256(body, signing_secret) using the secret from Step 3.
  3. Compare the result to the X-ColdSend-Signature header using a constant-time comparison.

Node.js example:

import crypto from "crypto";

function verifyColdSendSignature(req, secret) {
  const signature = req.headers["x-coldsend-signature"];
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(req.rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Python (FastAPI) example:

import hashlib
import hmac

def verify_coldsend_signature(body: bytes, secret: str, signature: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode("utf-8"), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

⚠️ Reject any request whose signature doesn't match — it did not come from ColdSend.


Step 6: Handle Incoming Events

All real events share the same envelope:

{
  "event_type": "reply_received",
  "event_id": "7f3a9c1e-...",
  "occurred_at": "2026-08-09T10:15:32+00:00",
  "team_id": "your-team-id",
  "campaign_id": "campaign-id-or-null",
  "data": { ... }
}

The data object differs per event type:

Event Type data Fields
email_sent lead_email, from_email, subject, sequence_step, message_id
email_delivered lead_email, delivered_at
email_opened lead_email, sequence_step, opened_at
link_clicked lead_email, link_index, url, clicked_at
email_bounced lead_email, bounce_type, status_message, sequence_step
reply_received lead_email, subject, reply_text, is_auto_reply, inbox_email
lead_unsubscribed lead_email, method
lead_status_changed lead_email, from_status, to_status

Example reply_received payload:

{
  "event_type": "reply_received",
  "event_id": "7f3a9c1e-...",
  "occurred_at": "2026-08-09T10:15:32+00:00",
  "team_id": "your-team-id",
  "campaign_id": "e9d8c7b6-...",
  "data": {
    "lead_email": "prospect@example.com",
    "subject": "Re: Quick question",
    "reply_text": "Sure, let's talk Thursday.",
    "is_auto_reply": false,
    "inbox_email": "alex@yourdomain.com"
  }
}

Best Practices for Your Endpoint

  • Respond fast: return 200 immediately and process the event asynchronously (e.g., push it to a queue). Requests that take longer than 10 seconds are treated as failures.
  • Be idempotent: ColdSend guarantees at-least-once delivery, so the same event may occasionally arrive twice. Use the event_id to deduplicate.
  • Return 2xx only on success: any 2xx counts as delivered; anything else is treated as a failure.

Step 7: Monitor Deliveries

Every webhook keeps a delivery log you can inspect from the Webhooks settings page:

  1. Click on a webhook to open its delivery history.
  2. Each entry shows the event type, status, HTTP response code, and any error.

Delivery Log

Delivery Statuses

Status Meaning
Succeeded Your endpoint returned a 2xx response
Failed Delivery failed — either a 4xx response (permanent, no retry) or a retryable failure still in progress
Dead All retry attempts were exhausted

Failed deliveries can be redelivered manually from the delivery log once you've fixed your endpoint.


Retries and Auto-Pause

ColdSend automatically retries failed deliveries with exponential backoff:

Attempt Timing
1st attempt Immediately when the event occurs
2nd attempt ~1 minute later
3rd attempt ~5 minutes later
4th attempt ~30 minutes later

Retry behavior depends on the failure type:

  • Timeouts, network errors, and 5xx responses → retried (up to 4 total attempts)
  • 4xx responses → treated as permanent failures and not retried (fix the client-side issue, then redeliver)

If a webhook produces 5 consecutive dead deliveries, ColdSend automatically pauses it to avoid hammering a broken endpoint. You can re-enable a paused webhook at any time from the Webhooks settings page.


Managing Webhooks

From the Webhooks settings page you can:

  • Edit — change the name, endpoint URL, or subscribed event types
  • Pause / resume — toggle a webhook on or off without deleting it
  • Delete — permanently remove a webhook (its signing secret is invalidated)

Webhook Actions

Note: Paused or deleted webhooks receive no events. Events that occur while a webhook is paused are not replayed when you resume it.


Troubleshooting

My endpoint never receives events

  • Verify the webhook is active (not paused) in the Webhooks settings page
  • Confirm the webhook is subscribed to the event types you expect
  • Ensure your endpoint is publicly reachable — ColdSend cannot reach localhost, private IPs, or VPN-only hosts
  • Check the delivery log for error details

Deliveries show "Request timed out"

Your endpoint took longer than 10 seconds to respond. Return 200 immediately and process the payload asynchronously.

Signature verification keeps failing

  • Use the raw request body bytes — re-serializing parsed JSON changes whitespace/key order and breaks the signature
  • Make sure you copied the secret correctly (no extra whitespace or newlines)
  • Remember the signature header is prefixed with sha256=

Deliveries fail with a 4xx response

4xx errors (e.g., 401, 404, 422) are permanent and are not retried. Fix the issue on your endpoint (auth, route, payload validation), then use redeliver from the delivery log.

My webhook got paused automatically

ColdSend auto-pauses a webhook after 5 consecutive dead deliveries. Check the delivery log for the underlying error, fix your endpoint, then re-enable the webhook.


FAQs

How many webhooks can I create? You can create multiple webhooks, each with its own endpoint and event-type selection — for example, one for your CRM and another for Slack notifications.

Do I receive events for all campaigns? Yes — a webhook receives events for your entire workspace (all campaigns), filtered only by the event types you selected.

What happens if my endpoint is down? ColdSend retries with exponential backoff (~1 min, ~5 min, ~30 min). If all retries fail, the delivery is marked dead. After 5 consecutive dead deliveries, the webhook is auto-paused.

Can I get a new signing secret for an existing webhook? No — secrets are shown once at creation and cannot be re-displayed or regenerated. Delete the webhook and create a new one to rotate the secret.

Are webhook deliveries guaranteed exactly once? No — delivery is at-least-once. Rarely, an event may be delivered twice. Deduplicate on your side using the event_id field.

Does ColdSend replay events that occurred before I created the webhook? No. You only receive events that occur after the webhook is created and active.

Related Guides