Model catalog
const url = 'https://api.harperharbor.com/open/v1/models?contextLevel=1';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.harperharbor.com/open/v1/models?contextLevel=1' \ --header 'Authorization: Bearer <token>'Returns configured model groups and current per-tier estimates. Requires chat.play. pendingAgent previews the unsaved mode. Agent estimates are typical/high credits and never a charge cap; use /player/agent-mode for the selected estimate and confirmation decision.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”story replaces costScore with the story-mode price. Any other value is ignored (no error).
Card id; used to read whether agent mode is on for the card (affects billingType, noLimitEligible, noLimitCovered) and to pick per-card price samples.
Context tier the client intends to use (a contextBudgetOptions[].value); affects noLimitCovered and dynamic price estimates. Invalid/<=0 becomes 1.
Read-only preview of the pending Agent selection. True uses token-priced Agent estimates and no unlimited-plan coverage; false previews ordinary mode. Does not save a preference.
Responses
Section titled “Responses”Successful response.
object
Localized group name.
Group description (may be empty).
object
Family name (e.g. a model generation); equals the model name for single-variant models.
Localized description.
Icon URL/identifier.
True if any variant requires membership.
True if any variant supports MAX output.
object
Label such as 64K.
Tier id to store in role-settings context.
Context budget in tokens.
Union of variant badges (e.g. new).
object
Value to store in role-settings thinkingDepth (off, high, max, ultra, on depending on the model).
Literal label when no i18n key exists.
Client i18n key.
Best health status among variants (variants without status count as green).
Remaining free uses for free-tier families; -1 = unlimited.
Sorted by costScore ascending.
One selectable model/lane. Fields marked omitempty in the server are absent when zero/false/empty.
object
Display name (localized for free-tier slots).
Stable model value to store in selectModel and to query uptime-history with.
Localized description.
Requires membership.
Speed rating.
Capability rating.
Safety/filter rating.
Points per turn at 1x (story price when scene=story; discounted price during a promotion).
Supports MAX output length.
Points per turn with MAX output.
Uses the cache-stable working-set context mode (affects contextBudgetOptions).
Agent mode available.
Warn before enabling agent mode.
Selectable context tiers; store the chosen value in role-settings context.
object
Label such as 64K.
Tier id to store in role-settings context.
Context budget in tokens.
Known value: new. Other values unverified.
Present only for reasoning models with selectable depth (absent when thinkingControl is none or adaptive).
object
Value to store in role-settings thinkingDepth (off, high, max, ultra, on depending on the model).
Literal label when no i18n key exists.
Client i18n key.
none = no thinking control; toggleable = use thinkingDepthOptions; adaptive = model decides, no control shown.
Upstream protocol; informational.
object
Green = healthy, yellow = degraded/high latency, red = unavailable, unknown = insufficient samples.
Percent 0-100.
object
Same signal scale as the performance metrics (copied from the latency metric).
object
object
Current-window median.
object
Current-window median.
object
Current-window median.
object
Current-window median.
object
Current-window median.
object
Current-window median.
object
Age of the newest availability evidence.
Status is based on synthetic probes only.
Lane/channel key, e.g. value_based, stable_1, stable_2, default, or a provider lane code.
Localized lane label.
Free-tier remaining uses; -1 = unlimited.
Percent.
Pre-discount 1x price (only during a promotion).
Promotion end, Unix seconds.
I18n key for the promotion label.
Platform chat discount relative to this lane’s normal tier price. Already included in quoted and billed chat rates; do not apply it again. Omitted when not discounted. Independent of upstream discounts and bare API pricing; no scheduled end date.
Upstream provider’s current discount in percent (no end date).
Lane was auto-generated from the provider roster (clients typically collapse these).
Covered by the unlimited plan in principle (false while agent mode is on for the card).
Covered by the unlimited plan at the requested contextLevel.
Present when billed by actual token usage; absent = fixed price.
Estimated minimum points per turn (dynamic billing).
Where the estimate comes from: this card’s samples, global samples, or a formula.
0 for formula.
Unix seconds.
Present (dynamic) if any variant is dynamically billed.
Example
[ { "families": [ { "bestStatus": "green", "variants": [ { "thinkingControl": "none", "apiFormat": "openai", "status": { "status": "green", "confidence": "none", "latencyBaseline": { "signal": "observing" }, "performance": { "latencyMs": { "signal": "observing" }, "firstTokenLatencyMs": { "signal": "observing" }, "charsPerSecond": { "signal": "observing" }, "tokensPerSecond": { "signal": "observing" }, "outputRate": { "signal": "observing" }, "completionRate": { "signal": "observing" } } }, "billingType": "dynamic", "estSource": "role" } ], "billingType": "dynamic", "estSource": "role" } ] }]Invalid_request
object
Error code (snake_case) or, for legacy handlers, a free-text/localized message.
Human-readable sentence. Present only on middleware errors and /me, /me/wallet.
Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.
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.
The token budget of required_context_tier for the selected model, for display.
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.
Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.
Only on insufficient_credits: the credits the wallet could set aside for it.
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
object
Error code (snake_case) or, for legacy handlers, a free-text/localized message.
Human-readable sentence. Present only on middleware errors and /me, /me/wallet.
Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.
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.
The token budget of required_context_tier for the selected model, for display.
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.
Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.
Only on insufficient_credits: the credits the wallet could set aside for it.
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}Insufficient_scope: requires chat.play
object
Error code (snake_case) or, for legacy handlers, a free-text/localized message.
Human-readable sentence. Present only on middleware errors and /me, /me/wallet.
Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.
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.
The token budget of required_context_tier for the selected model, for display.
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.
Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.
Only on insufficient_credits: the credits the wallet could set aside for it.
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: inaccessible resource
object
Error code (snake_case) or, for legacy handlers, a free-text/localized message.
Human-readable sentence. Present only on middleware errors and /me, /me/wallet.
Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.
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.
The token budget of required_context_tier for the selected model, for display.
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.
Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.
Only on insufficient_credits: the credits the wallet could set aside for it.
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}Chat_operation_conflict
object
Error code (snake_case) or, for legacy handlers, a free-text/localized message.
Human-readable sentence. Present only on middleware errors and /me, /me/wallet.
Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.
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.
The token budget of required_context_tier for the selected model, for display.
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.
Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.
Only on insufficient_credits: the credits the wallet could set aside for it.
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
object
Error code (snake_case) or, for legacy handlers, a free-text/localized message.
Human-readable sentence. Present only on middleware errors and /me, /me/wallet.
Whether retrying may succeed. Present only on middleware errors, /me, /me/wallet and service/share routes.
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.
The token budget of required_context_tier for the selected model, for display.
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.
Only on insufficient_credits: the credits this turn needs before it can start. Absent when the refusal came without an estimate.
Only on insufficient_credits: the credits the wallet could set aside for it.
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}