Business· Help center

Help center › Importing & exporting

How to get cold email events with webhooks

Settings → Integrations → Webhooks. Otto sends your own system a signed message the moment someone replies, a reply is sorted, a lead is kept, or a campaign starts or finishes.

Updated 2026-10-31

A webhook is an address on your own system, or your developer's, that Otto calls when something happens in cold email. Your system hears about a reply the moment it arrives, without asking Otto again and again. Only someone who manages the business can add one.

Every route, with what it takes and gives back, is in the API reference.

Add a webhook

  1. Open Settings → Integrations and scroll to Webhooks.
  2. Type the address. It must start with https:// and be on the public internet: Otto refuses a private or local address.
  3. Tick the events you want, at least one.
  4. Press Add webhook, then Copy secret.

The secret is shown once. Otto keeps it encrypted and cannot show it again: if you lose it, remove the webhook and add it again. A business can have 5 webhooks.

The events

  • Someone replied (reply.received): their words (up to 5,000 characters), the subject, the campaign, and the person's name, email and company.
  • A reply was sorted (reply.sorted): which reply, and the kind Otto gave it, such as interested or not now.
  • A found lead was kept (lead.kept): the campaign and the businesses you kept (keeping is free, so credits are always 0). When the lead agent keeps them, how many it added.
  • A campaign started (campaign.started): the campaign, and how many businesses it writes to.
  • A campaign finished (campaign.finished): the campaign, once nobody in it has anything left to be sent.

Each message is a POST with JSON in the body: {"id": 123, "event": "reply.received", "at": "...", "data": {...}}. id is the same number as the X-Otto-Delivery header.

Check it came from Otto

Every message carries three headers:

  • X-Otto-Event: the event, such as reply.received.
  • X-Otto-Delivery: a number for this message. A message tried again keeps its number, so your system can skip one it already has.
  • X-Otto-Signature: sha256= followed by the HMAC-SHA256 of the raw body, made with your secret.

On your side, work out the same HMAC-SHA256 of the body exactly as it arrived, with your secret, and compare. If they differ, ignore the message. Work it out before your code reads the JSON, because reading and writing it again can change the bytes.

Test it

Press Send a test beside the webhook. Otto sends one message with the event test, signed the same way, and shows what your address answered.

When your address does not answer

Any answer from 200 to 299 counts as received. Anything else, or no answer within 10 seconds, is tried again later, up to four tries in all, waiting longer each time: about 15 minutes, then 45, then a little over two hours. Otto never follows a redirect.

After 20 failures in a row, Otto switches the webhook off and sends you a notice. Fix your address, then switch it on again under Webhooks. The last answer is shown beside each webhook.

A tool such as Zapier can also add and remove its own webhook with an API key. Those show here too, marked as added with an API key, and stop if that key is revoked. See how to connect Otto to Zapier.

To use the cold email services from your own code as well, see how to use the cold email API.