Skip to content

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.

POST https://api.retidal.com/api/v1/decide

Auth: X-API-Key with scope decide or decision:call.

Rate limit: 30 requests/minute per (project, IP).

projectIdbodystringrequired

Must 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.

profileIdbodystringrequired

The user/profile whose traits are loaded for rule evaluation.

eventbodyobjectrequired
event fields
namebodystringrequired

The event name to evaluate rules against.

propsbodyobject

Optional event-specific properties available to rule conditions.

traitsbodyobject

Optional 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.

userFeaturesbodyobject

Optional 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.

Request
{
"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.

200
{
"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.

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).