sloptimize cloud

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

  1. Install the package.
    npm install sloptimize
  2. 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.
  3. 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());
  4. 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());
  5. 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 key
pk_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 key
sk_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 token
at_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

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.