Reten Docs

Single Upsert

Create or update the lifecycle state of a single commerce under an AGC.

POST /api/commerce-lifecycle-snapshots

Creates or updates (upsert) the lifecycle state of a commerce under a specific AGC. If a state already exists for the (commerce, AGC) pair, it is updated; otherwise it is created. Returns the resulting state.

Auth: Required — commerce-lifecycle-snapshot:create permission

To write many states at once, use the batch upsert (up to 1000 items in a single operation). This endpoint writes one and only accepts commerce_id (UUID), not an external code.

Request Body

FieldTypeRequiredDescription
commerce_idUUIDYesUUID of the commerce in Reten. Must exist.
activity_generation_config_idUUIDYesAGC under which the state is written. See AGC identifier.
codestringYesRetention state code (1–255 characters). Must correspond to a UserRetentionStatusConfig of the tenant; an unknown code responds 400.
stageenumYesStage: ACTIVATION, ENGAGEMENT or RESURRECTION.
last_computed_atISO 8601YesWhen the engine computed this state.

The label is not sent: Reten derives it from the code based on the retention states config (source of truth for the code → label pair). The state_changed_at is not sent either: Reten manages it — it only advances if the (stage, code) pair changes. See freshness.

Example

curl -X POST "https://api.reten.ai/api/commerce-lifecycle-snapshots" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "commerce_id": "c0000000-0000-4000-8000-000000000004",
    "activity_generation_config_id": "a1b2c3d4-0000-4000-8000-000000000001",
    "code": "ONBOARDING",
    "stage": "ACTIVATION",
    "last_computed_at": "2026-06-10T06:00:00.000Z"
  }'
const response = await fetch(
  "https://api.reten.ai/api/commerce-lifecycle-snapshots",
  {
    method: "POST",
    headers: {
      "x-api-key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      commerce_id: "c0000000-0000-4000-8000-000000000004",
      activity_generation_config_id: "a1b2c3d4-0000-4000-8000-000000000001",
      code: "ONBOARDING",
      stage: "ACTIVATION",
      last_computed_at: "2026-06-10T06:00:00.000Z",
    }),
  },
);
const snapshot = await response.json();
import requests

response = requests.post(
    "https://api.reten.ai/api/commerce-lifecycle-snapshots",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "commerce_id": "c0000000-0000-4000-8000-000000000004",
        "activity_generation_config_id": "a1b2c3d4-0000-4000-8000-000000000001",
        "code": "ONBOARDING",
        "stage": "ACTIVATION",
        "last_computed_at": "2026-06-10T06:00:00.000Z",
    },
)
snapshot = response.json()

Response 201 Created

Both on create and on update, the endpoint returns the resulting snapshot resource:

{
  "id": "5d000000-0000-4000-8000-000000000004",
  "commerce_id": "c0000000-0000-4000-8000-000000000004",
  "external_id": "SV-004",
  "activity_generation_config_id": "a1b2c3d4-0000-4000-8000-000000000001",
  "code": "ONBOARDING",
  "label": "Onboarding",
  "stage": "ACTIVATION",
  "last_computed_at": "2026-06-10T06:00:00.000Z",
  "state_changed_at": "2026-06-10T06:00:00.000Z"
}

Errors

StatusDescription
400Invalid body, unknown code, or invalid stage.
404The commerce (commerce_id) does not exist.
401Missing or invalid API key.
403The credential lacks the commerce-lifecycle-snapshot:create permission.