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

NameInTypeRequiredConstraintsMeaning
itemIdpathstringyesnoneBook to replace.
contentbodystringyesup to 1,000,000 bytesThe new markdown. Top-level # headings split it into pages.
expectedVersionbodyintegerno0 or moreThe version you read. Always send it when several writers can touch the book.

Request

bash
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

json
{
  "id": "cmabc123",
  "title": "Use The Index, Luke",
  "version": 8,
  "pageCount": 1,
  "updatedAt": "2026-10-01T09:30:00.000Z"
}

Errors

StatusMessageCodeFix
400content is requirednoneSend a string.
400expectedVersion must be a non-negative integer — pass the `version` field returned by GET /items/:id/contentnoneSend an integer.
409This 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_CONFLICTRead again, redo your edit, and retry with expectedVersion {b}. The body adds currentVersion, changedSince, nextAction and retryable.
413content exceeds maximum size of 1000000 bytes — …noneEdit one page, or append.
403This 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).noneAsk the owner for write access.
404Item not foundnoneCheck the id.
429Too many content writes in a short window — wait a minute and retry.RATE_LIMITEDWait 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

NameInTypeRequiredConstraintsMeaning
itemIdpathstringyesnoneBook to edit.
pageNumpathintegeryes1 to 999999Page to replace.
contentbodystringyesnot empty, up to 1,000,000 bytesThe new page.
expectedVersionbodyintegerno0 or moreThe version you read.

Request

bash
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

json
{
  "id": "cmabc123",
  "title": "Use The Index, Luke",
  "version": 9,
  "pageCount": 42,
  "updatedAt": "2026-10-01T09:31:00.000Z",
  "pageNum": 4
}

Errors

StatusMessageCodeFix
400pageNum must be a positive integernoneUse a whole number of 1 or more.
400content is requirednoneSend non-empty text.
400content would split into {n} pages — pages are split on top-level "# " headings and this operation replaces exactly one page. …INVALID_INPUTKeep one # heading. Demote the others to ##.
404Page {n} not found (document has {count} pages)nonePick a page inside the book.
409The version conflict messageVERSION_CONFLICTSame 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

NameInTypeRequiredConstraintsMeaning
itemIdpathstringyesnoneBook to extend.
contentbodystringyesnot empty, up to 1,000,000 bytesText to add.
positionbodystringnostart or endWhere to add it. Default end.

Request

bash
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

json
{
  "id": "cmabc123",
  "title": "Use The Index, Luke",
  "version": 10,
  "pageCount": 43,
  "updatedAt": "2026-10-01T09:32:00.000Z"
}

Errors

StatusMessageCodeFix
400content is requiredINVALID_INPUTSend non-empty text.
400position must be one of: start, endINVALID_INPUTUse start or end.
413content exceeds maximum size of 1000000 bytesPAYLOAD_TOO_LARGESend it in smaller parts.
413This write would grow the book past its fixed 30MB cap …noneThe 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

NameInTypeRequiredConstraintsMeaning
itemIdpathstringyesnoneBook to inspect.

Request

bash
curl https://heytrove.ai/api/v1/items/cmabc123/versions \
  -H "Authorization: Bearer trove_your_key"

Response

json
{
  "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

StatusMessageCodeFix
403Version history is available to the book's owner only. …FORBIDDENAsk the owner.
429The read-limit messageREAD_LIMIT_EXCEEDEDStop. 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

NameInTypeRequiredConstraintsMeaning
itemIdpathstringyesnoneBook to restore.
versionbodyintegeryes1 or moreVersion from the list.

Request

bash
curl https://heytrove.ai/api/v1/items/cmabc123/versions \
  -H "Authorization: Bearer trove_your_key" \
  -H "Content-Type: application/json" \
  -d '{"version":9}'

Response

json
{
  "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

StatusMessageCodeFix
400version must be a positive integer — list restorable versions with GET /items/:id/versionsINVALID_INPUTSend a version of 1 or more.
404No snapshot at version {n}. Available versions: {list}NOT_FOUNDPick a listed version.
409Version {n} is a single-page rollback point from an append, not a full copy of the book — …CONFLICTPick a version from the list.

CLI equivalent: trove items restore.

    Writing API | Trove