Skip to content

Set the opening message, alternate openings and prologue options

PATCH
/open/v1/role/{roleId}/welcome
curl --request PATCH \
--url https://api.harperharbor.com/open/v1/role/example/welcome \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "roleWelcome": "example", "alternates": [ "example" ], "prologue": [ "example" ], "idempotencyKey": "example" }'

Writes the opening (roleWelcome, required, non-blank) of an owned private role. alternates (alternate AI openings the player can pick before the first turn) and prologue (player-side first lines offered as choices) are full replacements distinguished by presence: key absent = unchanged, empty array = cleared. Neither list has a fixed item-count limit; blank entries are omitted. Every entry — like roleWelcome itself — is bounded by the welcome limit of the card language (8000 chars; 10000 for English cards; role_welcome_too_long). The role must be private (public_role_requires_clone). Limit and visibility violations are surfaced as HTTP 500 by the error mapper.

roleId
required
string

Role id.

Media typeapplication/json
object
roleWelcome
required

Opening message; non-blank; limit 8000 chars (English 10000).

string
alternates

Alternate AI openings; full replacement when present; [] clears. Blank entries dropped.

Array<string>
prologue

Player-side first-line options; full replacement when present; [] clears.

Array<string>
idempotencyKey

Accepted; not used for deduplication.

string
Examplegenerated
{
"roleWelcome": "example",
"alternates": [
"example"
],
"prologue": [
"example"
],
"idempotencyKey": "example"
}

Role summary; fieldChars.roleWelcome reports before/after character counts.

Media typeapplication/json

Summary returned by every role write.

object
roleId
required

Role id.

string
roleVisibility
required

Current visibility. HarperHarbor defaults to unlisted (usable by ID without community listing).

string
Allowed values: private public waitReview unlisted
reviewStatus
required

Moderation status.

string
Allowed values: not_submitted pending passed rejected
accountPermission
required

Always owner on these routes.

string
Allowed values: owner
patch

Present when a deep patch was applied to a single field.

object
patchedOperations
required

Number of operations applied.

integer
charsBefore
required

Rune count before.

integer
charsAfter
required

Rune count after.

integer
sha256Before
required

Hex SHA-256 of the text before.

string
sha256After
required

Hex SHA-256 of the text after.

string
textPatches

Per-field patch summaries keyed by field name; present when fieldPatches were used.

object
key
additional properties
object
patchedOperations
required

Number of operations applied.

integer
charsBefore
required

Rune count before.

integer
charsAfter
required

Rune count after.

integer
sha256Before
required

Hex SHA-256 of the text before.

string
sha256After
required

Hex SHA-256 of the text after.

string
fieldChars

Character counts before/after for the edited field (e.g. roleDetailDesc, roleWelcome).

object
key
additional properties
object
before
required

Character (rune) count before the write.

integer
after
required

Character (rune) count after the write.

integer
nextRecommendedTools
required

Suggested next MCP tool names; informational.

Array<string>
Example
{
"roleVisibility": "private",
"reviewStatus": "not_submitted",
"accountPermission": "owner"
}

invalid JSON body, roleWelcome is required.

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
}

record not found, public_role_requires_clone, role_welcome_too_long, or another unclassified error; retryable: true.

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
}