Intents
Create documents, clusters and categories through drafts you confirm.
Documents, clusters and categories are created through drafts, called intents. Start one with the fields you know, fill in the rest over as many requests as you need, then confirm it. Confirming checks every field and either creates the record or lists every problem at once.
- Each token has its own drafts. Other tokens’ drafts answer
404. - Drafts never expire. Discard the ones you don’t need.
- A token can have at most 100 unfinished drafts per project.
- Send fields at the top level of the body.
nullclears a field.
Fields#
Document intents#
titlestring | null- Required to confirm. At most 300 characters.
statusstring | null- idea, planned or drafting. Defaults to drafting, or idea when the draft has a brief.
slugstring | null- The URL slug. At most 200 characters.
markdownstring | null- The first content, as markdown. At most 2,097,152 characters.
briefobject | null- The brief, with the same fields as on the Briefs page.
assigneeIdstring | null- A team member’s id from GET /members.
categoryIdstring | null- A category’s id from GET /categories.
clusterIdstring | null- A cluster’s id from GET /clusters.
dueDatestring | null- The due date, YYYY-MM-DD.
Cluster intents#
namestring | null- Required to confirm. At most 100 characters, unique in the project ignoring case.
descriptionstring | null- What the topic covers. At most 2,000 characters.
keywordsstring[] | null- Keywords the topic targets. At most 50, each at most 100 characters.
A project can have at most 200 clusters.
Category intents#
namestring | null- Required to confirm. At most 200 characters.
slugstring | null- Required to confirm. Lowercase letters, numbers and single hyphens, unique in the project. At most 200 characters.
descriptionstring | null- What the category covers. Writers get it with each brief. At most 2,000 characters.
categoryIdstring | null- The parent category’s id, for a subcategory.
Endpoints#
The endpoints are the same for every kind. Replace {kind} with document, cluster or category, as in /document-intents.
Create a draft#
/{kind}-intentsStarts a draft with the fields you send. Only types and lengths are checked now; everything else is checked when you confirm. Answers 201.
kindstringrequireddocument,clusterorcategory.
BadRequest422- The token already has 100 unfinished drafts in this project. Confirm or discard some first.
HttpApiDecodeError400- A field has the wrong type or is too long.
curl -X POST "https://api.pmkin.io/document-intents" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"brief": {"intent": "commercial","keyword": "headless cms pricing"},"clusterId": "6702d4e5f6a7b8c9d0e1f2a3","status": "idea","title": "Headless CMS pricing"}'
{"createdAt": "2026-10-09T08:00:00.000Z","createdBy": {"name": "Writing agent","type": "token"},"fields": {"brief": {"intent": "commercial","keyword": "headless cms pricing"},"clusterId": "6702d4e5f6a7b8c9d0e1f2a3","status": "idea","title": "Headless CMS pricing"},"id": "6705e6f7a8b9c0d1e2f3a4b5","kind": "document","updatedAt": "2026-10-09T08:00:00.000Z"}
List drafts#
/{kind}-intentsLists the calling token’s drafts of this kind, most recently updated first, at most 100. Document drafts leave out markdown; get one draft to read it.
kindstringrequireddocument,clusterorcategory.
curl "https://api.pmkin.io/document-intents" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN"
[{"createdAt": "2026-10-09T08:00:00.000Z","createdBy": {"name": "Writing agent","type": "token"},"fields": {"brief": {"intent": "commercial","keyword": "headless cms pricing"},"clusterId": "6702d4e5f6a7b8c9d0e1f2a3","status": "idea","title": "Headless CMS pricing"},"id": "6705e6f7a8b9c0d1e2f3a4b5","kind": "document","updatedAt": "2026-10-09T08:00:00.000Z"}]
Get a draft#
/{kind}-intents/:idReturns one draft with every field.
kindstringrequireddocument,clusterorcategory.idstringrequired- The draft’s id.
NotFound404- No draft with this id for the calling token. It may have been confirmed or discarded already.
curl "https://api.pmkin.io/document-intents/6705e6f7a8b9c0d1e2f3a4b5" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN"
{"createdAt": "2026-10-09T08:00:00.000Z","createdBy": {"name": "Writing agent","type": "token"},"fields": {"brief": {"intent": "commercial","keyword": "headless cms pricing"},"clusterId": "6702d4e5f6a7b8c9d0e1f2a3","status": "idea","title": "Headless CMS pricing"},"id": "6705e6f7a8b9c0d1e2f3a4b5","kind": "document","updatedAt": "2026-10-09T08:00:00.000Z"}
Update a draft#
/{kind}-intents/:idSets the fields you send and leaves the others alone. null clears a field.
kindstringrequireddocument,clusterorcategory.idstringrequired- The draft’s id.
NotFound404- No draft with this id for the calling token. It may have been confirmed or discarded already.
HttpApiDecodeError400- A field has the wrong type or is too long.
curl -X PATCH "https://api.pmkin.io/document-intents/6705e6f7a8b9c0d1e2f3a4b5" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN" \-H "Content-Type: application/json" \-d '{"dueDate": "2026-10-20"}'
{"createdAt": "2026-10-09T08:00:00.000Z","createdBy": {"name": "Writing agent","type": "token"},"fields": {"brief": {"intent": "commercial","keyword": "headless cms pricing"},"clusterId": "6702d4e5f6a7b8c9d0e1f2a3","status": "idea","title": "Headless CMS pricing","dueDate": "2026-10-20"},"id": "6705e6f7a8b9c0d1e2f3a4b5","kind": "document","updatedAt": "2026-10-09T08:05:00.000Z"}
Discard a draft#
/{kind}-intents/:idDiscards the draft and returns it.
kindstringrequireddocument,clusterorcategory.idstringrequired- The draft’s id.
NotFound404- No draft with this id for the calling token. It may have been confirmed or discarded already.
curl -X DELETE "https://api.pmkin.io/document-intents/6705e6f7a8b9c0d1e2f3a4b5" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN"
{"createdAt": "2026-10-09T08:00:00.000Z","createdBy": {"name": "Writing agent","type": "token"},"fields": {"brief": {"intent": "commercial","keyword": "headless cms pricing"},"clusterId": "6702d4e5f6a7b8c9d0e1f2a3","status": "idea","title": "Headless CMS pricing"},"id": "6705e6f7a8b9c0d1e2f3a4b5","kind": "document","updatedAt": "2026-10-09T08:00:00.000Z"}
Confirm a draft#
/{kind}-intents/:id/confirmChecks every field and creates the document, cluster or category. When anything is wrong, nothing changes, the draft stays, and the 422 lists every problem at once, sorted by field. On success the draft is deleted and the response, a 201, holds the new record under its kind (document, cluster or category) and intentId.
kindstringrequireddocument,clusterorcategory.idstringrequired- The draft’s id.
IntentInvalid422- One or more fields are missing or invalid.
errorslists eachfieldwith amessage. NotFound404- No draft with this id for the calling token. It may have been confirmed or discarded already.
curl -X POST "https://api.pmkin.io/document-intents/6705e6f7a8b9c0d1e2f3a4b5/confirm" \-H "Authorization: Bearer $PMKIN_MANAGEMENT_TOKEN"
{"document": {"assigneeId": "66f0b2c4d5e6f7a8b9c0d1f0","authorId": "66f0b2c4d5e6f7a8b9c0d1f0","categoryId": "6701c3d4e5f6a7b8c9d0e1f2","clusterId": "6702d4e5f6a7b8c9d0e1f2a3","content": "","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": "idea","subtitle": "","teamId": "66f0b2c4d5e6f7a8b9c0d1e1","title": "Headless CMS pricing","updatedAt": "2026-10-08T09:12:44.000Z","version": 0,"wordCount": 0,"brief": {"audience": "Marketing leads comparing headless CMS plans","claimedAt": null,"claimedBy": null,"intent": "commercial","internalLinks": ["66fe91a2b3c4d5e6f7a8b9c0"],"keyword": "headless cms pricing","notes": "Use list prices from October 2026.","outline": "Who each plan is for\nWhat it costs as you grow\nWhen to upgrade","referenceUrls": ["https://example.com/cms-pricing-survey"],"state": "none","wordCount": "1,500–2,000"}},"intentId": "6705e6f7a8b9c0d1e2f3a4b5"}
brief and status idea or planned, confirm them, then mark each brief ready.