Reten Docs

Publish Activity Generation Config

Move an activity generation config from draft or paused to active.

PATCH /api/activity-generation-configs/:id/publish

Publish an AGC of the active project: move it from draft or paused to active (see Status). Only active configurations are meant to run. A paused AGC is resumed with this same endpoint, and it keeps its id.

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

Path Parameters

ParameterTypeDescription
idUUIDActivity generation config id

Request Body

The body is optional.

FieldTypeRequiredDescription
confirmDefaultRootbooleanNoConfirms publishing while the project's root audience is still the default one (see below). Only true confirms; absent, false or null do not

Transitions

Current statusResult
draftactive
pausedactive
activeNo change: responds 200 with the AGC as it is, without checking the root audience

Default root audience confirmation

Every project is created with its root audience Toda la empresa: the active commerces (see Projects → Root audience). While the root audience keeps that default definition, publishing runs the configuration over the whole company, so the API asks for an explicit confirmation.

  • The root audience is default while its definition is still exactly the original one: a single query block equivalent to SELECT DISTINCT user_id FROM user_properties WHERE is_active = true, with no joins, time window, grouping, HAVING or compositions. Any other structural change makes it edited; renaming it does not. A root audience edited and then brought back to that definition is default again.
  • The check is always on the project's root audience, even when the AGC has its own audienceId.
  • Without confirmDefaultRoot: true, publishing a draft or paused AGC in that situation responds 409 with this body, and the AGC keeps its status:
{
  "statusCode": 409,
  "error": "Conflict",
  "code": "DEFAULT_ROOT_CONFIRMATION_REQUIRED",
  "message": "La raíz del proyecto sigue siendo la raíz por defecto («Toda la empresa»): publicar hará correr esta configuración sobre toda la empresa. Para confirmarlo, reenvía la solicitud con `confirmDefaultRoot: true`."
}

Branch on code, never on the text of message, which may change (see Error Responses). To confirm, send the same request with { "confirmDefaultRoot": true }; sending it when the root audience is already edited is harmless, and the AGC is published as usual. To publish without the confirmation, first edit the project's root audience.

Example

curl -X PATCH https://api.reten.ai/api/activity-generation-configs/f47ac10b-58cc-4372-a567-0e02b2c3d479/publish \
  -H "Authorization: Bearer <token>" \
  -H "x-tenant-id: <tenant-id>" \
  -H "x-project-id: <project-id>" \
  -H "Content-Type: application/json" \
  -d '{ "confirmDefaultRoot": true }'
import axios from 'axios';

const id = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
const url = `https://api.reten.ai/api/activity-generation-configs/${id}/publish`;
const headers = { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' };

let published;
try {
  published = (await axios.patch(url, {}, { headers })).data;
} catch (error) {
  // The project's root audience is still the default one
  if (axios.isAxiosError(error) && error.response?.data?.code === 'DEFAULT_ROOT_CONFIRMATION_REQUIRED') {
    // Confirm with the user before publishing over the whole company
    published = (await axios.patch(url, { confirmDefaultRoot: true }, { headers })).data;
  } else {
    throw error;
  }
}

Response 200 OK

Returns the AGC with its new status and its three nested pillars, in the same camelCase shape as GET /:id, but without effectiveAudienceId and configHashes.

{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "projectId": "3f6c2b1a-8d4e-4f7a-9b2c-5e1d0a7f6c34",
  "name": "Default lifecycle",
  "description": "Activation, engagement and resurrection for the main funnel",
  "audienceId": "1f0d2c3b-4a59-4687-9c12-abcdef012345",
  "status": "active",
  "updatedBy": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "createdAt": "2026-06-10T14:00:00.000Z",
  "updatedAt": "2026-06-20T10:00:00.000Z",
  "activationConfig": {
    "id": "2a8f0c11-6b22-4d33-8e44-aa55bb66cc77",
    "name": "Activation",
    "description": "First-week activation moments",
    "sourceTable": "events",
    "sourceColumns": ["user_id", "event_id"],
    "dateColumn": "occurred_at",
    "activityGenerationConfigId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "aggregationMethod": "nunique",
    "isActive": true,
    "updatedBy": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "createdAt": "2026-06-10T14:00:00.000Z",
    "updatedAt": "2026-06-10T14:00:00.000Z",
    "activationMoments": [
      {
        "id": "3b9a1d22-7c33-4e44-9f55-bb66cc77dd88",
        "activationConfigId": "2a8f0c11-6b22-4d33-8e44-aa55bb66cc77",
        "statusCode": "aha",
        "userRetentionStatusConfigId": "aa11bb22-cc33-4d44-9e55-ff66aa77bb88",
        "minActions": 3,
        "windowDays": 7,
        "timeWindow": 30,
        "priority": 1,
        "isActive": true,
        "createdAt": "2026-06-10T14:00:00.000Z",
        "updatedAt": "2026-06-10T14:00:00.000Z"
      }
    ]
  },
  "engagementConfig": {
    "id": "5d1c3f44-9e55-4066-b177-dd88ee99ffaa",
    "name": "Engagement",
    "description": "Active-user engagement levels",
    "sourceTable": "events",
    "sourceColumns": ["user_id", "event_id"],
    "dateColumn": "occurred_at",
    "activityGenerationConfigId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "engagementWindowDays": 28,
    "minLifetimeActionsForEngaged": 1,
    "countingMethod": "active_days",
    "isActive": true,
    "updatedBy": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "createdAt": "2026-06-10T14:00:00.000Z",
    "updatedAt": "2026-06-10T14:00:00.000Z",
    "engagementLevels": [
      {
        "id": "6e2d4055-af66-4177-c288-ee99ffaa00bb",
        "engagementConfigId": "5d1c3f44-9e55-4066-b177-dd88ee99ffaa",
        "statusCode": "casual",
        "userRetentionStatusConfigId": "cc33dd44-ee55-4f66-a077-bb99ccaaddbb",
        "label": "Casual",
        "minThreshold": 1,
        "maxThreshold": 7,
        "order": 1,
        "isActive": true,
        "createdAt": "2026-06-10T14:00:00.000Z",
        "updatedAt": "2026-06-10T14:00:00.000Z"
      }
    ]
  },
  "resurrectionConfig": {
    "id": "8a4f6277-c188-4399-e400-aa00bb11ccdd",
    "name": "Resurrection",
    "description": "Recovery vs. churn classification",
    "sourceTable": "events",
    "sourceColumns": ["user_id"],
    "dateColumn": "occurred_at",
    "activityGenerationConfigId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "isActive": true,
    "updatedBy": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "createdAt": "2026-06-10T14:00:00.000Z",
    "updatedAt": "2026-06-10T14:00:00.000Z",
    "resurrectionThresholds": [
      {
        "id": "9b5a7388-d299-44aa-f511-bb11ccdd22ee",
        "resurrectionConfigId": "8a4f6277-c188-4399-e400-aa00bb11ccdd",
        "statusCode": "dormant",
        "userRetentionStatusConfigId": "ee55ff66-aa77-4188-c299-ddbbeeccffdd",
        "label": "Dormant",
        "thresholdDays": 30,
        "order": 1,
        "isActive": true,
        "createdAt": "2026-06-10T14:00:00.000Z",
        "updatedAt": "2026-06-10T14:00:00.000Z"
      }
    ]
  }
}

Error Responses

StatusDescription
400id is not a valid UUID
400confirmDefaultRoot is not a boolean
400Unknown field in the body
404No activity generation config with that id exists in the active project — Activity generation config <id> not found
409The project's root audience is still the default one and the request does not carry confirmDefaultRoot: true — code: DEFAULT_ROOT_CONFIRMATION_REQUIRED