Errors
Status codes and error bodies, and how to handle them.
Every error is a JSON object with a _tag, which names the error so code can branch on it, and a message, written for people: it says what went wrong and what to do. Show the message to whoever can fix the problem, and branch on the tag.
{"_tag": "TitleRequired","message": "Add a title before publishing. It's shown on your website and in search results."}
const response = await fetch(url, { headers, signal: AbortSignal.timeout(10_000) })if (!response.ok) {const error = await response.json()if (error._tag === 'VersionConflict') {// Read the document again, redo the change on top, and retry.}throw new Error(error.message)}
Status codes#
400Bad Request- The body isn’t valid JSON, a field has the wrong type or is out of range, or a required field is missing.
401Unauthorized- The token is missing, unknown, revoked or expired.
404Not Found- The record doesn’t exist in the token’s project, or the method and path don’t match an endpoint.
409Conflict- The request clashes with the record’s state: the document changed since your read, it’s in the wrong status for this step, or a brief is claimed.
413Payload Too Large- The body is over 20 MB, or the document would be over 2 MB.
422Unprocessable Entity- The request is well formed but breaks a rule, such as publishing without a title.
500Internal Server Error- Something went wrong on our side. Try again.
503Service Unavailable- Writing content without editor state is turned off for now.
Invalid requests#
When a parameter or body field has the wrong type, is out of range or is missing, the response is a 400 with the tag HttpApiDecodeError. issues lists each problem with the field’s path and a tag: Missing, Type or Refinement.
{"_tag": "HttpApiDecodeError","issues": [{"_tag": "Type","message": "must be a whole number between 1 and 100","path": ["limit"]}],"message": "The request is invalid: limit must be a whole number between 1 and 100. Fix the listed fields and try again."}
Request errors#
BadRequest400- The request body is not valid JSON. Send a JSON object with Content-Type: application/json.
Unauthorized401- Missing or invalid management token. See Authentication.
NotFound404- There is no such endpoint, or no record with that id (“documents 6704… not found”).
RequestEntityTooLarge413- The request body is too large. Send at most 20 MB.
Conflict409- Search Console isn’t ready for this project. The message says what to do.
InternalServerError500- Something went wrong on our side. Try again, and contact support if it keeps happening.
A 422 with the tag BadRequest means a rule outside the document workflow failed, such as a category slug that’s taken or an assignee who isn’t on the team. The message names the field and what to change.
Document errors#
Document content and workflow errors have their own tags. The endpoint pages list which ones each endpoint returns.
Version conflicts#
VersionConflict adds currentVersion. Read the document again, redo your change on the new content, and send it with the new version as baseVersion.
{"_tag": "VersionConflict","currentVersion": 9,"message": "This document changed since version 7. The current version is 9. Fetch the document again and reapply your edits."}
Every document error#
BaseVersionRequired400- An edits request without
baseVersion. Send theversionfrom your last read. RevisionNotFound404- The revision isn’t there. It may have been removed by the 200-revision limit.
BriefClaimHeld409- Only the agent that claimed the brief, or a person in PMKIN or the REST API, can withdraw it.
BriefClaimed409- Someone already claimed the brief. The message says who and when.
BriefClosed409- The document is already in review, scheduled or published, so its brief can’t be claimed or offered.
BriefNotOffered409- The brief isn’t ready or claimed.
BriefNotReady409- The brief isn’t ready to claim.
NotInReview409- Approve or request changes on a document that isn’t in review.
NotScheduled409- Unschedule a document that isn’t scheduled.
PublishNotAllowed409- Publish an idea or a scheduled document. Move the idea along, or unschedule first.
ScheduleNotAllowed409- Schedule an idea.
StatusLocked409- Change the status of a published or scheduled document. Unpublish or unschedule it first.
SubmitNotAllowed409- Submit a scheduled document for review.
VersionConflict409- The document changed since
baseVersion. The body hascurrentVersion. DocumentTooLarge413- The content would be over 2 MB. Split it into several documents.
ContentRequired422- Submit a document with no content.
EditInvalid422- An edit has none of
oldTextandnewText,appendorprepend. EditTextNotFound422- An
oldTextisn’t in the document. Copy it exactly, including whitespace and markdown. EditTextNotUnique422- An
oldTextmatches several places. Include more surrounding text. PublishAtInvalid422publishAtisn’t an ISO 8601 timestamp with a time zone, such as2026-10-20T09:00:00Z.PublishAtPast422publishAtis in the past.ScheduledNeedsTitleAndSlug422- Clear the title or slug of a scheduled document. Unschedule it first.
SlugRequired422- Publish, approve or schedule without a slug.
StatusInvalid422statusisn’t one of idea, planned, drafting, review, scheduled or published.StatusRequiresPublish422- A status update to published or scheduled. Use publish, approve or schedule.
StatusRequiresReview422- A status update to review. Use
POST /documents/:id/submit. TitleRequired422- Publish, approve or schedule without a title.
UnscheduleStatusInvalid422- Unschedule with a
statusother than drafting or review. WritesDisabled503- Writing content without
editorStateJsonis turned off. Try again later.
StatusRequiresPublish and StatusRequiresReview are shared with the MCP server and name its tools: publish_document and approve_document are POST …/publish and POST …/approve here, and submit_for_review is POST …/submit.Draft errors#
Confirming a draft checks every field and lists every problem at once in errors, so you can fix them all before you try again.
{"_tag": "IntentInvalid","errors": [{ "field": "status", "message": "Pick idea, planned or drafting. Drafts can't be created in review, scheduled or published." },{ "field": "title", "message": "Add a title. It's shown in lists and on your website." }],"message": "This draft can't be created yet. Fix the listed fields and try again."}