Management API

Content and edits

Replace or edit a document’s markdown safely with baseVersion.

A document’s content is GitHub Flavored Markdown: headings, paragraphs, emphasis, links, images, lists, task lists, blockquotes, code blocks, tables and horizontal rules. Writes change the draft; readers see the change after the document is published again. Every write records a revision.

Write safely with baseVersion#

Every document has a version that goes up with each content write. Read the document, make your change, and send the version you read as baseVersion. If someone wrote in between, nothing is written and you get a 409 VersionConflict with the currentVersion. Read the document again, redo your change on the new content, and retry.

Prefer edits
For a change to part of a document, send edits instead of the whole text. They’re smaller, and an edit that no longer matches fails instead of quietly undoing someone else’s work.

Limits#

  • A document’s content can be at most 2 MB.
  • A markdown field can be at most 2,097,152 characters.
  • The whole request body can be at most 20 MB.

Endpoints#

Replace the content#

PUT/documents/:id/content

Replaces the draft with new markdown and records a revision. Readers see the change after the document is published again.

The response is the document summary with the new version and hasUnpublishedChanges.

Path parameters
idstringrequired
Body
markdownstringrequired
baseVersioninteger
messagestring
editorStateJsonstring
Errors
VersionConflict409
DocumentTooLarge413
NotFound404
WritesDisabled503
curl -X PUT "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/content" \
-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"baseVersion": 7,
"markdown": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n\n## Free plans\n\nMost vendors offer one.\n",
"message": "Add a section on free plans"
}'
Response: 200 OK
{
"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0",
"briefState": "claimed",
"categoryId": "6701c3d4e5f6a7b8c9d0e1f2",
"clusterId": "6702d4e5f6a7b8c9d0e1f2a3",
"contentUpdatedBy": {
"agent": "Claude Code",
"id": "6703f6a7b8c9d0e1f2a3b4c5",
"name": "Writing agent",
"type": "token"
},
"dueDate": "2026-10-20",
"id": "6704a1f0c2b3d4e5f6a7b8c9",
"isPublished": false,
"slug": "headless-cms-pricing",
"status": "drafting",
"title": "Headless CMS pricing",
"updatedAt": "2026-10-08T09:12:44.000Z",
"wordCount": 11,
"hasUnpublishedChanges": false,
"version": 8
}

Edit the content#

POST/documents/:id/content/edits

Changes part of the draft without sending all of it. All edits apply, or none do: the first edit that fails stops the request and nothing is written. One revision records them all.

Kinds of edit#

  • { "oldText", "newText" } replaces text. oldText must match exactly one place in the document, including whitespace and markdown syntax. Copy it from the content you read, with enough around it to be unique. An empty newText deletes it.
  • { "append" } adds text as a new paragraph at the end.
  • { "prepend" } adds text as a new paragraph at the start.

Each edit sees the result of the ones before it. Error messages count edits from 1, so Edit 2 failed means the second.

Path parameters
idstringrequired
Body
editsobject[]required
baseVersionintegerrequired
messagestring
Errors
BaseVersionRequired400
VersionConflict409
EditTextNotFound422
EditTextNotUnique422
EditInvalid422
DocumentTooLarge413
NotFound404
WritesDisabled503
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/content/edits" \
-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"baseVersion": 7,
"edits": [
{
"newText": "What each plan costs in 2026, and when an upgrade pays off.",
"oldText": "What each plan costs, and when an upgrade pays off."
},
{
"append": "## Free plans\n\nMost vendors offer one."
}
],
"message": "Date the intro and add free plans"
}'
Response: 200 OK
{
"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0",
"briefState": "claimed",
"categoryId": "6701c3d4e5f6a7b8c9d0e1f2",
"clusterId": "6702d4e5f6a7b8c9d0e1f2a3",
"contentUpdatedBy": {
"agent": "Claude Code",
"id": "6703f6a7b8c9d0e1f2a3b4c5",
"name": "Writing agent",
"type": "token"
},
"dueDate": "2026-10-20",
"id": "6704a1f0c2b3d4e5f6a7b8c9",
"isPublished": false,
"slug": "headless-cms-pricing",
"status": "drafting",
"title": "Headless CMS pricing",
"updatedAt": "2026-10-08T09:12:44.000Z",
"wordCount": 11,
"hasUnpublishedChanges": false,
"version": 8
}