Skip to content

Assigning training

These endpoints decide what people owe: assigning a lesson, requiring a topic or knowledge item of someone, retraining them, excusing them or moving their due date, setting how often a lesson has to be retaken, and sending a pop quiz. The reads that go with them are under Training and Lessons.

They need a token granted the training:assign scope, which is an OAuth path today. It can be granted by an organization admin or a team admin. The person behind the token must also be allowed to do the act in Mereon, checked on every call, so a demotion takes effect on the next one.

How far a person reaches is the same as in the web app:

Person May assign to May excuse (waive, cancel, move a due date)
Organization admin Anyone in the organization Anyone in the organization
Team admin People on the teams they administer Nobody
Anyone else Themselves Nobody

A request that names someone outside that reach is a 403, and nothing is changed for anyone named in it. Sending a pop quiz, and setting a lesson’s retraining policy, have their own rules, described below.

Most of these return an obligation: a person’s requirement to complete a lesson or learn a topic or item, as it stands after the change.

{
"id": "…",
"userId": "…",
"itemType": "lesson",
"itemId": "…",
"status": "waived",
"required": true,
"dueDate": "2026-11-01T14:00:00.000Z",
"dueDateOverridden": false,
"needsReview": false
}
Field Type Notes
itemType string lesson, topic or item.
status string active, completed, cancelled or waived.
dueDate string | null The due date the person sees, or null when there is none.
dueDateOverridden boolean true when someone set the due date by hand, over the one it would have.
needsReview boolean true when what its due date counts from changed (a start date moved, for instance) and someone should confirm the new date.

To act on someone else’s obligation you need its id: read their obligations with GET /v1/people/{id}/progress.

POST /v1/lessons/{id}/assignments

Requires a lesson of everyone, of the people on some teams, or of named people. Each person it newly reaches gets an enrollment, a quiz prepared for them, and an email and text telling them.

{
"audience": "users",
"userIds": ["…", "…"],
"due": { "type": "days", "days": 30 }
}
Field Type Notes
audience string Required. everyone, teams or users.
teamIds string[] With teams only. Up to 50, from GET /v1/teams.
userIds string[] With users only. Up to 500, from GET /v1/people.
due object Leave out for no deadline. { "type": "date", "date": "2026-11-01T09:00:00-05:00" } for a moment (ISO 8601 with a UTC offset), or { "type": "days", "days": 30 } for a number of days after it is assigned (1 to 3,650).
{
"lessonId": "…",
"title": "Forklift safety",
"assigned": [{ "userId": "…", "enrollmentId": "…" }]
}

People who already had the lesson are left as they were and are not in assigned, so an empty list is a success that reached nobody new. With everyone or teams, people who cannot take the lesson are left out quietly; naming one of them in userIds is a 400. A closed lesson, or one generated for a single person, cannot be assigned.

POST /v1/lessons/{id}/unassign

Takes a lesson back from named people. Their enrollment in progress is removed, with their progress in it, and the requirement is cancelled. An enrollment someone already completed is kept, since it is the record of having done it. To excuse someone while keeping their record, waive or cancel the obligation instead.

{ "userIds": ["…"] }
{ "lessonId": "…", "title": "Forklift safety", "removedCount": 1 }

Refused with a 400 when none of the people named has the lesson in progress. Only an organization admin may take back a lesson that is required of someone, because removing the enrollment cancels the requirement; anyone else gets a 403.

PUT /v1/lessons/{id}/retraining-policy

How often people who completed the lesson have to take it again. It needs permission to edit that lesson, the same as changing it in the web app.

{
"retrainingType": "recurring",
"intervalDays": 365,
"completionMode": "full_retake"
}
Field Type Notes
retrainingType string Required. recurring, or none to turn retraining off.
intervalDays integer With recurring only. Days between retakes, 1 to 3,650.
completionMode string With recurring only. full_retake to redo the whole lesson, or changed_material for a shorter lesson on what changed since.

Returns the policy in the shape GET /v1/lessons/{id}/retraining-policy does. It applies from each person’s next completion, and creates nothing for people who completed the lesson before. A lesson generated for a single person cannot have one.

POST /v1/knowledge-obligations

Requires one person to learn a topic or a knowledge item. The level they have to reach follows from their duty on it, so the person must hold a duty on it, directly or through a role or team; otherwise it is a 400. If they already owe it, this merges into the obligation they have.

{
"userId": "…",
"itemType": "topic",
"itemId": "…",
"dueDays": 30,
"reason": "New to the warehouse"
}
Field Type Notes
userId string Required.
itemType string Required. topic or item.
itemId string Required.
dueDays integer Days from now until it is due, 1 to 3,650. Leave out for no deadline.
reason string Up to 2,000 characters, kept on the obligation.

Returns the obligation.

POST /v1/retraining-assignments

Requires one person to take a lesson again within a number of days, and tells them.

{
"userId": "…",
"lessonId": "…",
"dueDays": 14,
"retrainingResetsClock": true,
"reason": "Failed the forklift check"
}
Field Type Notes
userId string Required.
lessonId string Required.
dueDays integer Required. 1 to 3,650.
retrainingResetsClock boolean Required. Whether completing it counts as the person’s next scheduled retake under the lesson’s retraining policy.
reason string Up to 2,000 characters, kept on the obligation.

Returns the obligation. A lesson generated for a single person cannot be retrained.

POST /v1/obligations/{id}/waive

POST /v1/obligations/{id}/cancel

Waiving excuses a person from something they owe, as a deliberate exception. Cancelling ends a requirement that was assigned by mistake or no longer applies. Both keep the reason on the record, and for a lesson the person is told. Neither can be undone: assigning the same thing again creates a new obligation. Only an organization admin may do either.

{ "reason": "Moving to the front office" }

reason is required, up to 2,000 characters. Returns the obligation, now waived or cancelled. Only an active obligation can be waived or cancelled.

POST /v1/obligations/{id}/due-date

Sets the due date the person sees by hand, over the one it would have. Later assignments of the same thing do not move a date set this way. Send null to take the override off. For a lesson, setting a date tells the person. Only an organization admin may, and only on an active obligation.

{ "dueDate": "2026-11-08T17:00:00-05:00" }

Returns the obligation.

POST /v1/obligations/{id}/confirm-review

An obligation has needsReview set when what its due date counts from changed. This settles it at the date given, or with none, and clears the flag. It is refused for an obligation that is not flagged. Only an organization admin may.

{ "resolvedDueDate": "2026-12-01T00:00:00Z" }

Leave resolvedDueDate out, or send null, for no due date. Returns the obligation.

POST /v1/pop-quizzes

Sends a short quiz on a video, document or guide. Only an organization admin may send one.

{
"contentId": "…",
"audience": "teams",
"teamIds": ["…"],
"dueDate": "2026-11-01T17:00:00-05:00"
}
Field Type Notes
contentId string Required. A video, document or guide from GET /v1/content.
audience string Required. everyone, teams or users, with teamIds or userIds as for assigning a lesson.
dueDate string Required. ISO 8601 with a UTC offset, in the future.
difficulty string SIMPLE, MODERATE, CHALLENGING or ADVANCED. Leave out for the organization’s default. The harder levels need a plan that includes them.
{
"id": "…",
"title": "Forklift safety check",
"dueDate": "2026-11-01T22:00:00.000Z",
"url": "https://mereon.ai/pop-quiz/…"
}

Questions are written for each person after the call returns, and each is told by email and text once theirs are ready. Follow it with GET /v1/pop-quizzes/{id}. Everyone it goes to must be able to see the content; if someone cannot, it is a 400 and nothing is sent. If its questions cannot be started, nothing is created and the call is a 503 with POP_QUIZ_GENERATION_FAILED, which is safe to retry.

Status When
400 The body is invalid, a list does not match audience, nobody can be reached, a person or topic is not in the organization, a person has no duty on the topic or item, the obligation is not in a state that allows the change, or a pop quiz recipient cannot see the content.
403 The token lacks training:assign, the person may not do this act, or a person named is outside their reach.
404 The lesson, obligation or content is not in the organization.
429 Over the rate limit. Retry-After says when to try again.
503 A pop quiz’s questions could not be started. Nothing was created.

The other routes on this page are limited to 30 calls a minute and 300 an hour per connection. The MCP tools that do the same acts are held to the same numbers, counted per tool.