Reference
Writing API
Updated 1 Oct 2026
On this page
For agents
Load this page when: you need to edit book text over HTTP, or recover from a VERSION_CONFLICT
- Read the book first and send its version as expectedVersion on every replace.
- On VERSION_CONFLICT, read again, redo your edit on the fresh text, and retry. Nothing was lost.
- Use append when you only add content. It never conflicts.
Every write saves the earlier text as a version first, except appends. Writes share one budget of content writes. See Errors.
The write checks work like this: read the book with Get full content, and send its version back as expectedVersion. If anyone wrote since, the server refuses your write.
Replace a whole book
PUT https://heytrove.ai/api/v1/items/{itemId}/content
Replaces the full text. Everything not in content is deleted. Use it for books under 1 MB.
Parameters
| Name | In | Type | Required | Constraints | Meaning |
|---|---|---|---|---|---|
itemId | path | string | yes | none | Book to replace. |
content | body | string | yes | up to 1,000,000 bytes | The new markdown. Top-level # headings split it into pages. |
expectedVersion | body | integer | no | 0 or more | The version you read. Always send it when several writers can touch the book. |
Request
curl -X PUT https://heytrove.ai/api/v1/items/cmabc123/content \
-H "Authorization: Bearer trove_your_key" \
-H "Content-Type: application/json" \
-d '{"content":"# Anatomy of an Index\n\nUpdated text.","expectedVersion":7}'Response
{
"id": "cmabc123",
"title": "Use The Index, Luke",
"version": 8,
"pageCount": 1,
"updatedAt": "2026-10-01T09:30:00.000Z"
}Errors
| Status | Message | Code | Fix |
|---|---|---|---|
| 400 | content is required | none | Send a string. |
| 400 | expectedVersion must be a non-negative integer — pass the `version` field returned by GET /items/:id/content | none | Send an integer. |
| 409 | This book changed since you read it - you based this write on version {a} and it is now version {b}. Your write was NOT applied and nothing was lost. | VERSION_CONFLICT | Read again, redo your edit, and retry with expectedVersion {b}. The body adds currentVersion, changedSince, nextAction and retryable. |
| 413 | content exceeds maximum size of 1000000 bytes — … | none | Edit one page, or append. |
| 403 | This item is read-only for your account — you can view it but not edit it (you don't own it and don't have team write access). | none | Ask the owner for write access. |
| 404 | Item not found | none | Check the id. |
| 429 | Too many content writes in a short window — wait a minute and retry. | RATE_LIMITED | Wait for Retry-After. |
CLI equivalent: trove items put.
Replace one page
PUT https://heytrove.ai/api/v1/items/{itemId}/pages/{pageNum}
Replaces exactly one page. Only that page travels, so it works on books of any size. The new content must be one page: a single top-level # heading, with other headings at ## or lower. Page 1 may have no heading.
Parameters
| Name | In | Type | Required | Constraints | Meaning |
|---|---|---|---|---|---|
itemId | path | string | yes | none | Book to edit. |
pageNum | path | integer | yes | 1 to 999999 | Page to replace. |
content | body | string | yes | not empty, up to 1,000,000 bytes | The new page. |
expectedVersion | body | integer | no | 0 or more | The version you read. |
Request
curl -X PUT https://heytrove.ai/api/v1/items/cmabc123/pages/4 \
-H "Authorization: Bearer trove_your_key" \
-H "Content-Type: application/json" \
-d '{"content":"# Where Clauses\n\nNew text.","expectedVersion":8}'Response
{
"id": "cmabc123",
"title": "Use The Index, Luke",
"version": 9,
"pageCount": 42,
"updatedAt": "2026-10-01T09:31:00.000Z",
"pageNum": 4
}Errors
| Status | Message | Code | Fix |
|---|---|---|---|
| 400 | pageNum must be a positive integer | none | Use a whole number of 1 or more. |
| 400 | content is required | none | Send non-empty text. |
| 400 | content would split into {n} pages — pages are split on top-level "# " headings and this operation replaces exactly one page. … | INVALID_INPUT | Keep one # heading. Demote the others to ##. |
| 404 | Page {n} not found (document has {count} pages) | none | Pick a page inside the book. |
| 409 | The version conflict message | VERSION_CONFLICT | Same as above. |
CLI equivalent: trove items put with ID:PAGE.
Append or prepend pages
POST https://heytrove.ai/api/v1/items/{itemId}/pages
Adds content to the end of a book, or to the start. Only the new text travels, and it never conflicts with another writer. Start the text with a # heading so it becomes its own page. An append is not saved as a restorable version.
Parameters
| Name | In | Type | Required | Constraints | Meaning |
|---|---|---|---|---|---|
itemId | path | string | yes | none | Book to extend. |
content | body | string | yes | not empty, up to 1,000,000 bytes | Text to add. |
position | body | string | no | start or end | Where to add it. Default end. |
Request
curl https://heytrove.ai/api/v1/items/cmabc123/pages \
-H "Authorization: Bearer trove_your_key" \
-H "Content-Type: application/json" \
-d '{"content":"# New chapter\n\nText."}'Response
{
"id": "cmabc123",
"title": "Use The Index, Luke",
"version": 10,
"pageCount": 43,
"updatedAt": "2026-10-01T09:32:00.000Z"
}Errors
| Status | Message | Code | Fix |
|---|---|---|---|
| 400 | content is required | INVALID_INPUT | Send non-empty text. |
| 400 | position must be one of: start, end | INVALID_INPUT | Use start or end. |
| 413 | content exceeds maximum size of 1000000 bytes | PAYLOAD_TOO_LARGE | Send it in smaller parts. |
| 413 | This write would grow the book past its fixed 30MB cap … | none | The cap is permanent. Split the content into separate books. Do not retry. |
CLI equivalent: trove items append.
List versions
GET https://heytrove.ai/api/v1/items/{itemId}/versions
Lists up to 50 earlier versions, newest first. Only the owner can list them. The call counts as one read.
Parameters
| Name | In | Type | Required | Constraints | Meaning |
|---|---|---|---|---|---|
itemId | path | string | yes | none | Book to inspect. |
Request
curl https://heytrove.ai/api/v1/items/cmabc123/versions \
-H "Authorization: Bearer trove_your_key"Response
{
"id": "cmabc123",
"title": "Use The Index, Luke",
"currentVersion": 10,
"versions": [
{
"version": 9,
"savedAt": "2026-10-01T09:31:00.000Z",
"bytes": 81234,
"describes": "The text the book held at version 8."
}
],
"note": "…"
}Each entry holds the text as it was before the write that produced the next version. The wording of describes and note comes from the server.
Errors
| Status | Message | Code | Fix |
|---|---|---|---|
| 403 | Version history is available to the book's owner only. … | FORBIDDEN | Ask the owner. |
| 429 | The read-limit message | READ_LIMIT_EXCEEDED | Stop. Tell the user. |
CLI equivalent: trove items history.
Restore a version
POST https://heytrove.ai/api/v1/items/{itemId}/versions
Restores an earlier version. The current text is saved first, so a restore can itself be undone. Restoring version N brings back the text the book held at version N-1.
Parameters
| Name | In | Type | Required | Constraints | Meaning |
|---|---|---|---|---|---|
itemId | path | string | yes | none | Book to restore. |
version | body | integer | yes | 1 or more | Version from the list. |
Request
curl https://heytrove.ai/api/v1/items/cmabc123/versions \
-H "Authorization: Bearer trove_your_key" \
-H "Content-Type: application/json" \
-d '{"version":9}'Response
{
"id": "cmabc123",
"title": "Use The Index, Luke",
"version": 11,
"pageCount": 42,
"updatedAt": "2026-10-01T09:40:00.000Z"
}The response adds unchanged and note when the version already equals the stored text.
Errors
| Status | Message | Code | Fix |
|---|---|---|---|
| 400 | version must be a positive integer — list restorable versions with GET /items/:id/versions | INVALID_INPUT | Send a version of 1 or more. |
| 404 | No snapshot at version {n}. Available versions: {list} | NOT_FOUND | Pick a listed version. |
| 409 | Version {n} is a single-page rollback point from an append, not a full copy of the book — … | CONFLICT | Pick a version from the list. |
CLI equivalent: trove items restore.