POST /api/v1/courses/{courseId}/sections
Adds a section at the end of a course. Position is not an input: sections are reordered with their own command.
| Role in the organization | This endpoint |
|---|---|
OWNER | Allowed |
ADMIN | Allowed |
MEMBER | Refused |
| Requirement | Rule for this endpoint |
|---|---|
| Business role | None — sections carry the permission of their course |
| Resource scope | Course of the school attached to the API key |
| Resource state | An archived course, or a course of an archived program, answers 403 |
| Parameter | Type | Required | Description |
|---|---|---|---|
courseId | UUID | yes | Course visible from the key's school |
| Header | Required | Description |
|---|---|---|
x-api-key | yes | API key created for this school |
Idempotency-Key | no | Optional: binds the same target and payload for safe retries |
X-Correlation-Id | no | Caller correlation id, returned or generated |
| Field | Type | Required | Nullable | Description |
|---|---|---|---|---|
title | string | yes | no | 1 to 120 characters |
{"title": "Module 1 — Foundations"}curl -X POST "$COHORTE_API_BASE_URL/api/v1/courses/$COURSE_ID/sections" \
-H "x-api-key: $COHORTE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"title":"Module 1 — Foundations"}'201 Created — the section exists, last in the course.400 Bad Request — invalid JSON, or a title outside 1–120 characters.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 course is archived.404 Not Found — the course is unknown or belongs to another school.{
"success": true,
"data": {
"id": "e7a2c915-4b3d-4f8e-9a61-2c3d4e5f6a7b",
"courseId": "3b8e2d41-7a6c-4f1e-8b25-9c0d1e2f3a4b",
"title": "Module 1 — Foundations",
"position": 2,
"createdAt": "2026-09-01T09:00:00.000Z",
"updatedAt": "2026-09-01T09:00:00.000Z"
},
"correlationId": "0f6b1d92-5c3e-4a8b-9d71-3e2f4a6b8c10"
}Idempotency-Key, the same intention reuses its claim without a second mutation or event. A changed target or payload conflicts. Without a key, legacy calls are not retry-safe.section.created event are written in
one transaction.