POST /api/v1/milestones/{milestoneId}/contributions
Says that a lesson — or a resource — prepares a milestone.
Exactly one target: lessonId or resourceId, never both, never neither.
That rule is enforced by the platform and by a database constraint; sending both
is a 400.
| Role in the organization | This endpoint |
|---|---|
OWNER | Allowed |
ADMIN | Allowed |
MEMBER | Refused |
| Requirement | Rule for this endpoint |
|---|---|
| Business role | None — a contribution is composition, and follows the program |
| Resource scope | Milestone and target of the school attached to the API key |
| Resource state | An archived milestone, or a milestone of an archived program, answers 403 |
| Parameter | Type | Required | Description |
|---|---|---|---|
milestoneId | UUID | yes | Milestone 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 attachment |
X-Correlation-Id | no | Caller correlation id, returned or generated |
| Field | Type | Required | Nullable | Description |
|---|---|---|---|---|
lessonId | UUID | one of the two | no | A lesson of the same program |
resourceId | UUID | one of the two | no | A resource attached to a lesson of the same program |
{"lessonId": "1a2b3c4d-0000-4000-8000-000000000000"}curl -X POST "$COHORTE_API_BASE_URL/api/v1/milestones/$MILESTONE_ID/contributions" \
-H "x-api-key: $COHORTE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{"lessonId":"'"$LESSON_ID"'"}'201 Created — the contribution exists.200 OK — the same Idempotency-Key, or the same pair, replayed the original attachment.400 Bad Request — missing Idempotency-Key, invalid JSON, both targets, or neither.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 milestone is archived.404 Not Found — the milestone, the lesson or the resource is unknown, or belongs to another school or another program.Same shape as
List the contributions of a milestone,
for a single data object, plus replayed.
{
"success": true,
"replayed": false,
"data": {
"id": "d4b8e016-5c3f-4a2e-9b74-2b3c4d5e6f70",
"milestoneId": "2e6a9c14-8b7d-4f3e-a5c2-0f1a2b3c4d5e",
"lessonId": "5d9f3a60-1c2b-4e7d-8f4a-6b7c8d9e0f1a",
"resourceId": null,
"createdAt": "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.