Workflow
Move documents through review, scheduling and publishing.
Documents move through six statuses: idea, planned, drafting, review, scheduled and published. You can set the first three with a plain update. Review, scheduling and publishing each have their own endpoint, because they do more than change the status.
Transitions#
| From | To | How |
|---|---|---|
| idea, planned, drafting, review | idea, planned or drafting | PATCH /documents/:id with status |
| any but scheduled | review | POST …/submit |
| review | drafting | POST …/request-changes |
| review | published, or scheduled with a future publishAt | POST …/approve |
| planned, drafting, review, published | published, or scheduled with a future publishAt | POST …/publish |
| planned, drafting, review, published, scheduled | scheduled | POST …/schedule |
| scheduled | drafting or review | POST …/unschedule |
| scheduled | published | PMKIN, within a minute of publishAt |
| published, scheduled | drafting | POST …/unpublish |
Publishing, approving and scheduling need a title and a slug.
isPublished says whether the document is live, separately from status. A published document you edit keeps serving the published version, and hasUnpublishedChanges turns true until you publish again.Endpoints#
Submit for review#
/documents/:id/submitSends the document to review. A claimed brief becomes drafted. Works from any status except scheduled.
idstringrequired- The document’s id.
messagestring- A note for the reviewer. At most 2,000 characters.
ContentRequired422- The document has no content yet.
SubmitNotAllowed409- The document is scheduled. Unschedule it first.
NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/submit" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"message": "Ready for review. I left the pricing table for last."}'
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": false,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "","publishedVersion": 0,"slug": "headless-cms-pricing","status": "review","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11,"review": {"feedback": null,"feedbackAt": null,"feedbackBy": null,"message": "Ready for review. I left the pricing table for last.","submittedAt": "2026-10-09T11:00:00.000Z","submittedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"}}}
Request changes#
/documents/:id/request-changesSends a document in review back to drafting, with feedback for the writer in review.feedback.
idstringrequired- The document’s id.
feedbackstring- What to change. At most 5,000 characters.
NotInReview409- The document isn’t in review.
NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/request-changes" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"feedback": "Add a pricing table and cite the survey."}'
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": false,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "","publishedVersion": 0,"slug": "headless-cms-pricing","status": "drafting","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11,"review": {"feedback": "Add a pricing table and cite the survey.","feedbackAt": "2026-10-09T15:30:00.000Z","feedbackBy": {"id": "66f0b2c4d5e6f7a8b9c0d1f0","name": "Maja Lind","type": "user"},"message": "Ready for review. I left the pricing table for last.","submittedAt": "2026-10-09T11:00:00.000Z","submittedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"}}}
Approve#
/documents/:id/approveApproves a document in review: publishes it now, or schedules it when publishAt is in the future. The document needs a title and a slug.
idstringrequired- The document’s id.
publishAtstring | null- An ISO 8601 timestamp with a time zone, such as
2026-10-20T09:00:00Z. A future time schedules the document instead of publishing it now.nullor leaving it out publishes now.
NotInReview409- The document isn’t in review. Submit it first, or publish it directly.
TitleRequired422- The document has no title.
SlugRequired422- The document has no slug.
PublishAtInvalid422publishAtisn’t an ISO 8601 timestamp with a time zone.NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/approve" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{}'
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": true,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","publishedVersion": 7,"slug": "headless-cms-pricing","status": "published","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11,"publishedAt": "2026-10-09T16:00:00.000Z"}
Publish#
/documents/:id/publishPublishes the current draft without review, setting the details you send first. Works from planned, drafting, review and published, so publishing again pushes new changes live.
idstringrequired- The document’s id.
titlestringrequired- The title to publish with.
slugstringrequired- The slug to publish with.
publishAtstring | null- An ISO 8601 timestamp with a time zone, such as
2026-10-20T09:00:00Z. A future time schedules the document instead of publishing it now.nullor leaving it out publishes now. categoryIdstring | null- The category’s id from
GET /categories.nulltakes the document out of its category. excerptstring- A short summary for lists and previews.
publishedAtstring- The publish date your site shows, as an ISO 8601 timestamp.
subtitlestring- A subtitle shown under the title.
PublishNotAllowed409- The document is an idea (move it to planned or drafting first) or scheduled (unschedule it first).
PublishAtPast422publishAtis in the past. Leave it out to publish now.PublishAtInvalid422publishAtisn’t an ISO 8601 timestamp with a time zone.HttpApiDecodeError400titleorslugis missing.NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/publish" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"slug": "headless-cms-pricing","title": "Headless CMS pricing"}'
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": true,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","publishedVersion": 7,"slug": "headless-cms-pricing","status": "published","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11,"publishedAt": "2026-10-09T16:00:00.000Z"}
Schedule#
/documents/:id/scheduleSchedules the current version to publish at publishAt. Later edits to the draft don’t change what publishes; schedule again to publish a newer version. Works from planned, drafting, review, published and scheduled. The document needs a title and a slug.
idstringrequired- The document’s id.
publishAtstringrequired- When to publish: an ISO 8601 timestamp with a time zone, in the future.
ScheduleNotAllowed409- The document is still an idea.
PublishAtPast422publishAtis in the past.PublishAtInvalid422publishAtisn’t an ISO 8601 timestamp with a time zone.TitleRequired422- The document has no title.
SlugRequiredwhen it has no slug. NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/schedule" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"publishAt": "2026-10-20T09:00:00Z"}'
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": false,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "","publishedVersion": 0,"slug": "headless-cms-pricing","status": "scheduled","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11,"publishAt": "2026-10-20T09:00:00Z","scheduledVersion": 7}
Unschedule#
/documents/:id/unscheduleCancels a schedule.
idstringrequired- The document’s id.
statusstring- Where the document goes back to:
drafting(the default) orreview.
NotScheduled409- The document isn’t scheduled.
UnscheduleStatusInvalid422statusis something other thandraftingorreview.NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/unschedule" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"status": "review"}'
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": false,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "","publishedVersion": 0,"slug": "headless-cms-pricing","status": "review","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11}
Unpublish#
/documents/:id/unpublishTakes the document off your site and moves it to drafting. A scheduled document loses its schedule too. The content stays.
idstringrequired- The document’s id.
NotFound404- No document with this id in the token’s project, or it was deleted.
curl -X POST "https://api.pmkin.io/documents/6704a1f0c2b3d4e5f6a7b8c9/unpublish" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN"
{"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "# Headless CMS pricing\n\nWhat each plan costs, and when an upgrade pays off.\n","contentUpdatedAt": "2026-10-08T09:12:44.000Z","contentUpdatedBy": {"agent": "Claude Code","id": "6703f6a7b8c9d0e1f2a3b4c5","name": "Writing agent","type": "token"},"coverImageUrl": null,"dueDate": "2026-10-20","hasUnpublishedChanges": false,"id": "6704a1f0c2b3d4e5f6a7b8c9","isPublished": false,"metaDescription": "","metaTitle": "","projectId": "66f0b2c4d5e6f7a8b9c0d1e2","publishedMarkdown": "","publishedVersion": 0,"slug": "headless-cms-pricing","status": "drafting","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 7,"wordCount": 11}