Events & automation
POST /api/v1/events, conversions and attribution, automations (conditions, delays, cancelOn) and auto-capture.
POST /api/v1/events — send a behavioral event from your server (scope events:write; the browser SDK's track() uses a public route instead). Name the person with externalId (your user id) or subscriberId (relaybell's id); an event that names nobody is stored but only a product alert can come of it.
{ "event": "purchase", "externalId": "user_123", "properties": { "value": 79.99, "orderId": "A123" } }It answers 202 (400 event_required without a name; name works as another spelling of event; names are cut to 120 characters):
{ "ok": true, "eventId": "1234", "subscriberId": "…", "isConversion": true,
"attribution": { "notificationId": "5b0c2f7e-…", "value": 79.99 },
"automationsTriggered": 0, "sequencesEnrolled": 0 }Conversions: purchase, order.completed and checkout.completed count as conversions (or the list in your conversionEvents setting), and so does any other event with a numeric value or revenue property — except the funnel steps cart.updated and checkout.started. A conversion is credited, with its value, to the last notification delivered to that subscriber in the previous 7 days (attributionWindowDays setting). GET /api/v1/events (scope subscribers:read) lists the latest 100 events.
Automations
/api/v1/automations — one push to a person when they do something: an event arrives, the optional delay passes, the message goes out. This powers cart abandonment (a purchase cancels the reminder), back-in-stock and price-drop (see Product alerts), and welcome-back flows. Each event fires every enabled automation with that event name whose conditions match.
POST /api/v1/automations
{ "name": "Cart abandon", "event": "cart.updated", "delaySeconds": 3600, "cancelOn": "purchase",
"conditions": [ { "field": "cartTotal", "op": "gte", "value": 20 } ],
"action": { "title": "You left {product|something} in your cart 🛒", "body": "Complete your order before it's gone.", "url": "{url}" } }| Field | Description |
|---|---|
event * | The event name that starts it (400 event_required). |
action * | { title, body, url, icon } — title is required (400 action_title_required). Merge tags take values from the triggering event's properties: {product}, {url}, {price|}, … |
name | Up to 120 characters (default "Automation"). |
delaySeconds | Wait before sending (default 0). With a delay, a newer event from the same person replaces their pending one, so three cart updates make one reminder, timed from the last. |
cancelOn | An event name that cancels the person's pending (delayed) push, e.g. purchase. |
conditions | A list of { field, op, value } checked against the event's properties; all must match. op: eq (default), neq, contains (case-sensitive), exists, and the number comparisons gt, gte, lt, lte. Empty or left out: every event matches. |
oncePerSubscriber | true = at most once per person, ever (a pending or sent one blocks the next). |
enabled | Default true; false pauses it (pending pushes are dropped when they come due). |
PUT /api/v1/automations/:id replaces the automation with the body you send — enabled goes back to true unless you send false — except conditions, which are kept when the body has no conditions key. GET /api/v1/automations lists them with sent (all-time deliveries) and stats30d { sent, clicks, ctr, conversions, revenue }; GET /api/v1/automations/:id returns one; DELETE removes one. Writes need settings:write. Automation pushes follow your quiet hours and frequency cap, and never go to someone who has unsubscribed.
Auto-capture & Google Tag Manager
Rather than call track() by hand everywhere, opt in and relaybell records pageviews, declarative clicks and scroll depth for you — only for subscribed or identified visitors, so anonymous traffic makes no noise. The events are page_view { url, path, title } (also on single-page-app route changes), your own data-rb-event names, and scroll_depth { percent } at 25, 50, 75 and 100%:
RelayBell.init({ projectId: "YOUR_PROJECT_ID", apiBase: "https://relaybell.com", autoCapture: true });
// granular: autoCapture: { pageviews: true, clicks: true, scroll: true }
// Track any click declaratively — the other data-rb-* attributes become event properties
// (data-rb-sku → sku, data-rb-unit-price → unit_price; values are text):
<button data-rb-event="add_to_cart" data-rb-sku="TEE-01" data-rb-price="19.99">Add to cart</button>Mirror events from Google Tag Manager / GA. You can't trigger push directly from Google Analytics or Meta Pixel — those are analytics and ad tools, not real-time per-user event buses, and their terms don't allow using that data to message individuals. Instead, fire the same events you already track into relaybell too, most easily via a GTM Custom HTML tag on your existing dataLayer events, then segment and automate on them here:
<script>/* GTM Custom HTML tag, fired on your event trigger.
{{Event}} is GTM's built-in variable holding the dataLayer event name. */
if (window.RelayBell) RelayBell.track({{Event}}, {});</script>To send details with the event, replace {} with an object built from your own Data Layer Variables, for example { productId: {{DLV - productId}} }.