Error Codes
Every SketchAPI failure carries a stable, machine-readable code. Branch on the code, never on the human-readable message.
Table of Contents
Control Plane Responses
Control-plane errors use one JSON envelope on every status:
{
"error": {
"code": "origin_not_allowed",
"message": "Parent origin is not allowed for this project.",
"details": {}
}
} details appears only when a field-level breakdown exists, such as validation
failures.
Codes returned by POST /v1/sessions and GET /v1/usage:
| Code | Status | Meaning | Action |
|---|---|---|---|
invalid_request | 400 | The request body or query failed validation. | Fix the request; details.fieldErrors names each invalid field. |
invalid_usage_period | 400 | period was not day or month. | Send a supported period. |
authentication_required | 401 | No API key was provided. | Send the key as Authorization: Bearer or x-api-key. |
invalid_api_key | 401 | The key is unknown or revoked. | Mint a new key in the dashboard and update your server secret. |
insufficient_scope | 403 | The key lacks the required scope. | details.required names the missing scope; mint a key with it. |
origin_not_allowed | 403 | parentOrigin is not registered for the project. | Register the exact origin in the dashboard before minting sessions for it. |
subscription_required | 403 | The owning account has no active SketchAPI subscription. | Start a plan from the pricing page, then retry. |
not_found | 404 | The route does not exist. | Check the request path and method. |
rate_limit_exceeded | 429 | Per-minute session creation limit reached. | Wait retry-after seconds; the x-ratelimit-* headers describe the window. |
monthly_session_limit_reached | 429 | Monthly session quota exhausted. | Contact us to raise your plan limit, or wait for the next calendar month. |
internal_error | 500 | Unexpected control-plane failure. | Retry with backoff; contact support if it persists. |
accounts_unavailable | 503 | Entitlement verification is temporarily unavailable. | Retry with backoff. |
Session creation also returns x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset on success (201) and on minute-limited failure (429), so
one code path can implement backoff.
Browser Client Errors
The browser client rejects with HostedSketchAPIError; read error.code:
import { HostedSketchAPIError, Sketchpad } from 'https://sketchapi.com/sdk/v1/sketchapi.js'
try {
await sketchpad.mount(container)
} catch (error) {
if (error instanceof HostedSketchAPIError && error.code === 'session_expired') {
// Request a fresh session from your server and mount a new instance.
}
} | Code | When | Action |
|---|---|---|
session_expired | The session passed expiresAt before mount(). | Mint a fresh session; sessions gate mounting only. |
session_unavailable | The instance no longer holds a session. | Create a new Sketchpad with a new session. |
session_token_in_url | The session token appeared inside frameUrl. | Never place the token in URLs; pass the session object untouched. |
instance_destroyed | A call arrived after destroy(). | Create a new instance; instances are single-use. |
parent_window_unavailable | The host element is detached from a live window. | Mount into a connected element. |
frame_unavailable | The hosted frame lost its browsing context. | Retry the mount with a fresh session. |
frame_load_failed | The frame document failed to load. | Check network access to sketchapi.com, then retry. |
frame_timeout | The frame did not finish loading in time. | Retry; raise requestTimeoutMs for slow networks. |
frame_handshake_timeout | The frame loaded but never announced readiness. | Retry; if persistent, check for frame-blocking extensions or CSP. |
protocol_version_unsupported | The cached client and hosted frame speak different protocol versions. | Reload the page so the browser fetches the current client. |
connection_timeout | The frame channel did not connect in time. | Retry the mount. |
connection_closed | The frame connection ended, usually after a fatal frame error. | Listen for onStateChange('destroyed') and remount with a fresh session. |
request_timeout | One API operation exceeded requestTimeoutMs. | Retry the operation; raise the timeout for heavy work such as large imports. |
message_error | A frame message failed to deserialize. | Retry; report the payload to support if reproducible. |
Session expiry never interrupts a mounted editor: expiresAt gates mounting
only, and a user who is already drawing keeps working. There is no session
renewal; remounting always uses a fresh session and a fresh Sketchpad instance.
Ready to build?