Skip to main content

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.

For the endpoint spec (URL, auth, request/response shapes, examples), see Send Lead Event. This page covers when to send events, how to configure a campaign send to consume them, and the patterns the time-window filter is designed for.

Why

Some sends should depend on what a lead has done, not just which audience they’re in:
  • “Don’t send the May 17 ‘introducing Mastery’ message to anyone who already purchased it.”
  • “For the +2hr ‘you can still join’ reminder, skip phones currently in the live event.”
You record those signals as lead events — small per-phone records like mastery_purchase or webinar_attended, each with a timestamp. At send-fire time, the campaign send filters its audience based on those events.

Real-time vs bulk

The endpoint accepts either pattern — both produce the same rows, the filter logic doesn’t care.
  • Real-time stream — POST one event at a time as it happens (a purchase completes, a phone joins the live event). Best when you want the freshest possible data without a polling loop.
  • Bulk batch — POST up to 50,000 events in one call. Best when your source system aggregates and you’d rather push periodically than per-event.
If you POST the same (phoneE164, eventType, occurredAt) more than once, the duplicate is silently dropped. Retries are safe.

Configuring a send to consume events

When adding a send to your campaign sequence, 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 strings you POST (case-sensitive).
  • Within last (minutes, optional) — only consider events whose occurredAt is within this many minutes of the send firing.
The filter is applied at send-materialize time, ~60 seconds before the scheduled fire time.

Sticky vs windowed events

Whether to use the time window depends on the event’s meaning:
PatternFilter configUse when
Sticky (no window){ mode: "exclude", eventType: "mastery_purchase" }The event is permanent — once it happens, the lead is “done” forever.
Windowed (with within.minutes){ mode: "exclude", eventType: "webinar_attended", within: { minutes: 120 } }The event is temporary — “currently attending” only matters for ~2hrs.
Without a window, “ever happened” matches. With a window, only events whose occurredAt falls inside the last N minutes from send-fire time match.

Common patterns

Exclude prior purchasers across a multi-day campaign:
{ "mode": "exclude", "eventType": "mastery_purchase" }
No window — once a lead purchases, they stop receiving the upsell sequence on every subsequent day. Skip people in the live event for the “you can still join” reminder:
{ "mode": "exclude", "eventType": "attended", "within": { "minutes": 120 } }
Window matches today’s session only. Yesterday’s attendees who haven’t joined today still receive the reminder. Only message engaged leads (opt-in confirmation campaign):
{ "mode": "include", "eventType": "double_opt_in_confirmed" }
Sends only to leads who completed the confirmation step.

Combining with audience filtering

A send can have both an event filter (this page) and an audience filter configured. Both must keep a recipient for them to receive the message — the filters are ANDed.

Phone normalization

phoneE164 values you POST go through libphonenumber. Both +15551234567 and 15551234567 parse to the same canonical E.164. Numbers that don’t parse are reported per-row in the response’s rejects[] rather than failing the whole batch.