PATCH /api/v1/programs/{programId}
Changes a program. A field you omit is left alone; a field you send as null
is erased. You never have to send the whole object back, and forgetting one
field never destroys it.
Setting status to active is what makes the program visible to members.
archived is not accepted here — archiving is its own command.
| Role in the organization | This endpoint |
|---|---|
OWNER | Allowed |
ADMIN | Allowed |
MEMBER | Refused |
| Requirement | Rule for this endpoint |
|---|---|
| Business role | None — composing content is an organization-role decision |
| Resource scope | Program of the school attached to the API key |
| Resource state | An archived program refuses every write, and answers 403 |
| Parameter | Type | Required | Description |
|---|---|---|---|
programId | UUID | yes | Program visible from the key's school |
| Header | Required | Description |
|---|---|---|
x-api-key | yes | API key created for this school |
Idempotency-Key | yes | Stable key for this change |
X-Correlation-Id | no | Caller correlation id, returned or generated |
slug accepts a nonempty string of lowercase letters, digits and dashes. Omitting it preserves the existing slug. null is rejected with 400; this operation does not clear a slug.
| Field | Type | Required | Nullable | Description |
|---|---|---|---|---|
name | string | no | no | 3 to 100 characters |
description | string | no | yes | Up to 500 characters; null erases it |
transformation | string | no | yes | Up to 500 characters; null erases it |
status | string | no | no | draft or active. archived is refused here |
unlockMode | string | no | no | immediate, sequential or validation-required |
{
"status": "active",
"unlockMode": "sequential"
}curl -X PATCH "$COHORTE_API_BASE_URL/api/v1/programs/$PROGRAM_ID" \
-H "x-api-key: $COHORTE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{"status":"active"}'200 OK — the program, as it now stands.400 Bad Request — missing Idempotency-Key, invalid JSON, an unknown status or unlock mode, or an illegal transition.401 Unauthorized — the key is missing, invalid, or no longer attached to a member.403 Forbidden — the bearer is not OWNER or ADMIN, or the program is archived.404 Not Found — the program is unknown or belongs to another school.Identical to Read a program, plus
replayed, which is true when the change had already been applied.
{
"success": true,
"replayed": false,
"data": {
"id": "9f2c0a1e-4b7d-4c1a-9e3f-2a6b8c0d1e2f",
"name": "Agentic AI Developer",
"slug": "agentic-ai-developer",
"description": "Twelve weeks to ship agents in production.",
"transformation": "Ship one agent to production every week.",
"status": "active",
"unlockMode": "sequential",
"createdAt": "2026-09-01T09:00:00.000Z",
"updatedAt": "2026-09-04T17:12:00.000Z"
},
"correlationId": "0f6b1d92-5c3e-4a8b-9d71-3e2f4a6b8c10"
}unlockMode changes what every member of the program can open. It is recorded
in the program.updated event with its before and after.