Help · API reference
Drafts and content
Drafts, content, review and publishing.
List project draftsGET /api/v1/projects/{project}/drafts
Lists the project's drafts and branches the caller can see (shared branches and their own sessions) in every status, most recently updated first, as one unpaged data list. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)
200 Success.
What comes back
dataarray of object, requiredA list of:
idstring, requiredkind"session" | "branch", requiredtitlestring, requiredstatusstring, requiredbranchstring, requiredoriginstring, requiredcreated_bystring | null, requiredcreated_atstring, required: ISO 8601 timestamp.updated_atstring, required: ISO 8601 timestamp.head_commitstring, requiredbase_commitstring, requiredpreview_urlstring | null, required: The line’s stable preview address; null until somebody asks for one.preview_visibility"members" | "public", requiredpreview_public_untilone of: string | null, requiredOne of:
string. ISO 8601 timestamp.
null
expires_atone of: string | null, required: When the line is tidied away: an idle session, or an assistant’s line whose token died. Null for a branch.One of:
string. ISO 8601 timestamp.
null
publish_atone of: string | null, requiredOne of:
string. ISO 8601 timestamp.
null
merged_intostring | null, required: Where a merged line went:live(published) or the id of the line it was folded into. Null while open.scheduled_bystring | null, required: Who setpublish_at; null when nothing is scheduled.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - default Any other failure, as RFC 9457 problem details.
Create a project draftPOST /api/v1/projects/{project}/drafts
Opens a new draft on its own branch from the live branch and answers 201 with it; title defaults to Untitled changes. Needs the draft-create permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)Idempotency-Key(header, string, optional): Optional. A key the caller chooses, at most 160 characters, kept per team. A repeat of the same request (method, path and body) under the same key is answered with the first result and the headerIdempotent-Replay: true, and the work is not done twice. The same key with a different request answers 409; so does a repeat sent while the first is still running, withRetry-After: 5.
Body (application/json)
titlestring, 1 to 120 characters, default "Untitled changes"
201 Success. Headers: Idempotent-Replay.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Get a project draftGET /api/v1/projects/{project}/drafts/{draft}
Returns a draft with its head commit, how far it is behind the live branch, its review state and history, preview builds and invitations, and whether publishing it is blocked. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - default Any other failure, as RFC 9457 problem details.
Update a project draftPATCH /api/v1/projects/{project}/drafts/{draft}
Renames a draft (title). Needs the draft-create permission. A draft that is already published or discarded keeps its name and the request is refused.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
titlestring, required, 1 to 120 characters
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Delete a project draftDELETE /api/v1/projects/{project}/drafts/{draft}
Discards a draft: its branch is archived in the repository and open reviews close. Needs the draft-create permission for your own draft and the team-members permission for someone else's. A published draft cannot be discarded.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - default Any other failure, as RFC 9457 problem details.
List draft commentsGET /api/v1/projects/{project}/drafts/{draft}/comments
Returns the draft's whole review thread: every comment (data) and every review request (requests), oldest first, unpaged. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - default Any other failure, as RFC 9457 problem details.
Create a draft commentPOST /api/v1/projects/{project}/drafts/{draft}/comments
Adds a comment to the draft's review thread, optionally pinned to a page (page_path) or block (block_id), and notifies the others on the project who may comment. Answers 201 with the comment. Needs the review-comment permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
bodystring, required, 1 to 4000 characterspage_pathstring, at most 300 charactersblock_idstring, at most 64 characters
201 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Compare a draft against liveGET /api/v1/projects/{project}/drafts/{draft}/compare
Compares two versions, by default the live branch (from) against the draft (to), and lists what changed, naming pages whose editor work is not saved yet (unsaved). Comparing live against the draft also returns code an assistant wrote, with diffs. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)from(query, string, optional)to(query, string, optional)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - default Any other failure, as RFC 9457 problem details.
List draft content in a collectionGET /api/v1/projects/{project}/drafts/{draft}/content/{collection}
Lists a collection's entries on the draft. Without paging parameters it answers the whole list as a bare array; with limit (1 to 500) or after (a slug) it answers entries and next, in slug order. x-webentor-commit gives the draft's head. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)collection(path, string)after(query, string, optional)limit(query, string, optional)
200 Success.
What comes back
One of:
A list of:
slugstring, requiredfieldsobject, required: The entry’s scalar fields (title, description, order, …);_invalid: truefor a file that does not parse.countsobject, required: How many blocks a page has; empty for an entry that does not parse.
entriesarray of object, requiredA list of:
slugstring, requiredfieldsobject, required: The entry’s scalar fields (title, description, order, …);_invalid: truefor a file that does not parse.countsobject, required: How many blocks a page has; empty for an entry that does not parse.
nextstring | null, required: Theafterfor the next page; null on the last.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Create a draft content entryPOST /api/v1/projects/{project}/drafts/{draft}/content/{collection}
Creates an entry (slug, data) on the draft as a commit and answers 201 with the commit. Needs the content-write permission. The draft must be open, and an existing slug is refused.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)collection(path, string)
Body (application/json)
slugstring, required, 1 to 200 characters: The new entry’s slug;/makes a nested path.dataany, required: The entry, shaped by the collection’s own schema. The editor door’sdescribe_collectiontool reads it.
201 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Get a draft content entryGET /api/v1/projects/{project}/drafts/{draft}/content/{collection}/{slug}
Returns one entry's document on the draft. The ETag is the draft's head commit; send it back as If-Match when writing. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)collection(path, string)slug(path, string): May contain unencoded/: this is a path, not a single segment. Encoded slashes will not match.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 404 Not found. Also returned when the resource exists but the caller may not see it, so that the two cannot be told apart. (
codeisnot_found.) - default Any other failure, as RFC 9457 problem details.
Write a draft content entryPUT /api/v1/projects/{project}/drafts/{draft}/content/{collection}/{slug}
Writes an entry's whole document on the draft as a commit and answers with the commit and whether anything changed. Needs the content-write permission, and the draft must be open. With If-Match set to the ETag you read, the write is refused with 412 if the draft has moved since.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)collection(path, string)slug(path, string): May contain unencoded/: this is a path, not a single segment. Encoded slashes will not match.If-Match(header, string, optional): Optimistic concurrency: the revision the write is based on.
Body (application/json)
The whole entry, replacing what is there: read it with GET at the same address, change it, send it back. Send the ETag that read answered as If-Match, so a change made in between is refused with 412 rather than overwritten. A document that does not fit its envelope is refused with 422 and issues; one that fits the envelope but not the project’s block or collection schema fails the next build, so validate it first (GET …/validate, or the editor door’s describe_collection and validate_content tools).
One of:
titlestringdescriptionstringregionstringblocksarray of object, requiredA list of:
typestring, required
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Delete a draft content entryDELETE /api/v1/projects/{project}/drafts/{draft}/content/{collection}/{slug}
Deletes an entry from the draft as a commit and answers with the commit. Needs the content-write permission. The draft must be open.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)collection(path, string)slug(path, string): May contain unencoded/: this is a path, not a single segment. Encoded slashes will not match.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - default Any other failure, as RFC 9457 problem details.
Rename a draft content entryPOST /api/v1/projects/{project}/drafts/{draft}/content/{collection}/{slug}/rename
Moves an entry to a new slug (to) on the draft as a commit, carrying any unsaved editor work with it. Needs the content-write permission. The draft must be open, and a slug that is taken is refused.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)collection(path, string)slug(path, string): May contain unencoded/: this is a path, not a single segment. Encoded slashes will not match.
Body (application/json)
tostring, required, 1 to 200 characters: The new slug.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Get draft historyGET /api/v1/projects/{project}/drafts/{draft}/history
Returns the draft branch's commits, newest first, up to limit (50 by default, at most 200), as a data list with no further paging. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)limit(query, integer, optional), at most 200, default 50
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - default Any other failure, as RFC 9457 problem details.
Create a draft keepPOST /api/v1/projects/{project}/drafts/{draft}/keep
Postpones the cleanup of an idle editing session or assistant line, so it is not removed for another 30 days; the answer gives the new expires_at. Needs the draft-create permission. A branch never expires, so asking for one is refused.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Get draft manifestGET /api/v1/projects/{project}/drafts/{draft}/manifest
Returns the project's content manifest (collections and their schemas) and lock file as they are on the draft. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - default Any other failure, as RFC 9457 problem details.
Create a draft mergePOST /api/v1/projects/{project}/drafts/{draft}/merge
Merges the draft into the live branch or into another line (into), without deploying anything; the live site changes only when published. Into live it needs the deploy-production permission, and under review_required the draft must be approved and editors and developers may not publish; into a line it needs the content-write permission. Conflicting files come back as a 409, and decisions settles them.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
intostring, default "live": Where to merge:live, or the id of another line.decisionsobject: Repository path → the side that wins what that file could not merge. For a page this settles only the blocks both sides changed (the 409 names them underconflicts); the other edits of both sides are kept. For any other file the chosen side is taken whole. The answer lists what a decision set aside underdiscarded.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Preview a draftPOST /api/v1/projects/{project}/drafts/{draft}/preview
Queues a preview build of the draft's head, or of an older commit of it (at), and answers with build_id, the line's lasting preview address (url) and this build's address (build_url). A finished build of the same commit is reused. Needs the draft-read permission. The draft must be open.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)at(query, string, optional)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 404 Not found. Also returned when the resource exists but the caller may not see it, so that the two cannot be told apart. (
codeisnot_found.) - 409 Conflict. (
codeisconflict.) - default Any other failure, as RFC 9457 problem details.
Replace preview accessPUT /api/v1/projects/{project}/drafts/{draft}/preview/access
Sets who can open the draft's preview: team members only (members) or anyone with the link (public) for days (1, 7 or 30; 7 by default). Needs the draft-create permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
visibility"members" | "public", requireddaysone of: 1 | 7 | 30: How long a public preview stays public; 7 when omitted.One of:
1
7
30
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Create a preview invitePOST /api/v1/projects/{project}/drafts/{draft}/preview/invites
Invites one person by email to the draft's preview and emails them a personal link; the answer carries the link and whether it was emailed. Needs the draft-create permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
emailstring (email), required, at most 200 characters, matches ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
201 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Delete a preview inviteDELETE /api/v1/projects/{project}/drafts/{draft}/preview/invites/{invite}
Revokes one person's invitation to the draft's preview, so the personal link they were emailed stops working at once. The revocation is recorded. Needs the draft-create permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)invite(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 404 Not found. Also returned when the resource exists but the caller may not see it, so that the two cannot be told apart. (
codeisnot_found.) - default Any other failure, as RFC 9457 problem details.
Publish a draftPOST /api/v1/projects/{project}/drafts/{draft}/publish
Publishes the draft: merges it into the live branch and queues a production build, answering 202 with the commit and build_id; the site changes when the build finishes. It needs the deploy-production permission, and under review_required the draft must be approved and editors and developers may not publish. Refused for a draft already published or discarded, while a rollback is unresolved, or with unsaved editor work.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)Idempotency-Key(header, string, optional): Optional. A key the caller chooses, at most 160 characters, kept per team. A repeat of the same request (method, path and body) under the same key is answered with the first result and the headerIdempotent-Replay: true, and the work is not done twice. The same key with a different request answers 409; so does a repeat sent while the first is still running, withRetry-After: 5.
202 Success. Headers: Idempotent-Replay.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - default Any other failure, as RFC 9457 problem details.
Submit a draft for reviewPOST /api/v1/projects/{project}/drafts/{draft}/review
Sends the draft for review, optionally with a note, and notifies the named reviewer (reviewer_id) or else everyone who may decide. Needs the review-submit permission. A draft already published or discarded is refused, and reviewer_id must be someone on the project.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
notestring, at most 2000 charactersreviewer_idstring (uuid), matches ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$: A member to ask; omitted, anyone who may decide.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Approve or reject a draftPOST /api/v1/projects/{project}/drafts/{draft}/review/decision
Approves the draft or requests changes (decision), optionally with a note. Needs the review-decide permission. The draft must be in review, nobody may approve their own draft, and an approval is refused if the draft has changed since it was sent, or since reviewed_head.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
decision"approve" | "request_changes", requirednotestring, at most 2000 charactersreviewed_headstring, matches ^[0-9a-f]{7,64}$: The draft’shead_committhe reviewer read; a decision on a version that has moved is refused.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Replace a draft schedulePUT /api/v1/projects/{project}/drafts/{draft}/schedule
Schedules the draft to publish itself at at (ISO 8601), or cancels the schedule with null; permissions are checked again when it fires. Setting a time needs the deploy-production permission, and under review_required the draft must be approved and editors and developers may not publish. at may be at most a year ahead, unsaved editor work is refused, and a closed draft cannot be scheduled.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
atone of: string (date-time) | null, required: When to publish, ISO 8601;nullcancels.One of:
string (date-time)
null
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Synchronise a draftPOST /api/v1/projects/{project}/drafts/{draft}/sync
Brings the live branch, or another line named in from, into the draft, keeping the draft's changes; nothing to bring in answers Already up to date. Needs the content-write permission. The draft must be open; conflicting files come back as a 409, and decisions settles them.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
Body (application/json)
fromstring, default "live": What to bring in:live, or the id of another line.decisionsobject: Repository path → the side that wins what that file could not merge. For a page this settles only the blocks both sides changed (the 409 names them underconflicts); the other edits of both sides are kept. For any other file the chosen side is taken whole. The answer lists what a decision set aside underdiscarded.
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - 403 Not allowed. (
codeisforbidden.) - 409 Conflict. (
codeisconflict.) - 422 Validation failed. The body carries an
issuesarray describing each rejected field. (codeisvalidation_failed.) - default Any other failure, as RFC 9457 problem details.
Validate a draftGET /api/v1/projects/{project}/drafts/{draft}/validate
Checks the draft's content against the project's schemas and answers ok with a list of problems, each naming what would fail and why. Needs the draft-read permission.
Who may call it: A signed-in session, or an access token (write to change anything)
Parameters
project(path, string)draft(path, string)
200 Success.
Errors it can answer
- 401 Authentication required. (
codeisunauthenticated.) - default Any other failure, as RFC 9457 problem details.