Docs
How to wire a game to sloptimize cloud, what each key does, and every API route. The package itself, including the recorder and the frame sample, is documented in INTEGRATION.md on GitHub.
Setup
- Install the package.
npm install sloptimize
- Create a project. Sign in with GitHub, go to Projects, and name it. You land on its settings page. Mint a publishable key and a secret key there; the page shows these snippets filled in.
- Browser. Add a cloud sink beside the recorder. The publishable key is safe to ship in the bundle.
import { createRecorder, createErrorMonitor, createCloudSink } from 'sloptimize'; const rec = createRecorder({ budgetFrameMs: 16.7 }); createErrorMonitor(rec); const cloud = createCloudSink({ key: 'pk_live_…', endpoint: 'https://sloptimizejs.com/v1/ingest', build: BUILD_ID }); // every ~2 s cloud.enqueue(rec.drainRecords()); - Game server (Node). A tick over budget becomes a server hitch, attributed by the V8 sampler.
import { createServerRuntime } from 'sloptimize/node'; const server = createServerRuntime({ key: process.env.SLOPTIMIZE_KEY, endpoint: 'https://sloptimizejs.com/v1/ingest', build: BUILD_ID, tickBudgetMs: 16 }); server.tick(() => stepWorld()); - Check it. Play for a minute, then open the project's Timeline. Heartbeats appear within five minutes; incidents appear as they happen.
Keys and tokens
Publishable keypk_live_… | Belongs to one project. Write-only: it can send records and nothing else, so it is the only credential a game build may contain. Minted on the project's settings page. |
|---|---|
Secret keysk_live_… | Belongs to one project. Sends records and reads the whole catalogue. For the game server, the CLI and the MCP server. Never in a browser bundle. Minted on the settings page, shown once. |
Access tokenat_live_… | Acts as you across the whole API: it lists and creates projects, mints and revokes project keys, and reads any of your projects. Give one to a coding agent or a CI job so it can set a project up without you. It cannot send records. Minted on your account page, shown once, revocable there. |
Every API call sends its credential as Authorization: Bearer <token>. An access token also passes ?project=<slug> on project routes to say which project it means.
Dashboard
- Issues. The catalogue by cause. Each row is one footprint: a stable identity for a cause, counted across players and builds, with its worst occurrence, where it happens, and the fixes applied to it.
- Timeline. Mean and worst p95 frame time across tabs, mean draw calls, incidents per bucket, build boundaries and fix markers. Filter by phase, build and GPU regime.
- Sessions. One row per player tab, worst first. Open one for its frame-time trace and its incidents in order.
- Fixes. Each fix with what your machine measured beside what players saw: occurrences per tab-hour in the 24 hours before and after.
Every view takes a range. Automated tabs, such as test probes, are hidden unless you ask for them.
API
Base URL https://sloptimizejs.com/v1. Requests and responses are JSON. Project routes take a secret key, or an access token with ?project=<slug>. Ranges are preset=24h|7d|30d|90d or from and to as ISO timestamps.
POST /v1/ingest
Sends a batch of up to 200 records. Publishable or secret key. Heartbeats are folded into the timeline and never count against a quota. Every other record is an incident. Records are dropped one at a time with a reason, never the whole batch. Returns 429 with Retry-After when the monthly quota, the daily cap or the rate limit is reached.
curl -s https://sloptimizejs.com/v1/ingest -H "Authorization: Bearer pk_live_…" -H "Content-Type: application/json" \
-d '{"records":[{"type":"hitch","at":"2026-09-02T12:00:00Z","frameMs":120}]}'
GET /v1/issues
The footprints seen in the range, with counts. Filter with source=client|server or kind. Ranges over 7 days are day-granular.
curl -s "https://sloptimizejs.com/v1/issues?preset=7d" -H "Authorization: Bearer sk_live_…"
GET /v1/footprints/:id
One footprint over the range: counts, its occurrence series, the worst record, sibling situations and linked fixes.
curl -s "https://sloptimizejs.com/v1/footprints/abc123?preset=7d" -H "Authorization: Bearer sk_live_…"
GET /v1/timeline
The timeline as JSON: buckets with beats, p95 mean and max, median mean, draw calls and incidents by kind, plus the builds seen in the range. Query phase, build, regime=hardware|software|all, automated=1.
curl -s "https://sloptimizejs.com/v1/timeline?preset=24h" -H "Authorization: Bearer sk_live_…"
GET /v1/sessions, GET /v1/sessions/:id
Sessions last seen in the range, worst first, at most 100. One session returns its last 60 beats and its records in order. Query build, automated=1.
curl -s "https://sloptimizejs.com/v1/sessions?preset=24h" -H "Authorization: Bearer sk_live_…"
GET /v1/fixes, POST /v1/fixes
The project's fixes, newest first. POST records or updates one, linked to footprint ids. A fix without an id gets a stable one from its title, commit, time and footprints, so pushing the same fix twice updates one row.
curl -s -X POST "https://sloptimizejs.com/v1/fixes" -H "Authorization: Bearer sk_live_…" -H "Content-Type: application/json" \
-d '{"title":"debounce warm-up","footprints":["abc123"]}'
GET /v1/me
Access token only. The token's owner: id, login and plan.
curl -s https://sloptimizejs.com/v1/me -H "Authorization: Bearer at_live_…"
GET /v1/projects, POST /v1/projects
Access token only. Lists your projects, or creates one from a name. The response carries the slug the other routes take. 403 when the plan's project limit is reached.
curl -s -X POST https://sloptimizejs.com/v1/projects -H "Authorization: Bearer at_live_…" -H "Content-Type: application/json" -d '{"name":"My Game"}'
GET /v1/projects/:slug/keys, POST /v1/projects/:slug/keys, DELETE /v1/projects/:slug/keys/:id
Access token only. Lists, mints or revokes a project's keys. POST takes kind of publishable or secret and an optional label. Its response is the only place a secret key appears in full.
curl -s -X POST https://sloptimizejs.com/v1/projects/my-game/keys -H "Authorization: Bearer at_live_…" -H "Content-Type: application/json" -d '{"kind":"secret","label":"server"}'
curl -s "https://sloptimizejs.com/v1/issues?project=my-game&preset=7d" -H "Authorization: Bearer at_live_…"
GET /healthz
No auth. { "ok": true } when the database answers.
CLI and MCP
The sloptimize CLI and its MCP server read the catalogue with a project's secret key.
SLOPTIMIZE_KEY=sk_live_… SLOPTIMIZE_ENDPOINT=https://sloptimizejs.com npx sloptimize issues --cloud --preset 7d SLOPTIMIZE_KEY=sk_live_… SLOPTIMIZE_ENDPOINT=https://sloptimizejs.com npx sloptimize fix --push --footprints abc123 --title "debounce warm-up"
For an agent that should set a project up from nothing, give it an access token instead. It can create the project, mint the keys and read the catalogue with the routes above.