Skip to content

Render an opening through the card's display rules

GET
/open/v1/role/render
curl --request GET \
--url 'https://api.harperharbor.com/open/v1/role/render?roleId=example' \
--header 'Authorization: Bearer <token>'

Applies the author’s display rules to one opening of a card owned by the bearer, using the same engine the play page runs, and returns the text the player’s renderer receives before Markdown expansion. {{char}} and {{user}} are expanded first: {{user}} becomes the card’s player name, or a language default when that name is a placeholder such as 你 or user. Each rule reports applied, unmatched, disabled, empty or rolled_back (with the engine’s reason: bad_regex, empty_match, replacement_alone, volume or timeout). {{random}} always takes its first option, so two renders of the same card are identical. report.unsupported lists author-API identifiers the card’s chat page does not provide, with a hint: on a classic-page card that is the sandbox sdk, [data-chat] nodes and --chat-* variables (switch the card to the sandbox page); on any page it is MMD’s platform state variables. capture says what still needs a browser. The play page remains authoritative for Markdown, HTML card components, layout and contrast.

roleId
required
string

Role id.

opening
integer

Which opening to render: 0 (default) is roleWelcome; N is welcomeAlternates[N-1]. Out of range is invalid_param.

Render report.

Media typeapplication/json
object
roleId
required
string
opening
required
object
index
required
integer
count
required

Main opening plus alternates.

integer
names
required
object
player
required

What {{user}} was expanded to.

string
character
required

What {{char}} was expanded to.

string
source
required

The chosen opening with {{char}} and {{user}} expanded, before any rule.

string
rendered
required

After the display rules: what the renderer receives. Markdown is not expanded.

string
authorAsset
required

Null when the card has no display rules.

object
version
required
integer
pageMode
required
string
mountLayer
required
string
mountTrigger
required
string
cardFormat
required
string
rules
required

Total rules.

integer
enabled
required

Enabled rules.

integer
rules
required

One entry per rule, in application order.

Array<object>
object
id
required
string
name
required
string
status
required
string
Allowed values: applied unmatched disabled empty rolled_back
reason

Only with rolled_back.

string
Allowed values: bad_regex empty_match replacement_alone volume timeout
report
required

Static scan of rendered; nothing here needs a browser.

object
chars
required
integer
estimatedTokens
required
integer
tags
required

Count per HTML tag name.

object
key
additional properties
integer
components
required

hc-* HTML card component classes found.

Array<string>
scripts
required
integer
styles
required
integer
inlineHandlers
required

Inline on*= event handlers.

integer
externalUrls
required

At most 50 distinct http(s) URLs.

Array<string>
unsupported
required
Array<object>

An author-API identifier the card’s chat page does not provide.

object
api
required
string
count
required
integer
where
required

rendered, welcome, or rule:<id>.

Array<string>
hint
required

What to do: switch the card to the sandbox page, or drop the call because no chat page provides it.

string
crossLineRules
required

Whether any enabled rule can match across lines; such rules disable the streaming render cache.

boolean
warnings
required

Human-readable notes: rolled-back rules and unsupported identifiers.

Array<string>
capture
required

The provider takes no screenshots; recommended says what to check in a browser.

object
serverCaptureAvailable
required
boolean
recommended
required
string
Example
{
"rules": [
{
"status": "applied",
"reason": "bad_regex"
}
]
}

roleId is required, or invalid_param when opening is not an index into the openings.

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
}

role_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 when the rules could not be evaluated within the render deadline; 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
}