GET /api/v1/milestones/{milestoneId}/contributions
Returns what contributes to a milestone: the lessons and resources that prepare it. Each contribution names exactly one of the two.
| Role in the organization | This endpoint |
|---|---|
OWNER | Allowed |
ADMIN | Allowed |
MEMBER | Conditional — with the program_director business role scoped to the organization, or as coach of the milestone's program |
| 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 |
X-Correlation-Id | no | Caller correlation id, returned or generated |
curl "$COHORTE_API_BASE_URL/api/v1/milestones/$MILESTONE_ID/contributions" \
-H "x-api-key: $COHORTE_API_KEY"200 OK — the list, possibly empty. A milestone of another school also
answers an empty list rather than confirming it exists.401 Unauthorized — the key is missing, invalid, or no longer attached to a member.403 Forbidden — the bearer is not OWNER, ADMIN, an organization-scoped program_director of this school, nor the coach of this program.| Field | Type | Nullable | Description |
|---|---|---|---|
success | boolean | no | true for a successful request |
data[].id | UUID | no | Contribution identifier |
data[].milestoneId | UUID | no | The milestone |
data[].lessonId | UUID | yes | The lesson, when the contribution is a lesson |
data[].resourceId | UUID | yes | The resource, when the contribution is a resource |
data[].createdAt | ISO 8601 string | no | When it was attached, in UTC |
correlationId | UUID | no | Correlation id for support |
Exactly one of lessonId and resourceId is set on every line.
{
"success": true,
"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"
}