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
| Parameter | Type | Description |
|---|---|---|
id | UUID | Activity generation config id |
Request Body
The body is optional.
| Field | Type | Required | Description |
|---|---|---|---|
confirmDefaultRoot | boolean | No | Confirms 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 status | Result |
|---|---|
draft | active |
paused | active |
active | No 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,HAVINGor 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 adraftorpausedAGC in that situation responds409with 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
| Status | Description |
|---|---|
400 | id is not a valid UUID |
400 | confirmDefaultRoot is not a boolean |
400 | Unknown field in the body |
404 | No activity generation config with that id exists in the active project — Activity generation config <id> not found |
409 | The project's root audience is still the default one and the request does not carry confirmDefaultRoot: true — code: DEFAULT_ROOT_CONFIRMATION_REQUIRED |