Derived rules
Define custom "entered / exited a segment" events that fire automatically from your existing event stream, without changing your integration.
A derived rule watches a subject (an identified user or an account/tenant) for a
condition on its subscribed anchor events, and emits a brand-new event of your own
naming when that condition is met — a high_value_order event, say, fired the moment an
order’s own amount property crosses a threshold, with no client-side code change
required.
The condition is evaluated against the anchor event that just arrived: its name, its timestamp, its own properties, and a few profile facts. A rule cannot sum or count across a subject’s past events, so a threshold has to be one the triggering event carries by itself — see Worked example and Guardrails.
Prerequisites
Section titled “Prerequisites”- The anchor event(s) the rule subscribes to already flowing through Sending events — a rule can only watch events that exist.
Authentication
Section titled “Authentication”Every endpoint on this page is a Management API call — host https://retidal.com,
authenticated with the trackly_session cookie from a logged-in console user and your
project role. There is no API-key path here; see Authentication
for the full session-vs-key model.
Listing rules
Section titled “Listing rules”GET https://retidal.com/api/projects/{projectId}/derived-rulesReturns every derived rule configured for the project. Console → Projects → Derived Rules shows the same list, with rule type, subject, and enabled/disabled state.
Creating a rule
Section titled “Creating a rule”POST https://retidal.com/api/projects/{projectId}/derived-rulesruleTypebodystringrequiredevent_condition (fires when a subscribed event’s condition matches) or absence
(fires when a subject has produced none of the subscribed events for longer than
absenceThresholdSeconds).
subjectTypebodystringrequiredidentified_user or account.
subscribedEventsbodyarrayrequiredThe anchor event names this rule watches. A derived event itself cannot be subscribed to — Retidal rejects a rule that would create a cycle.
outputEventNamebodystringrequiredThe name of the new event this rule emits. Must not collide with an existing non-derived event name in the project.
POST /api/projects/{projectId}/derived-rules returns 409 if the project’s rule-count
cap is reached, and 422 if the body fails validation, creates a subscription cycle, or
the output event name conflicts with an existing one.
Rule detail and updates (optional)
Section titled “Rule detail and updates (optional)”GET https://retidal.com/api/projects/{projectId}/derived-rules/{id}PATCH https://retidal.com/api/projects/{projectId}/derived-rules/{id}GET returns one rule’s full detail. PATCH updates mutable fields only — ruleType,
subjectType, and outputEventName are immutable after creation; create a new rule
instead of trying to change them.
Enabling and disabling a rule (optional)
Section titled “Enabling and disabling a rule (optional)”POST https://retidal.com/api/projects/{projectId}/derived-rules/{id}/enableStarts or stops a rule. A disabled rule stops evaluating incoming events entirely — it does not queue or backfill events that arrived while disabled.
What this unlocks
Section titled “What this unlocks”A derived rule turns a pattern in your existing event stream into a first-class event name you can subscribe Event mappings or an automation to, without instrumenting a new client-side call for it.
Verify it worked
Section titled “Verify it worked”Confirm the rule is enabled
Console → Projects → Derived Rules shows the rule with its enabled/disabled state. Equivalently, from a browser session already logged into the console (so the
trackly_sessioncookie is sent automatically):bash curl -s https://retidal.com/api/projects/{projectId}/derived-rules/{id} \-H "Cookie: trackly_session=$SESSION_COOKIE"# expect: 200 with "enabled": trueSend an event that satisfies the rule's condition
Send one of the rule’s
subscribedEventsvia Sending events, with a property value that makes the condition true (for the worked example below, achat.completedevent withtokensat least 2000) — the condition is evaluated only against that event’s own properties, not a running total.Confirm the output event appears
Check Event catalog (or
GET /api/projects/{projectId}/project-events) for the rule’soutputEventNameappearing with recent volume.
If it doesn’t work
Section titled “If it doesn’t work”If the rule never fires — the derived event itself never arrives — work through Events not arriving; the rule not firing is the same “expected event never showed up” symptom that page diagnoses.
Worked example
Section titled “Worked example”A rule that emits user.heavy_session whenever an identified user sends a
chat.completed event whose own tokens property is at least 2000 — the rule engine
only ever sees the anchor event’s own name, timestamp, and properties (plus a few
profile facts), not a cumulative count across past events, so the condition must be
evaluated against a fact the triggering event actually carries:
{ "name": "Heavy sessions", "ruleType": "event_condition", "subjectType": "identified_user", "subscribedEvents": ["chat.completed"], "condition": { "all": [ { "fact": "event.tokens", "op": "gte", "value": 2000 } ] }, "outputEventName": "user.heavy_session", "outputEventCategory": "Engagement", "enabled": true}Guardrails
Section titled “Guardrails”outputEventName is checked against every existing non-derived event name in the
project at creation time, but not re-checked if a matching event name is introduced
later — naming a derived event too generically (completed, active) risks a silent
future naming collision once that name is claimed elsewhere. Prefer a namespaced
output name (user.power_user, not power_user). Separately, subscribedEvents cannot
include another derived event — POST /api/projects/{projectId}/derived-rules rejects
that at creation with 422, preventing an infinite derivation loop where rule A’s
output feeds rule B whose output feeds rule A.
Next steps
Section titled “Next steps”See a derived event’s volume and downstream consumers once it starts firing.
Map a derived event onto a standard event for ad-platform reporting.