Decide
Evaluate incentive/decision rules for a profile and event with POST /api/v1/decide.
POST /api/v1/decide runs Retidal’s incentive decision pipeline for one profile
and one event, and returns which rules matched — synchronously. The rules’
actual effects (like granting a coupon) are queued asynchronously; the response
tells you what matched, not that the effect has already been applied.
Call this when you need an answer in the moment — for example, deciding whether to show a discount banner when a user abandons checkout.
Endpoint
Section titled “Endpoint”POST https://api.retidal.com/api/v1/decideAuth: X-API-Key with scope decide or decision:call.
Rate limit: 30 requests/minute per (project, IP).
Request body
Section titled “Request body”projectIdbodystringrequiredMust match the API key’s own project — a mismatch on POST /api/v1/decide
returns 404, the same shape as “not found,” to avoid leaking whether a
project exists.
profileIdbodystringrequiredThe user/profile whose traits are loaded for rule evaluation.
eventbodyobjectrequiredtraitsbodyobjectOptional traits merged over the profile’s stored traits, for this decision only — not persisted. Use this to pass in-the-moment context (like a live cart value) without writing it to the profile.
userFeaturesbodyobjectOptional feature snapshot used for offer selection: valueScore (number or
null), payingAtRisk (boolean), attributionChannelQuality (number or
null), historicalRedemptionRate (number or null). Omitted fields default to
null.
{ "projectId": "prj_123", "profileId": "uid_456", "event": { "name": "checkout_abandoned", "props": { "cartValue": 12000 } }}Profile traits themselves come from the same store PUT /api/v1/profile writes
to (identified_users.traits_masked); any inline traits you send here are
shallow-merged on top for this evaluation only.
Response
Section titled “Response”{ "decisionId": "dec_abc", "matched": [ { "ruleId": "rule_1", "effects": [ { "type": "grant_coupon", "summary": "5% off next order" } ] } ]}matched is an empty array when no rule fires — that’s a valid, successful
response, not an error.
Errors
Section titled “Errors”| Status | Meaning |
|---|---|
400 |
Invalid JSON or a required field is missing (POST /api/v1/decide). |
401 |
Missing or invalid API key (POST /api/v1/decide). |
403 |
The API key lacks the decide / decision:call scope (POST /api/v1/decide). |
404 |
Project not found, or the key belongs to a different project — POST /api/v1/decide. |
429 |
Rate limit exceeded (30/min per project + IP) — POST /api/v1/decide. |
503 |
The decision cache or a backing service is unavailable (POST /api/v1/decide). |