Skip to main content
Outbound webhooks are available on Standard and Pro plans.

Overview

Outbound webhooks deliver real-time event notifications to your external systems — CRMs, Zapier, n8n, HubSpot, or custom backends. When something happens (a lead is created, an appointment is booked), SetterMaxer sends an HTTP POST to your configured URL.

Events

Every event carries a lead_id and the person’s full current record under data.lead, so any subscription can create or update a CRM contact without a second lookup.

lead.contacted

Fires the first time a person actually engages — either they send a first message, or an automatic outbound WhatsApp message reaches them.
This follows first contact, not row creation. Importing a CSV creates contacts and fires nothing. If automatic contact is switched on, those imported contacts do fire lead.contacted later, as each outbound message is accepted for delivery.
It fires once per person per agent, ever. Deleting a contact and having them come back does not fire it again; the same person engaging a second agent does. data.initiated_by tells the two paths apart: inbound when the person messaged first, outbound when an automatic-contact message reached them — a distinction the channel alone cannot make.

lead.updated

Fires when your agent establishes something about the person: a captured detail, a tag applied during a conversation, a qualification result, the AI summary, or the lead score. changed_fields names what moved, and previous carries the prior values of just those keys — enough to update the record you created earlier rather than adding a second one.
When the AI summary or lead score changes, data also carries summary and summary_text. Those are per-conversation rather than per-person, which is why they sit outside data.lead.
Edits you make by hand do not fire this event — not in the Leads table, not in bulk, and not by import, API or Zapier. The event means your agent established something. One bulk edit can cover a thousand contacts, and firing per row would deliver a thousand messages for one click.

Appointments

Both appointment events carry the meeting itself, so a receiver can create a dated task or calendar entry without a second lookup. appointment.rescheduled adds the times the meeting moved from, so you can find and update the entry you created earlier instead of adding a second one.
appointment.booked sends the same fields minus the previous_* pair, with booked_at in place of rescheduled_at.
The appointment_* fields can be empty. Calendly booking links and Acuity only fill in what the provider returns. appointment_url is whichever link is most useful for that provider — the calendar event for Google, the invitee’s page for Calendly — the same link the app shows as View appointment. appointment_meeting_url is the video-call link (Google Meet, or the agent’s Zoom or Microsoft Teams link) when the booking has one, and null otherwise.

Configure webhooks

Go to Organisation Settings → Webhooks (admin/owner required).
1

Add endpoint

Click Add endpoint and enter your webhook URL (HTTPS required).
2

Select events

Choose which events to subscribe to.
3

Scope to a agent (optional)

Optionally limit the webhook to a specific agent. Leave blank to receive events from all agents.
4

Save

Your signing secret is displayed once. Copy and store it securely.
The signing secret (format whsec_...) is shown only at creation time. If you lose it, use Regenerate Secret to create a new one.

Payload format

Every webhook delivery sends a JSON envelope:
The id is the same across all fan-out deliveries for one logical event, so your system can deduplicate. Match records on lead_id. It identifies the person and is stable across everything they do. conversation_id identifies one conversation, and a person has one per channel — so someone who starts on your website widget and later books over WhatsApp will arrive with a conversation_id you have never seen, but the same lead_id. conversation_id is the identifier shown as Conversation ID in the conversation details panel.
On lead.contacted, conversation_id is the conversation the contact was first captured in. It is the one event where the field can be null — imported contacts have no conversation until they reply, and the field is cleared if that conversation is later deleted.
The keys under custom_fields are the columns you configured for that agent, so they differ per agent, and a value the lead has not given is absent rather than empty.

Signature verification

Every delivery includes an HMAC-SHA256 signature in the X-SetterMaxer-Signature header:
Verify the signature by computing HMAC-SHA256(signing_secret, raw_request_body) and comparing.

Additional headers

Retry policy

Failed deliveries are retried up to 5 times with exponential backoff: After 5 failed attempts, the delivery is marked as dead and not retried. A delivery is considered failed if your endpoint returns a non-2xx status code or doesn’t respond within 10 seconds.

Testing

Click Test on any webhook endpoint to send a synthetic test event. This inserts a test delivery and triggers immediate dispatch so you can verify your integration without waiting for a real event.

Limits