Skip to content

Deleting content

These endpoints remove resources that are already in your library. The reads that go with them are under Content. Renaming, editing, publishing, sharing and tagging stay under Managing content.

They need a token granted the content:delete 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 delete resources in Mereon, checked on every call, so a demotion takes effect on the next one.

An organization admin deletes the resources. A team admin mostly removes them from the teams they administer, and the resources stay in the library for everyone else. A guide is deleted for the whole organization either way. Deleting can close lessons left with nothing to teach, and can stop people who are part-way through those lessons when you say so.

A resource is named by the id GET /v1/content returns, whatever its type: a video, an audio recording, a document or a guide. One call names 1 to 25 of them. The same id is used on both routes below.

A resource you may delete proceeds, including an unpublished document that is yours to delete. One you can see but may not delete is a 403. One you can neither see nor delete is a 404. A set that mixes an id that does not exist with one you may not delete answers 404 and names only the ids that do not exist. When every id exists and some of them you may not delete, the call is 403 and deletes nothing.

POST /v1/content/deletion-preview

Reports what deleting these resources would do, and changes nothing. Ask this before POST /v1/content/deletions.

Terminal window
curl -X POST "https://api.mereon.ai/v1/content/deletion-preview" \
-H "Authorization: Bearer $MEREON_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "contentIds": ["cnt_…"] }'
Field Type Notes
contentIds string[] 1 to 25 ids from GET /v1/content.
{
"scope": "organization",
"deleting": [{ "contentId": "cnt_…", "title": "Returns policy" }],
"unsharing": [],
"blocked": [],
"lessonsClosing": { "count": 1, "preview": [{ "id": "les_…", "title": "Returns" }] },
"lessonsStaying": { "count": 0, "preview": [] },
"learnersInProgress": 2,
"inFlightAccessRequired": true,
"orphanedTopics": {
"topics": [{ "id": "top_…", "title": "Return window" }],
"blocked": [],
"content": [{ "contentId": "cnt_…", "title": "Returns policy" }],
"lessonsClosing": { "count": 1, "preview": [{ "id": "les_…", "title": "Returns" }] },
"learnersInProgress": 1
},
"openIssues": { "count": 0, "spansOtherContent": false, "content": [] }
}

scope is organization or team. On organization, resources that can go are listed under deleting and unsharing is empty. On team, most resources are listed under unsharing and guides are listed under deleting.

blocked names each resource the delete would leave, with every reason:

Reason What it means
sole-evidence-for-topic The resource is the only live evidence for a topic, judged over the whole set. Sending retireOrphanedTopics: true answers it when those topics can be retired.
blocked-by-open-issues An open issue targets the resource. Sending dismissIssues: true answers it.
system-organization The resource belongs to the system organization. No answer lifts this.

lessonsClosing and lessonsStaying are judged over the whole set. Each has a count and a short preview of { id, title }. learnersInProgress is how many people are part-way through a lesson the delete itself would close. inFlightAccessRequired is true when that count is above zero, or when retiring the topics below would close a lesson someone is part-way through.

On organization scope, orphanedTopics names topics that would be left with no evidence (topics), topics that cannot be retired and why (blocked, with not-found, already-retired, topic-retired or not-active), and the resources holding them up (content). orphanedTopics.lessonsClosing is the lessons retiring those topics would leave with no surviving topic. A lesson built from a topic has no content id, so it is not in lessonsClosing above. orphanedTopics.learnersInProgress is how many people are part-way through those lessons. openIssues names how many open issues stand in the way, whether dismissing them would also close an issue that names something else (spansOtherContent), and which resources those issues block. On team scope those two are empty, and a blocked guide stays blocked.

POST /v1/content/deletions

Deletes the resources once every blocked reason is answered. Lessons this empties are closed. A lesson that still has other material stays open: a curated one is rebuilt, and a guided one is marked out of date.

Terminal window
curl -X POST "https://api.mereon.ai/v1/content/deletions" \
-H "Authorization: Bearer $MEREON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"contentIds": ["cnt_…"],
"inFlightAccess": "keep",
"retireOrphanedTopics": true
}'
Field Type Notes
contentIds string[] The same ids you previewed, 1 to 25.
inFlightAccess string keep leaves people part-way through a closing lesson going. revoke stops them. Required when learnersInProgress is above zero. Also required when retireOrphanedTopics is true and orphanedTopics.learnersInProgress is above zero. When the flag is true only because of those topics, and you are not retiring them, leave it out.
dismissIssues boolean Dismiss the open issues that block these resources. Leave it out, or send false, unless you mean to dismiss them.
retireOrphanedTopics boolean Retire topics this would leave with no evidence. Leave it out, or send false, unless you mean to retire them. When there are such topics, you also need permission to retire topics.

A field the body does not take is a 400, so a misspelt field is refused rather than ignored. Naming the same id twice is a 400 as well.

{
"results": [
{ "contentId": "cnt_…", "title": "Returns policy", "outcome": "deleted" }
],
"topicsRetired": 1,
"issuesDismissed": 0,
"complete": true
}

results follows the order of contentIds. outcome is deleted, unshared or kept. An organization admin’s success is deleted. A team admin’s success on a video, audio recording or document is unshared, which takes it off the teams they administer. A guide’s success is deleted. A resource that was already gone by the time the delete ran is deleted. kept means that resource was left in place, and reason says why. complete is true when every result is deleted or unshared.

topicsRetired and issuesDismissed count what this call already did. When a later resource is kept, those earlier writes stay and complete is false: an issue can be filed again, and a delete cannot be taken back.

The call is refused before anything changes when a resource is still blocked (409), when people are part-way through a closing lesson and inFlightAccess is missing (400), or when retiring topics was asked and you may not retire them (403). When more than one of these applies, the 409 is what you see first.

Status When
400 The body is invalid, an id is repeated, or people are part-way through a lesson this would close and inFlightAccess is missing.
403 The token lacks content:delete, you may not delete resources, you may not delete one of these resources, or you asked to retire topics and may not.
404 A resource is not one you can see, or the set names an id that does not exist.
409 A resource is still blocked with the answers given. details.blocked names each one and its reasons. Nothing is deleted.
429 Over the rate limit. Retry-After says when to try again.

Both routes are limited to 30 calls a minute and 300 an hour per connection. The MCP tools preview_content_deletion and delete_content are held to the same numbers, counted per tool. Each resource removed or taken off a team is recorded in the audit log.