Skip to main content
POST
/
api
/
v1
/
webhooks
/
lead-events
curl --request POST \
  --url https://chat.trysetter.com/api/v1/webhooks/lead-events \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "organizationId": 42,
  "eventType": "mastery_purchase",
  "events": [
    {
      "phoneE164": "+15551234567",
      "occurredAt": "2026-05-12T18:34:00Z",
      "metadata": {
        "orderId": "ord_9F2",
        "amountUsd": 297
      }
    }
  ]
}
'
{
  "status": "accepted",
  "received": 3,
  "inserted": 3,
  "duplicates": 0,
  "rejected": 0,
  "rejects": []
}

Documentation Index

Fetch the complete documentation index at: https://docs.trysetter.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Generic per-phone event stream. Use this to tell Setter “this phone number did event X at time T” so future campaign sends can include or exclude that lead based on whether the event happened (optionally within a time window). Typical event types: mastery_purchase, webinar_attended, trial_started, cart_abandoned. You choose the names — they’re free strings scoped to your organization.
Shape-agnostic: this endpoint accepts either real-time per-event POSTs (one event per call) or bulk batches (up to 50,000 events per call). Both produce the same rows; the filter logic doesn’t care which shape was used.

Authentication

Pick the auth mode for inbound webhooks once per organization, in Settings → Webhooks:
  • API key (default) — Bearer-token auth using any active org-level API key.
  • HMAC — generate a signing key, sign the raw request body with HMAC-SHA256, send as X-Setter-Signature: sha256=<hex>. Multiple signing keys can be active concurrently for rotation.

How sends consume these events

When configuring a send under Campaigns → Sequence → Add a send, enable Event filter and pick:
  • Modeexclude (skip leads that have the event) or include (only send to leads that have the event).
  • Event type — must match the eventType you POST.
  • Within last (minutes, optional) — only consider events whose occurredAt is within this many minutes of the send firing.
Examples:
  • Skip anyone who’s ever purchased Mastery: { mode: "exclude", eventType: "mastery_purchase" } (no window — sticky event)
  • Skip anyone currently in the live event: { mode: "exclude", eventType: "webinar_attended", within: { minutes: 120 } } (windowed — “currently attending”)
The filter is applied at send-materialize time alongside any audience-filter event. Both filters can be active on the same send and are ANDed.

Idempotency and validation

The unique key (organizationId, phoneE164, eventType, occurredAt) makes retries safe — re-POSTing the same batch returns duplicates = received and inserted = 0. Invalid rows (bad phone, missing/invalid occurredAt, oversize metadata) are rejected per-row, not per-batch — you get a structured rejects[] array back rather than a 400 for the whole call. The first 50 rejection reasons are returned for debugging.

Phone normalization

phoneE164 is parsed via libphonenumber. Accepts the value with or without leading + and tolerates common formatting variants. Numbers that don’t parse are reported in rejects[] with reason invalid phoneE164.

Caps

LimitValue
Events per request50,000
Request body size10 MB
eventType length128 chars
metadata per event (encoded)8 KB

Example Usage

Real-time single event (Bearer API key)

curl -X POST https://chat.trysetter.com/api/v1/webhooks/lead-events \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "organizationId": 42,
    "eventType": "mastery_purchase",
    "events": [
      {
        "phoneE164": "+15551234567",
        "occurredAt": "2026-05-12T18:34:00Z",
        "metadata": { "orderId": "ord_9F2", "amountUsd": 297 }
      }
    ]
  }'

Bulk batch (HMAC signature)

SECRET="your-signing-secret"
BODY='{"organizationId":42,"eventType":"webinar_attended","events":[{"phoneE164":"+15551234567","occurredAt":"2026-05-15T13:00:00Z"},{"phoneE164":"+447700900123","occurredAt":"2026-05-15T13:05:11Z"}]}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -binary | xxd -p -c 256)

curl -X POST https://chat.trysetter.com/api/v1/webhooks/lead-events \
  -H "Content-Type: application/json" \
  -H "X-Setter-Signature: sha256=$SIG" \
  --data-raw "$BODY"

Authorizations

Authorization
string
header
required

Bearer token authentication using your API key

Body

application/json
organizationId
integer
required

Your Setter organization ID. Auth credentials must match this org.

eventType
string
required

Free string scoped to your org. We recommend snake_case (e.g. mastery_purchase).

Maximum string length: 128
events
object[]
required
Required array length: 1 - 50000 elements

Response

Batch processed. Inspect inserted / duplicates / rejected for outcome detail.

status
enum<string>
Available options:
accepted
received
integer

Number of entries in the input events array.

inserted
integer

Newly stored rows.

duplicates
integer

Entries that collided with an existing (organizationId, phoneE164, eventType, occurredAt) row.

rejected
integer

Entries that failed validation (bad phone, invalid date, oversize metadata).

rejects
object[]

First 50 rejected entries with a reason (debugging aid).