API reference
API overview and auth
Everything the UI does goes through this HTTP API. It serves JSON over the app's URL, the one Get started opens, which cascade deploy prints as app:.
Every response on these pages was captured from a running server, by landing/docs-src/capture_examples.py. The sims in that run replayed a recorded Accel-Sim log of BabelStream on an RTX 3070, so the cycles, IPC and kernel names come from that log, not from the uploaded trace. That's also why a finished sim shows kernels_done 6 against kernels_total 4: the log has six kernels and the uploaded trace has four. Long lists and maps are trimmed, and each cut is marked with a /* ... trimmed */ comment.
Base URL#
The samples read the app's URL and your token from the environment.
export CASCADE_URL=https://<your-app>
export CASCADE_TOKEN=<your token>Locally, the app's URL is http://127.0.0.1:8000.
Authentication#
Send the token the app was started with as a bearer token on every request.
curl -H "Authorization: Bearer $CASCADE_TOKEN" "$CASCADE_URL/api/traces"A missing or wrong token gets 401 with a WWW-Authenticate: Bearer header. Two routes differ.
- Check health needs no token.
- Stream run events also accepts the token as
?token=, because the browser'sEventSourcecan't send headers.
There is one token per app, shared by the UI, the profiler and every sim. The app compares it in constant time.
Conventions#
- Request and response bodies are JSON. Every type is generated from
cascade/models.py. - Timestamps are ISO 8601 in UTC, such as
2026-11-08T03:05:34.001386Z. - A trace's id is the profiler's run name. Runs and sims get generated ids,
run-orsim-and 12 hex digits. - Lists come back whole. There is no pagination.
- Errors are JSON with a
detailfield. See Errors.
Routes#
| method | path | what it does |
|---|---|---|
| GET | /api/health | Liveness check. Needs no token. |
| GET | /api/traces | Every trace, newest first. |
| GET | /api/traces/{trace_id} | One trace with its metadata and kernels. |
| GET | /api/gpu-configs | The GPU configs a run can use. |
| POST | /api/runs | Launch sims for a ready trace. |
| GET | /api/runs | Every run, newest first. |
| GET | /api/runs/{run_id} | One run with its trace and every sim. |
| POST | /api/runs/{run_id}/cancel | Cancel every unfinished sim. |
| GET | /api/runs/{run_id}/comparison | Per-kernel real time against simulated time per config. |
| GET | /api/runs/{run_id}/kernels | Every sim's per-kernel stats, without the full stats maps. |
| GET | /api/runs/{run_id}/step-timelines | Each sim's predicted step timeline and its comparison with the real run. |
| GET | /api/runs/{run_id}/results | One JSON file with the run, trace, every sim's stats and the comparison. |
| GET | /api/sims/{sim_id}/results | One sim's config, per-kernel stats and totals. |
| GET | /api/sims/{sim_id}/log | The sim's full raw output. |
| GET | /api/runs/{run_id}/files | Every output file the run's sims uploaded. |
| GET | /api/runs/{run_id}/perfetto | The run's simulated kernels as a Chrome trace JSON for ui.perfetto.dev. |
| GET | /api/sims/{sim_id}/files | The output files one sim uploaded. |
| GET | /api/sims/{sim_id}/files/{name} | One output file, as the sim uploaded it. |
| GET | /api/runs/{run_id}/events | Server-sent events for one run. |
| POST | /api/sims/{sim_id}/heartbeat | Report a sim's state. The reply says whether to stop. |
| POST | /api/sims/{sim_id}/logs | Append a chunk of simulator output. |
| POST | /api/sims/{sim_id}/step-timeline | Store a sim's predicted step timeline and its comparison. |
| PUT | /api/sims/{sim_id}/files/{name} | Store one of the simulator's output files. |
Any other path under /api/ returns 404 with {"detail": "Not Found"}, without checking the token. Paths outside /api/ serve the web UI.
Check health#
Returns {"ok": true, "auth": true, "workspace": ...} while the app process is serving requests. auth is false only when the app runs with CASCADE_NO_AUTH=1, a local-dev mode where no token is needed and the web UI skips its token screen. workspace is CASCADE_WORKSPACE, the name the web UI shows in its rail, or null. Health does not check the database, the S3 endpoint or the launcher.
Returns#
200 with {"ok": true, "auth": true, "workspace": "<name or null>"}.
Example#
curl "$CASCADE_URL/api/health"import os
import httpx
resp = httpx.get(f"{os.environ['CASCADE_URL']}/api/health")
resp.raise_for_status()
print(resp.json())const resp = await fetch(`${CASCADE_URL}/api/health`);
console.log(await resp.json());{
"ok": true,
"auth": true,
"workspace": "acme-lab",
"s3_endpoint": "http://127.0.0.1:9020"
}