Reten Docs

Update Lifecycle Configs

In-place update of one or more lifecycle pillars on an AGC.

PUT /api/activity-generation-configs/:id/lifecycle

Update one or more lifecycle pillars of an AGC in place, in a single atomic transaction.

Auth: Required — activity-generation-config:update permission

Path Parameters

ParameterTypeDescription
idUUIDActivity generation config id

Request Body

Send only the pillars you want to update. Each pillar you send edits the matching pillar of the AGC in the path — an AGC has exactly one of each, so the body does not identify it. Within a pillar, send only the fields you want to change (the same fields as in create); omitted fields keep their current value. Request bodies are snake_case.

FieldTypeRequiredDescription
activationobjectNoActivation fields to update. Omit to leave activation untouched.
engagementobjectNoEngagement fields to update. Omit to leave engagement untouched.
resurrectionobjectNoResurrection fields to update. Omit to leave resurrection untouched.

Editing a pillar keeps its id — the same one you read from GET /:id.

Child reconciliation (by id)

Each child item (a moment / level / threshold) carries an optional id. When a pillar includes its child array (moments / levels / thresholds), the children are reconciled against the existing rows; when the array is omitted, the children are left untouched:

Child in requestEffect
WITH id matching an existing childUpdated in place (id preserved)
WITHOUT idInserted as a new child
Existing child absent from the arrayDeleted

The whole operation runs in one transaction — either every change applies, or none does.

Example — update engagement only

Edit one level (kept by its id), add a new level (no id), and drop a level by omitting it.

curl -X PUT https://api.reten.ai/api/activity-generation-configs/f47ac10b-58cc-4372-a567-0e02b2c3d479/lifecycle \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "engagement": {
      "name": "Engagement",
      "source_table": "events",
      "source_columns": ["user_id", "event_id"],
      "date_column": "occurred_at",
      "engagement_window_days": 28,
      "min_lifetime_actions_for_engaged": 1,
      "counting_method": "active_days",
      "levels": [
        {
          "id": "6e2d4055-af66-4177-c288-ee99ffaa00bb",
          "status_code": "casual",
          "user_retention_status_config_id": "cc33dd44-ee55-4f66-a077-bb99ccaaddbb",
          "label": "Casual",
          "min_threshold": 1,
          "max_threshold": 9,
          "order": 1
        },
        {
          "status_code": "power",
          "user_retention_status_config_id": "1122aabb-3344-4ccd-9eef-556677889900",
          "label": "Power",
          "min_threshold": 10,
          "order": 2
        }
      ]
    }
  }'
import axios from 'axios';

const id = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
const body = {
  engagement: {
    name: 'Engagement',
    source_table: 'events',
    source_columns: ['user_id', 'event_id'],
    date_column: 'occurred_at',
    engagement_window_days: 28,
    min_lifetime_actions_for_engaged: 1,
    counting_method: 'active_days',
    levels: [
      {
        id: '6e2d4055-af66-4177-c288-ee99ffaa00bb', // has id -> updated in place
        status_code: 'casual',
        user_retention_status_config_id: 'cc33dd44-ee55-4f66-a077-bb99ccaaddbb',
        label: 'Casual',
        min_threshold: 1,
        max_threshold: 9,
        order: 1,
      },
      {
        // no id -> inserted as a new level
        status_code: 'power',
        user_retention_status_config_id: '1122aabb-3344-4ccd-9eef-556677889900',
        label: 'Power',
        min_threshold: 10,
        order: 2,
      },
      // the previous "core" level is omitted -> deleted
    ],
  },
  // activation and resurrection are omitted -> left untouched
};

await axios.put(
  `https://api.reten.ai/api/activity-generation-configs/${id}/lifecycle`,
  body,
  { headers: { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' } },
);

In this example: the casual level is updated in place (its id is preserved), a new power level is inserted, and the previous core level — absent from the array — is deleted. activation and resurrection are omitted, so they are left untouched.

Response 200 OK

Empty body. Fetch GET /:id afterward to read the updated pillars and the recomputed configHashes.

Error Responses

StatusDescription
400Validation failed — including a pillar that carries an id (the pillar is always the one of the AGC in the path) or a child id that does not belong to that pillar
404Activity generation config not found