POST /api/v1/programs/{programId}/lessons/reorder
Sets the order of the lessons of one scope: a course, or the lessons of the
program that belong to no course. You send the complete ordered list of that
scope, never a move.
courseId is required, null included. Omitting it would make the platform
pick a scope, and you would believe you reordered the course you meant while you
reordered the loose lessons.
| 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, or an archived course, 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 ordering |
X-Correlation-Id | no | Caller correlation id, returned or generated |
Request body
| Field | Type | Required | Nullable | Description |
|---|
courseId | UUID | yes | yes | The scope. null means the lessons of the program with no course |
orderedLessonIds | array of UUID | yes | no | 1 to 500 ids, no duplicates, exactly the lessons of that scope |
{
"courseId": "9f2c0a1e-0000-4000-8000-000000000000",
"orderedLessonIds": [
"1a2b3c4d-0000-4000-8000-000000000000",
"1a2b3c4d-0000-4000-8000-000000000001"
]
}
curl -X POST "$COHORTE_API_BASE_URL/api/v1/programs/$PROGRAM_ID/lessons/reorder" \
-H "x-api-key: $COHORTE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{"courseId":null,"orderedLessonIds":["'"$FIRST"'"]}'
200 OK — the lessons of that scope, in their new order.
400 Bad Request — missing Idempotency-Key, invalid JSON, duplicates, an empty list, more than 500 ids, or a set that is not exactly the lessons of the scope.
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.
{
"success": true,
"data": [
{
"id": "5d9f3a60-1c2b-4e7d-8f4a-6b7c8d9e0f1a",
"programId": "9f2c0a1e-4b7d-4c1a-9e3f-2a6b8c0d1e2f",
"courseId": null,
"sectionId": null,
"title": "Structure a discovery call",
"content": "## Why it matters\n\nA discovery call decides the rest of the sale.",
"videoUrl": "https://vimeo.com/912440188",
"status": "published",
"position": 1,
"createdAt": "2026-09-01T09:00:00.000Z",
"updatedAt": "2026-09-04T17:12:00.000Z"
}
],
"correlationId": "0f6b1d92-5c3e-4a8b-9d71-3e2f4a6b8c10"
}
With Idempotency-Key, retries of the identical target and payload do not write another mutation, audit or event. A different intention under that key returns 409. Results describe the currently authorized resource state.