Skip to content

Update metadata, add/update/delete entries and bind a Lorebook in one request

POST
/open/v1/worldbook/{worldbookId}/document
curl --request POST \
--url https://api.harperharbor.com/open/v1/worldbook/example/document \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "metadata": { "name": "example", "description": "example", "iconUrl": "example", "tags": [ "example" ], "visibility": "private", "textPatches": { "description": { "baseSha256": "example", "operations": [ { "op": "replaceText", "oldText": "example", "newText": "example", "text": "example", "beforeText": "example", "afterText": "example", "replaceAll": false } ] }, "content": { "baseSha256": "example", "operations": [ { "op": "replaceText", "oldText": "example", "newText": "example", "text": "example", "beforeText": "example", "afterText": "example", "replaceAll": false } ] } } }, "entries": [ { "op": "create", "entryId": "example", "name": "example", "content": "example", "category": "rule", "keywords": [ "example" ], "secondaryKeywords": [ "example" ], "isEnabled": true, "isConstant": true, "triggerRegion": "both", "matchOptions": { "caseSensitive": false, "matchWholeWords": false, "selectiveLogic": 0, "selective": true, "scanDepth": 1, "order": 1, "groupId": "example", "groupOrder": 1, "extensions": {} }, "contentDeepPatch": { "baseSha256": "example", "operations": [ { "op": "replaceText", "oldText": "example", "newText": "example", "text": "example", "beforeText": "example", "afterText": "example", "replaceAll": false } ] }, "textPatches": { "description": { "baseSha256": "example", "operations": [ { "op": "replaceText", "oldText": "example", "newText": "example", "text": "example", "beforeText": "example", "afterText": "example", "replaceAll": false } ] }, "content": { "baseSha256": "example", "operations": [ { "op": "replaceText", "oldText": "example", "newText": "example", "text": "example", "beforeText": "example", "afterText": "example", "replaceAll": false } ] } } } ], "binding": { "roleId": "example", "targetType": "character", "targetId": "example" } }'

Applies metadata, entry operations and binding in one transaction; an invalid operation rolls back the entire request. At most 200 entry operations are accepted per request. The caller must own the Lorebook and any agent configuration being bound. Metadata replaces name, description, iconUrl and tags; omitted visibility is preserved. The response returns createdEntryIds in create-operation order. Read the book-specific entryContentMax from the detail endpoint; the widest bound language applies. There is no idempotency deduplication: after an unknown outcome, read the entries before repeating creates.

worldbookId
required
string

Lorebook id. Only the path parameter is honoured.

Media typeapplication/json
object
metadata

Full replacement of the Lorebook’s editable metadata. Fields not sent are blanked (description, iconUrl, tags) or reset to private (visibility), except when textPatches.description is present, in which case missing fields are back-filled from the current record.

object
name
required

Required, non-blank (name required).

string
description
string
iconUrl
string
tags
Array<string>
visibility

Unknown/omitted = private.

string
Allowed values: private public waitReview
textPatches
object
description

Metadata description deep patch.

object
baseSha256

Optional hex SHA-256 of the text the patch was computed against; the patch is rejected (invalid_field_patch) when it does not match the stored text.

string
operations
required

Operations applied in order.

Array<object>

One anchored text operation. Anchors (oldText, beforeText, afterText) must be found exactly once unless replaceAll is set; otherwise invalid_field_patch (anchor_not_found / anchor_not_unique / invalid_operation).

object
op
required

Operation kind. replaceText: replace oldText with newText; deleteText: remove oldText; insertText: insert text before beforeText or after afterText (exactly one anchor); appendText/prependText: add text at the end/start. oldText/text must be non-empty. Anchors must occur exactly once unless replaceAll is set (replace/delete only).

string
Allowed values: replaceText deleteText insertText appendText prependText
oldText

Text to find (replace operations).

string
newText

Replacement text.

string
text

Text to insert (insert operations).

string
beforeText

Anchor: insert before this text.

string
afterText

Anchor: insert after this text.

string
replaceAll

Replace every occurrence instead of requiring a unique anchor.

boolean
content

Entry content deep patch (update op; same as contentDeepPatch).

object
baseSha256

Optional hex SHA-256 of the text the patch was computed against; the patch is rejected (invalid_field_patch) when it does not match the stored text.

string
operations
required

Operations applied in order.

Array<object>

One anchored text operation. Anchors (oldText, beforeText, afterText) must be found exactly once unless replaceAll is set; otherwise invalid_field_patch (anchor_not_found / anchor_not_unique / invalid_operation).

object
op
required

Operation kind. replaceText: replace oldText with newText; deleteText: remove oldText; insertText: insert text before beforeText or after afterText (exactly one anchor); appendText/prependText: add text at the end/start. oldText/text must be non-empty. Anchors must occur exactly once unless replaceAll is set (replace/delete only).

string
Allowed values: replaceText deleteText insertText appendText prependText
oldText

Text to find (replace operations).

string
newText

Replacement text.

string
text

Text to insert (insert operations).

string
beforeText

Anchor: insert before this text.

string
afterText

Anchor: insert after this text.

string
replaceAll

Replace every occurrence instead of requiring a unique anchor.

boolean
entries
Array<object>
<= 200 items

One entry operation. create: name and content required (content non-blank and within the book’s entry limit: 4000 chars for Chinese, 6000 for Japanese or Korean, 12000 for English, following the language of the cards the book is bound to, the widest when there are several; an unbound book uses its own language; entryContentMax on GET /open/v1/worldbook/detail gives the value); category defaults to custom; triggerRegion defaults to both; isConstant defaults to false; matchOptions omitted = tavern default on tavern books, none on native books; keywords shorter than the minimum length are silently dropped (single characters are allowed only on tavern-format books). update: entryId required; empty-string name/content/category/triggerRegion mean ‘keep’; keywords/secondaryKeywords null/omitted = keep, [] = clear; isEnabled/isConstant/matchOptions omitted = keep; contentDeepPatch (or textPatches.content) edits the content in place. delete: entryId required. Unknown op fails with invalid_worldbook_document_operation.

object
op
required

Case-insensitive.

string
Allowed values: create update delete
entryId

Target entry for update/delete.

string
name
string
content

At most the book’s entry limit, entryContentMax on the Lorebook detail (4000 chars for Chinese, 6000 for Japanese or Korean, 12000 for English).

string
<= 12000 characters
category
string
Allowed values: rule character location item event custom
keywords
Array<string>
secondaryKeywords
Array<string>
isEnabled

Update only.

boolean
isConstant
boolean
triggerRegion
string
Allowed values: both user_only ai_only
matchOptions

Tavern-format keyword matching options. null on native entries.

object
caseSensitive
boolean
matchWholeWords
boolean
selectiveLogic

How secondaryKeywords gate activation: 0 = AND ANY (any secondary keyword present), 1 = NOT ALL, 2 = NOT ANY, 3 = AND ALL. Out-of-range values are normalized to 0.

integer
0
Allowed values: 0 1 2 3
selective

When false, ignore secondaryKeywords. If omitted, secondaryKeywords use selectiveLogic.

boolean
scanDepth

HarperHarbor: keyword scan window in messages, including current input. Zero or omitted uses the current input and latest assistant reply.

integer
<= 100
order

Author ordering for new admissions. Existing HarperHarbor context anchors keep their original positions.

integer
groupId

Optional logical entry identifier, scoped to one book. HarperHarbor semantic recall admits eligible imported fragments together.

string
<= 128 characters
groupOrder

Fragment order within groupId.

integer
<= 10000
extensions

Preserved author metadata. Unknown fields are not executed as matching or placement instructions.

object
key
additional properties
any
contentDeepPatch

Anchored edit applied to the current value of a text field.

object
baseSha256

Optional hex SHA-256 of the text the patch was computed against; the patch is rejected (invalid_field_patch) when it does not match the stored text.

string
operations
required

Operations applied in order.

Array<object>

One anchored text operation. Anchors (oldText, beforeText, afterText) must be found exactly once unless replaceAll is set; otherwise invalid_field_patch (anchor_not_found / anchor_not_unique / invalid_operation).

object
op
required

Operation kind. replaceText: replace oldText with newText; deleteText: remove oldText; insertText: insert text before beforeText or after afterText (exactly one anchor); appendText/prependText: add text at the end/start. oldText/text must be non-empty. Anchors must occur exactly once unless replaceAll is set (replace/delete only).

string
Allowed values: replaceText deleteText insertText appendText prependText
oldText

Text to find (replace operations).

string
newText

Replacement text.

string
text

Text to insert (insert operations).

string
beforeText

Anchor: insert before this text.

string
afterText

Anchor: insert after this text.

string
replaceAll

Replace every occurrence instead of requiring a unique anchor.

boolean
textPatches
object
description

Metadata description deep patch.

object
baseSha256

Optional hex SHA-256 of the text the patch was computed against; the patch is rejected (invalid_field_patch) when it does not match the stored text.

string
operations
required

Operations applied in order.

Array<object>

One anchored text operation. Anchors (oldText, beforeText, afterText) must be found exactly once unless replaceAll is set; otherwise invalid_field_patch (anchor_not_found / anchor_not_unique / invalid_operation).

object
op
required

Operation kind. replaceText: replace oldText with newText; deleteText: remove oldText; insertText: insert text before beforeText or after afterText (exactly one anchor); appendText/prependText: add text at the end/start. oldText/text must be non-empty. Anchors must occur exactly once unless replaceAll is set (replace/delete only).

string
Allowed values: replaceText deleteText insertText appendText prependText
oldText

Text to find (replace operations).

string
newText

Replacement text.

string
text

Text to insert (insert operations).

string
beforeText

Anchor: insert before this text.

string
afterText

Anchor: insert after this text.

string
replaceAll

Replace every occurrence instead of requiring a unique anchor.

boolean
content

Entry content deep patch (update op; same as contentDeepPatch).

object
baseSha256

Optional hex SHA-256 of the text the patch was computed against; the patch is rejected (invalid_field_patch) when it does not match the stored text.

string
operations
required

Operations applied in order.

Array<object>

One anchored text operation. Anchors (oldText, beforeText, afterText) must be found exactly once unless replaceAll is set; otherwise invalid_field_patch (anchor_not_found / anchor_not_unique / invalid_operation).

object
op
required

Operation kind. replaceText: replace oldText with newText; deleteText: remove oldText; insertText: insert text before beforeText or after afterText (exactly one anchor); appendText/prependText: add text at the end/start. oldText/text must be non-empty. Anchors must occur exactly once unless replaceAll is set (replace/delete only).

string
Allowed values: replaceText deleteText insertText appendText prependText
oldText

Text to find (replace operations).

string
newText

Replacement text.

string
text

Text to insert (insert operations).

string
beforeText

Anchor: insert before this text.

string
afterText

Anchor: insert after this text.

string
replaceAll

Replace every occurrence instead of requiring a unique anchor.

boolean
binding

Bind this Lorebook to a role. Send roleId (targetType defaults to character), or an explicit targetType/targetId pair. A role holds one active Lorebook; the previous binding is replaced.

object
roleId

Role id (used as targetId when targetType is character).

string
targetType
string
default: character
Allowed values: character role user mod
targetId
string

Summary of what was applied.

Media typeapplication/json
object
createdEntryIds
Array<string>
updatedCount
integer
deletedCount
integer
bound
boolean
metadataUpdated
boolean
worldbookId
string format: uuid
documentVersion
string
Allowed values: worldbookPatch.v1
Example
{
"documentVersion": "worldbookPatch.v1"
}

worldbook_limit_exceeded reports field, reason, index, max, actual and unit for an operation-count limit. Other validation errors use invalid_arguments with field, index and reason; length errors also include max, actual and unit. Entry indices are zero-based; document-level fields use -1. Fix the indicated field or split the batch before resending.

Media typeapplication/json
object
error
required

Error code (snake_case) or, for legacy handlers, a free-text/localized message.

string
message

Human-readable sentence. Present only on middleware errors and /me, /me/wallet.

string
retryable

Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.

boolean
required_context_tier

Only on a first-turn context_capacity_exceeded: the smallest context tier that fits the whole card with room to talk. Save it as context in player settings and resend. Absent when no tier fits.

integer
>= 1 <= 5
required_context_tokens

The token budget of required_context_tier for the selected model, for display.

integer
constant_lore_trim_fits

Only on a first-turn context_capacity_exceeded: whether saving trimConstantLore=true lets the card play at the current tier. Absent on mid-conversation capacity errors.

boolean
credits_needed

Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.

integer
credits_available

Only on insufficient_credits: the credits the wallet could set aside for it.

integer
Examplegenerated
{
"error": "example",
"message": "example",
"retryable": true,
"required_context_tier": 1,
"required_context_tokens": 1,
"constant_lore_trim_fits": true,
"credits_needed": 1,
"credits_available": 1
}

unauthorized.

Media typeapplication/json
object
error
required

Error code (snake_case) or, for legacy handlers, a free-text/localized message.

string
message

Human-readable sentence. Present only on middleware errors and /me, /me/wallet.

string
retryable

Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.

boolean
required_context_tier

Only on a first-turn context_capacity_exceeded: the smallest context tier that fits the whole card with room to talk. Save it as context in player settings and resend. Absent when no tier fits.

integer
>= 1 <= 5
required_context_tokens

The token budget of required_context_tier for the selected model, for display.

integer
constant_lore_trim_fits

Only on a first-turn context_capacity_exceeded: whether saving trimConstantLore=true lets the card play at the current tier. Absent on mid-conversation capacity errors.

boolean
credits_needed

Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.

integer
credits_available

Only on insufficient_credits: the credits the wallet could set aside for it.

integer
Examplegenerated
{
"error": "example",
"message": "example",
"retryable": true,
"required_context_tier": 1,
"required_context_tokens": 1,
"constant_lore_trim_fits": true,
"credits_needed": 1,
"credits_available": 1
}

permission_denied

Media typeapplication/json
object
error
required

Error code (snake_case) or, for legacy handlers, a free-text/localized message.

string
message

Human-readable sentence. Present only on middleware errors and /me, /me/wallet.

string
retryable

Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.

boolean
required_context_tier

Only on a first-turn context_capacity_exceeded: the smallest context tier that fits the whole card with room to talk. Save it as context in player settings and resend. Absent when no tier fits.

integer
>= 1 <= 5
required_context_tokens

The token budget of required_context_tier for the selected model, for display.

integer
constant_lore_trim_fits

Only on a first-turn context_capacity_exceeded: whether saving trimConstantLore=true lets the card play at the current tier. Absent on mid-conversation capacity errors.

boolean
credits_needed

Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.

integer
credits_available

Only on insufficient_credits: the credits the wallet could set aside for it.

integer
Examplegenerated
{
"error": "example",
"message": "example",
"retryable": true,
"required_context_tier": 1,
"required_context_tokens": 1,
"constant_lore_trim_fits": true,
"credits_needed": 1,
"credits_available": 1
}

not_found

Media typeapplication/json
object
error
required

Error code (snake_case) or, for legacy handlers, a free-text/localized message.

string
message

Human-readable sentence. Present only on middleware errors and /me, /me/wallet.

string
retryable

Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.

boolean
required_context_tier

Only on a first-turn context_capacity_exceeded: the smallest context tier that fits the whole card with room to talk. Save it as context in player settings and resend. Absent when no tier fits.

integer
>= 1 <= 5
required_context_tokens

The token budget of required_context_tier for the selected model, for display.

integer
constant_lore_trim_fits

Only on a first-turn context_capacity_exceeded: whether saving trimConstantLore=true lets the card play at the current tier. Absent on mid-conversation capacity errors.

boolean
credits_needed

Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.

integer
credits_available

Only on insufficient_credits: the credits the wallet could set aside for it.

integer
Examplegenerated
{
"error": "example",
"message": "example",
"retryable": true,
"required_context_tier": 1,
"required_context_tokens": 1,
"constant_lore_trim_fits": true,
"credits_needed": 1,
"credits_available": 1
}

temporarily_unavailable

Media typeapplication/json
object
error
required

Error code (snake_case) or, for legacy handlers, a free-text/localized message.

string
message

Human-readable sentence. Present only on middleware errors and /me, /me/wallet.

string
retryable

Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.

boolean
required_context_tier

Only on a first-turn context_capacity_exceeded: the smallest context tier that fits the whole card with room to talk. Save it as context in player settings and resend. Absent when no tier fits.

integer
>= 1 <= 5
required_context_tokens

The token budget of required_context_tier for the selected model, for display.

integer
constant_lore_trim_fits

Only on a first-turn context_capacity_exceeded: whether saving trimConstantLore=true lets the card play at the current tier. Absent on mid-conversation capacity errors.

boolean
credits_needed

Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.

integer
credits_available

Only on insufficient_credits: the credits the wallet could set aside for it.

integer
Examplegenerated
{
"error": "example",
"message": "example",
"retryable": true,
"required_context_tier": 1,
"required_context_tokens": 1,
"constant_lore_trim_fits": true,
"credits_needed": 1,
"credits_available": 1
}