Reten Docs

List States

Paginated list of the tenant's lifecycle states, with filters by code, stage, AGC and freshness.

GET /api/commerce-lifecycle-snapshots

Returns a paginated list of the tenant's lifecycle states, with optional filters. Without an AGC filter, it walks the states across all of the tenant's AGCs.

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

Headers

HeaderRequiredValue
x-api-keyYes (partner)YOUR_API_KEY

Alternatively, with JWT: Authorization: Bearer <token> + x-tenant-id: <tenant-id>.

Query Parameters

ParameterTypeDefaultDescription
pagenumber1Page number (minimum 1).
per_pagenumber25Items per page (minimum 1, maximum 100).
codestring-Filter by retention state code (exact match, e.g. AT_RISK_MONTHLY).
stageenum-Filter by stage: ACTIVATION, ENGAGEMENT or RESURRECTION.
activity_generation_config_idUUID-Filter by AGC. If omitted, lists the states across all AGCs.
state_changed_sinceISO 8601-Returns only states whose state_changed_at is after this date. Useful for incremental sync.
sortstring-state_changed_atSort by state_changed_at. - prefix convention: state_changed_at → ascending; -state_changed_at → descending (most recent first).

By default (without sort) the order is descending by state_changed_at — the states that changed most recently appear first. The only sortable field is state_changed_at; any other sort value returns 400.

Example

curl "https://api.reten.ai/api/commerce-lifecycle-snapshots?stage=ENGAGEMENT&per_page=25&state_changed_since=2026-06-01T00:00:00Z" \
  -H "x-api-key: YOUR_API_KEY"
const params = new URLSearchParams({
  stage: "ENGAGEMENT",
  per_page: "25",
  state_changed_since: "2026-06-01T00:00:00Z",
});
const response = await fetch(
  `https://api.reten.ai/api/commerce-lifecycle-snapshots?${params}`,
  { headers: { "x-api-key": "YOUR_API_KEY" } },
);
const data = await response.json();
import requests

response = requests.get(
    "https://api.reten.ai/api/commerce-lifecycle-snapshots",
    headers={"x-api-key": "YOUR_API_KEY"},
    params={
        "stage": "ENGAGEMENT",
        "per_page": 25,
        "state_changed_since": "2026-06-01T00:00:00Z",
    },
)
data = response.json()

Response 200 OK

{
  "data": [
    {
      "id": "5d000000-0000-4000-8000-000000000001",
      "commerce_id": "c0000000-0000-4000-8000-000000000001",
      "external_id": "SV-001",
      "activity_generation_config_id": "a1b2c3d4-0000-4000-8000-000000000001",
      "code": "AT_RISK_MONTHLY",
      "label": "At risk (monthly)",
      "stage": "ENGAGEMENT",
      "last_computed_at": "2026-06-10T06:00:00.000Z",
      "state_changed_at": "2026-06-08T06:00:00.000Z"
    },
    {
      "id": "5d000000-0000-4000-8000-000000000002",
      "commerce_id": "c0000000-0000-4000-8000-000000000002",
      "external_id": "SV-002",
      "activity_generation_config_id": "a1b2c3d4-0000-4000-8000-000000000001",
      "code": "HEALTHY",
      "label": "Healthy",
      "stage": "ENGAGEMENT",
      "last_computed_at": "2026-06-10T06:00:00.000Z",
      "state_changed_at": "2026-06-03T06:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 25,
    "total": 2,
    "total_pages": 1,
    "has_next": false,
    "has_previous": false
  }
}

Pagination fields

FieldTypeDescription
pagenumberCurrent page.
per_pagenumberItems per page.
totalnumberExact total count of states matching the filters.
total_pagesnumberceil(total / per_page).
has_nextbooleantrue if there is a next page.
has_previousbooleantrue if there is a previous page.

The shape of each data element is the snapshot resource.

Errors

StatusDescription
400Invalid parameter (e.g. sort outside the whitelist, invalid stage, per_page over 100).
401Missing or invalid API key.
403The credential lacks the commerce-lifecycle-snapshot:view permission.