API documentation
Five endpoints. Header auth. Image bytes in, image bytes out.
Authentication
Send your key in the X-API-Key header. Authorization: Bearer <key>
is also accepted. Keys look like ss_live_… and are shown once, at creation.
If you lose one, rotate it from your dashboard — rotating revokes the previous key immediately.
-H "X-API-Key: ss_live_xxxxxxxxxxxxxxxxxxxxxxxx"
POST /v1/render
Renders a snippet and returns the raw image bytes — image/png by default,
or image/svg+xml with "format": "svg". Send a JSON body.
| Field | Type | Description |
|---|---|---|
code | string, required | The snippet to render. Up to 100 KB and 500 lines. |
language | string | Syntax to highlight. Unknown values fall back to plain text. Default plaintext. |
theme | string or object | One of the ids from /v1/themes, or a custom theme object — see below. Default midnight. |
format | string | png or svg. Default png. |
title | string | Filename shown in the window title bar. Max 60 characters. |
lineNumbers | boolean | Show a line-number gutter. Default false. |
windowControls | boolean | Show the red/yellow/green dots. Default true. |
padding | number | Backdrop padding in px, 0–160. Default 32. |
fontSize | number | Code font size in px, 10–32. Default 15. |
scale | number | Pixel density for PNG, 1–4. Default 2. |
Custom themes
Pass an object instead of an id to tweak one of the 20 presets rather than pick one as-is —
every field is optional, and anything you don't set falls through to extends
(default midnight). Colors must be plain hex (#rgb, #rrggbb
or with alpha) — see /v1/themes for the full list of overridable fields.
Every field below is optional — this example sets all of them just to show what exists. A real request would only include the ones you actually want to change.
{
"code": "const hi = 1;",
"language": "javascript",
"theme": {
"extends": "midnight",
"background": "#0a0014",
"window": "#1a0033",
"titleBar": "#241147",
"border": "#3d1a66",
"lineNumber": "#6b4a99",
"title": "#b799e6",
"shadow": 0.6,
"colors": {
"plain": "#e8ddff",
"keyword": "#ff00ff",
"string": "#00ffcc",
"number": "#ffcc00",
"comment": "#7a5c99",
"function": "#66ccff",
"type": "#ff9d00",
"property": "#00ffcc",
"operator": "#ff00ff",
"punctuation": "#b799e6"
}
}
}
Every successful response carries your quota state:
| Header | Meaning |
|---|---|
X-Quota-Used | Renders consumed this month. |
X-Quota-Remaining | Renders left before the quota resets. |
X-Render-Cached | true when served from cache. |
X-Image-Width / X-Image-Height | Output dimensions in CSS px. |
Other endpoints
| Endpoint | Auth | Returns |
|---|---|---|
GET /v1/usage | API key | Your current plan, usage and reset date. |
GET /v1/themes | none | Available theme ids and names. |
GET /v1/languages | none | Supported language identifiers. |
GET /v1/plans | none | Plans, prices and monthly limits. |
GET /healthz | none | Service health for uptime monitors. |
Errors
Failures return JSON: {"error": {"code": "...", "message": "..."}}.
| Status | Code | What happened |
|---|---|---|
| 400 | invalid_request | A field is missing or out of range. The field property says which. |
| 401 | unauthorized | Missing, invalid or revoked API key. |
| 402 | quota_exceeded | Monthly limit reached. Upgrade or wait for the reset. |
| 413 | payload_too_large | Request body above the size cap. |
| 429 | rate_limited | Too many requests. Honour the Retry-After header. |
| 503 | raster_unavailable | PNG backend is down. Retry, or request "format": "svg". |
Renders that fail after passing validation are refunded automatically — you are never billed for an image you did not receive.
Caching
Identical parameters always produce identical bytes, served from a content-addressed cache.
Cached responses still count against your quota (they're still API calls), but they return in
single-digit milliseconds. Responses carry a stable ETag, so you can revalidate
cheaply from your own CDN.
Full example
#!/usr/bin/env bash set -euo pipefail curl --fail-with-body -X POST "$SS_HOST/v1/render" \ -H "X-API-Key: $SS_KEY" \ -H "Content-Type: application/json" \ -d @- <<'JSON' --output snippet.png { "code": "SELECT id, email\nFROM users\nWHERE created_at > now() - interval '7 days';", "language": "sql", "theme": "sunset", "title": "recent_signups.sql", "lineNumbers": true, "scale": 3 } JSON