PATCH /api/v1/cohorts/{cohortId}
Changes the configuration of a cohort. A field you omit is left alone; a
field you send as null is erased. The status does not change here: moving a
cohort through its lifecycle is its own command.
| Role in the organization | This endpoint |
|---|---|
OWNER | Allowed |
ADMIN | Allowed |
MEMBER | Refused — 403 |
| Requirement | Rule for this endpoint |
|---|---|
| Business role | None |
| Resource scope | The cohort belongs to the key's organization |
| Participation | None |
| Resource state | The cohort is not closed |
| Parameter | Type | Required | Description |
|---|---|---|---|
cohortId | UUID | yes | Cohort of the key's organization |
| Header | Required | Description |
|---|---|---|
x-api-key | yes | API key created for this organization |
Idempotency-Key | yes | Stable key for this change; a replay returns the first result |
X-Correlation-Id | no | Caller correlation id, returned or generated |
| Field | Type | Required | Nullable | Description |
|---|---|---|---|---|
name | string | no | no | 3 to 100 characters |
startDate | string | no | yes | Calendar date, YYYY-MM-DD |
endDate | string | no | yes | Calendar date, YYYY-MM-DD, not before startDate |
timezone | string | no | no | IANA time zone, for example Europe/Paris |
capacity | integer | no | yes | Positive; null means unlimited |
phases | array | no | no | Replaces the ordered phase list, up to 50 |
phases[].id | UUID | no | no | Keep it to keep an existing phase; omit it to add one |
phases[].name | string | yes | no | 1 to 100 characters |
phases[].position | integer | yes | no | Positive, unique in the list |
curl -X PATCH "$COHORTE_API_BASE_URL/api/v1/cohorts/$COHORT_ID" \
-H "x-api-key: $COHORTE_API_KEY" \
-H "Idempotency-Key: cohort-autumn-capacity-24" \
-H "Content-Type: application/json" \
-d '{
"name": "Autumn cohort",
"startDate": "2026-10-05",
"timezone": "Europe/Paris",
"capacity": 24,
"phases": [
{"id": "11111111-1111-4111-8111-111111111111", "name": "Foundations", "position": 1}
]
}'200 OK — the cohort as configured. replayed: true when the key was already used.400 Bad Request — missing Idempotency-Key, invalid JSON, a field out of bounds, an end date before the start date, duplicate phase ids or positions, a capacity below current occupancy, or the removal of the current phase.401 Unauthorized — missing, unknown or expired key.403 Forbidden — the bearer is not OWNER or ADMIN.404 Not Found — the cohort is unknown or belongs to another school.409 Conflict — the cohort is closed.| Field | Type | Description |
|---|---|---|
data.id | UUID | Cohort id |
data.programId | UUID | Program of the cohort |
data.name | string | Cohort name |
data.status | string | Lifecycle status |
data.startDate / data.endDate | string | ISO dates, or null |
data.timezone | string | IANA time zone |
data.capacity | integer | Maximum seats, or null for unlimited |
data.occupancy | integer | Seats taken |
data.overCapacity | boolean | true when occupancy exceeds capacity |
data.phases[] | array | id, name, position, isCurrent |
{
"success": true,
"replayed": false,
"data": {
"id": "3a1f…",
"programId": "9f2c…",
"name": "Autumn cohort",
"status": "active",
"startDate": "2026-10-05T00:00:00.000Z",
"endDate": null,
"timezone": "Europe/Paris",
"capacity": 24,
"occupancy": 12,
"overCapacity": false,
"phases": [
{"id": "11111111-1111-4111-8111-111111111111", "name": "Foundations", "position": 1, "isCurrent": true}
]
},
"correlationId": "c0ffee…"
}phases replaces the whole list: send every phase you keep, with its id.Idempotency-Key returns the original result without a second audit entry or event.