API: Stories
Stories: sections, edit locks, sharing, comments, publishing and versions. All endpoints require authentication unless noted. 44 endpoints.
GET /api/stories
Section titled “GET /api/stories”List the stories the caller can see
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
tab |
"all" | "mine" | "shared" | "assigned" | "archived" |
no | |
q |
string | no | |
limit |
integer | no | |
offset |
integer | no |
Responses: 200 · 400 · 401
POST /api/stories
Section titled “POST /api/stories”Create a story
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | no | |
summary |
string | null | no | |
sections |
array of object | no | |
templateId |
string | no |
Responses: 201 · 400 · 401 · 409
GET /api/stories/{id}
Section titled “GET /api/stories/{id}”Read a story and its sections
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
PATCH /api/stories/{id}
Section titled “PATCH /api/stories/{id}”Update a story’s title, summary or data mode (live, or a snapshot kept at publishing)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
baseEditSeq |
integer | no |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | no | |
summary |
string | null | no | |
mode |
"live" | "snapshot" |
no |
Responses: 200 · 400 · 401 · 404
DELETE /api/stories/{id}
Section titled “DELETE /api/stories/{id}”Delete a story
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 204 — No content · 401 · 404
GET /api/stories/{id}/access
Section titled “GET /api/stories/{id}/access”List who a story is shared with
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401
POST /api/stories/{id}/access
Section titled “POST /api/stories/{id}/access”Share a story with a workspace member
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes | |
permission |
"viewer" | "commenter" | "contributor" | "editor" |
yes |
Responses: 201 · 400 · 401 · 409
GET /api/stories/{id}/access-check
Section titled “GET /api/stories/{id}/access-check”Before sharing: what the person would see and which live blocks their data access hides
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
email |
string | yes | |
permission |
"viewer" | "commenter" | "contributor" | "editor" |
no |
Responses: 200 · 400 · 401 · 404
DELETE /api/stories/{id}/access/{accessId}
Section titled “DELETE /api/stories/{id}/access/{accessId}”Stop sharing a story with someone
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
accessId |
string | yes |
Responses: 204 — No content · 401 · 404
GET /api/stories/{id}/access/candidates
Section titled “GET /api/stories/{id}/access/candidates”Search workspace members to share a story with (or to mention)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
q |
string | no |
Responses: 200 · 400 · 401
GET /api/stories/{id}/activity
Section titled “GET /api/stories/{id}/activity”What happened to the story, newest first (page with ?before=<id>)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit |
integer | no | |
before |
integer | no |
Responses: 200 · 400 · 401
POST /api/stories/{id}/ai/next
Section titled “POST /api/stories/{id}/ai/next”Suggest the story’s next section: a title, a question for Write with AI, and why (one metered AI call)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404 · 502 · 503
POST /api/stories/{id}/ai/rewrite
Section titled “POST /api/stories/{id}/ai/rewrite”Rewrite a selection: shorten, expand, tone, fix or translate (one metered AI call)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
text |
string | yes | |
action |
"shorten" | "expand" | "tone" | "fix" | "translate" |
yes | |
tone |
"professional" | "friendly" | "concise" | "confident" |
no | |
language |
string | no |
Responses: 200 · 400 · 401 · 403 · 404 · 502 · 503
POST /api/stories/{id}/archive
Section titled “POST /api/stories/{id}/archive”Archive a story, or bring it back
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
archived |
boolean | yes |
Responses: 200 · 400 · 401 · 404
PUT /api/stories/{id}/follow
Section titled “PUT /api/stories/{id}/follow”Follow a story: hear in the app (and on the phone) when it is published again or someone comments
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
DELETE /api/stories/{id}/follow
Section titled “DELETE /api/stories/{id}/follow”Stop following a story
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/presence
Section titled “POST /api/stories/{id}/presence”Heartbeat: say you have the story open; returns who else does and each section’s state
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/publish
Section titled “POST /api/stories/{id}/publish”Publish the story: everyone whose role can view Stories can read it; a version is saved
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
GET /api/stories/{id}/readers
Section titled “GET /api/stories/{id}/readers”Who has read the story and for how long (editors and the owner)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/review
Section titled “POST /api/stories/{id}/review”Ask people to review the story before it is published (closes any earlier round)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
reviewerIds |
array of string | yes | |
note |
string | null | no |
Responses: 201 · 400 · 401 · 409
DELETE /api/stories/{id}/review
Section titled “DELETE /api/stories/{id}/review”Cancel the review round (whoever asked for it, or the story’s owner)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 204 — No content · 401 · 404
POST /api/stories/{id}/review/decision
Section titled “POST /api/stories/{id}/review/decision”As a reviewer: approve the story, or ask for changes
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
decision |
"approved" | "changes_requested" |
yes | |
note |
string | null | no |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/sections
Section titled “POST /api/stories/{id}/sections”Add a section to a story
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | null | no | |
content |
object | no | |
source |
"manual" | "ai" | "ai_edited" |
no | |
ai |
object | null | no | |
afterSectionId |
string | null | no | |
atStart |
boolean | no |
Responses: 201 · 400 · 401 · 409
PATCH /api/stories/{id}/sections/{sectionId}
Section titled “PATCH /api/stories/{id}/sections/{sectionId}”Edit a section (refused while someone else holds its lock)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
baseEditSeq |
integer | no |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | null | no | |
content |
object | no | |
source |
"manual" | "ai" | "ai_edited" |
no | |
ai |
object | null | no | |
status |
"draft" | "in_review" | "done" |
no |
Responses: 200 · 400 · 401 · 404
DELETE /api/stories/{id}/sections/{sectionId}
Section titled “DELETE /api/stories/{id}/sections/{sectionId}”Delete a section
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Responses: 204 — No content · 401 · 404
POST /api/stories/{id}/sections/{sectionId}/ai/refresh
Section titled “POST /api/stories/{id}/sections/{sectionId}/ai/refresh”After a section’s live numbers changed: the AI’s revision of the words that no longer fit (one metered call)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
paragraphs |
array of object | yes | |
changes |
array of object | yes |
Responses: 200 · 400 · 401 · 404 · 502 · 503
PUT /api/stories/{id}/sections/{sectionId}/editors
Section titled “PUT /api/stories/{id}/sections/{sectionId}/editors”Name the people who alone may edit a section (an empty list lifts the restriction)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
userIds |
array of string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/sections/{sectionId}/lock
Section titled “POST /api/stories/{id}/sections/{sectionId}/lock”Take or renew the edit lock on a section (423 when someone else holds it)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Responses: 200 · 400 · 401 · 404
DELETE /api/stories/{id}/sections/{sectionId}/lock
Section titled “DELETE /api/stories/{id}/sections/{sectionId}/lock”Release your edit lock on a section
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Responses: 204 — No content · 401 · 404
POST /api/stories/{id}/sections/{sectionId}/read-only
Section titled “POST /api/stories/{id}/sections/{sectionId}/read-only”Lock a section read-only (nobody edits it until it is unlocked), or unlock it
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
locked |
boolean | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/sections/{sectionId}/suggestions/{commentId}/accept
Section titled “POST /api/stories/{id}/sections/{sectionId}/suggestions/{commentId}/accept”Accept a suggested edit: the quoted text is replaced and the suggestion resolved
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes | |
commentId |
string | yes |
Responses: 200 · 400 · 401 · 404
PUT /api/stories/{id}/sections/{sectionId}/visibility
Section titled “PUT /api/stories/{id}/sections/{sectionId}/visibility”Who can read a section: everyone who reads the story, or only people who can see all its data
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
visibility |
"everyone" | "data_access" |
yes |
Responses: 200 · 400 · 401 · 404
PATCH /api/stories/{id}/sections/{sectionId}/work
Section titled “PATCH /api/stories/{id}/sections/{sectionId}/work”Assign a section, set its due date, or move its status (not an edit of its text)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
sectionId |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
status |
"draft" | "in_review" | "done" |
no | |
assigneeId |
string | null | no | |
dueAt |
string | null | no |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/sections/reorder
Section titled “POST /api/stories/{id}/sections/reorder”Reorder a story’s sections
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
order |
array of string | yes |
Responses: 204 — No content · 401 · 404
POST /api/stories/{id}/share/slack
Section titled “POST /api/stories/{id}/share/slack”Post a link to the story in a Slack channel (title, summary and your note — never data)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
webhookId |
string | yes | |
note |
string | null | no |
Responses: 200 · 400 · 401 · 404
GET /api/stories/{id}/slack-targets
Section titled “GET /api/stories/{id}/slack-targets”The Slack channels a story can be shared to (the workspace’s Slack webhooks, by name)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401
GET /api/stories/{id}/versions
Section titled “GET /api/stories/{id}/versions”List a story’s saved versions
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401
GET /api/stories/{id}/versions/{version}
Section titled “GET /api/stories/{id}/versions/{version}”Read one saved version
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
version |
integer | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/{id}/versions/{version}/restore
Section titled “POST /api/stories/{id}/versions/{version}/restore”Restore a saved version (recorded as a new version)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
version |
integer | yes |
Responses: 200 · 400 · 401 · 404
POST /api/stories/ai/outline
Section titled “POST /api/stories/ai/outline”Draft a story’s outline from a goal: a title and sections, each with a question for Write with AI (one metered AI call)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
goal |
string | yes |
Responses: 200 · 400 · 401 · 404 · 502 · 503
GET /api/stories/templates
Section titled “GET /api/stories/templates”Story templates: the built-in ones, then the workspace’s own
Responses: 200 · 400 · 401
POST /api/stories/templates
Section titled “POST /api/stories/templates”Save a story’s sections as a workspace template
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | |
description |
string | null | no | |
storyId |
string | yes |
Responses: 201 · 400 · 401 · 409
GET /api/stories/templates/{templateId}
Section titled “GET /api/stories/templates/{templateId}”One template with its sections
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
templateId |
string | yes |
Responses: 200 · 400 · 401 · 404
DELETE /api/stories/templates/{templateId}
Section titled “DELETE /api/stories/templates/{templateId}”Remove a workspace template (its author or an admin)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
templateId |
string | yes |
Responses: 204 — No content · 401 · 404