Public API
SnapBench exposes a stable, versioned REST API at /api/v1 so external scripts and integrations can launch scenario runs and retrieve their public interfaces.
Common use cases:
- Automated training sessions (launch N runs at once from a script)
- CI pipelines that need isolated environments
- Custom dashboards that monitor active runs
- Integrations with external tools (Kafka clients, data pipelines, etc.)
OpenAPI Specification
The full machine-readable spec is served at /api/v1/openapi.yaml and can be imported into Swagger UI, Postman, or any OpenAPI-compatible codegen tool.
Authentication
Every endpoint requires authentication. Two methods are supported:
API Keys (recommended for scripts)
Personal API keys are created from your Account Settings page.
| Property | Details |
|---|---|
| Format | sb_live_ followed by 43 base64url characters |
| Scope | Tied to your user identity; inherits your organization's quotas and permissions |
| Storage | Only a SHA-256 hash is stored; the plaintext key is shown once at creation |
| Lifecycle | Can be named, expire, or be revoked at any time |
Pass the key in the Authorization header:
Authorization: Bearer sb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxSave Your Key
API keys are shown only once when created. Copy and store them in a secure location (password manager, secret store, CI variables). If lost, revoke the key and create a new one.
JWT Session Cookie (fallback)
If you are already logged in to the SnapBench app in your browser, the session cookie is accepted as a fallback auth method. This is useful for quick manual tests from the browser console but not recommended for scripts.
Managing API Keys
- Open your Account Settings page
- Go to the API Keys section
- Click Create API Key
- Give it a descriptive name (e.g.,
kafka-training-runner,ci-pipeline) - Optionally set an expiration date
- Copy the key immediately - it will not be shown again
- Revoke keys you no longer need
Endpoints
All endpoints are under /api/v1.
Launch Runs
POST /api/v1/scenarios/{id}/runsCreates and provisions count independent runs of a scenario. Each run lives in its own isolated namespace.
Path parameters:
| Name | Description |
|---|---|
id | Scenario ID (UUID) |
Request body:
| Field | Type | Description |
|---|---|---|
count | integer | Number of runs to launch (default 1, subject to platform and per-org limits) |
ttlMinutes | integer | Optional TTL override. Falls back to scenario TTL, then org default, then 60 |
Example:
curl -X POST https://app.snapbench.io/api/v1/scenarios/$SCENARIO_ID/runs \
-H "Authorization: Bearer $SB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"count": 3, "ttlMinutes": 120}'Responses:
| Status | Meaning |
|---|---|
201 Created | All runs were created; provisioning runs asynchronously |
207 Multi-Status | Partial success; some runs were created before an error occurred |
400 Bad Request | Invalid scenario ID or count exceeds the per-request limit |
404 Not Found | Scenario not found or has no published version |
429 Too Many Requests | Platform concurrent-run cap would be exceeded |
Response body:
{
"runs": [
{
"id": "uuid",
"scenarioId": "uuid",
"status": "PROVISIONING",
"namespace": "snapbench-run-xxxxx",
"createdAt": "2026-04-16T12:00:00Z",
"startedAt": "2026-04-16T12:00:00Z",
"expiresAt": "2026-04-16T14:00:00Z",
"provisionedAt": null,
"endedAt": null
}
]
}List Runs
GET /api/v1/runsReturns up to 100 of the caller's most recent runs, newest first.
Query parameters:
| Name | Description |
|---|---|
status | Filter by status: PENDING, PROVISIONING, RUNNING, ENDING, ENDED, FAILED |
scenarioId | Filter to runs of a single scenario (UUID) |
Example:
curl https://app.snapbench.io/api/v1/runs?status=RUNNING \
-H "Authorization: Bearer $SB_API_KEY"Get a Run
GET /api/v1/runs/{id}Returns a single run's current status.
Responses:
| Status | Meaning |
|---|---|
200 OK | Returns the run object |
403 Forbidden | You do not own this run |
404 Not Found | Run does not exist |
List Run Interfaces
GET /api/v1/runs/{id}/interfacesReturns every externally reachable interface exposed by a run.
| Type | Description |
|---|---|
tcp | Raw host:port pairs reachable from the public internet, one per published public TCP port |
web | Full HTTPS URLs for ingress-backed services (dashboards, consoles, etc.) |
Example:
curl https://app.snapbench.io/api/v1/runs/$RUN_ID/interfaces \
-H "Authorization: Bearer $SB_API_KEY"Response body:
{
"interfaces": [
{
"type": "tcp",
"component": "kafka",
"name": "external",
"protocol": "tcp",
"host": "tcp.snapbench.io",
"port": 30001
},
{
"type": "web",
"component": "grafana",
"name": "http",
"url": "https://grafana-abc123.snapbench.io"
}
]
}Web UIs May Lag
The web interfaces list is built from a cache refreshed every few seconds. Right after provisioning, it may briefly lag behind the TCP list. Poll /interfaces until the expected URLs appear.
Run Status Values
| Status | Meaning |
|---|---|
PENDING | Run created, not yet picked up by the orchestrator |
PROVISIONING | Namespace created, components being deployed |
RUNNING | All components ready, run is live |
ENDING | Cleanup in progress |
ENDED | Run terminated cleanly; all resources deleted |
FAILED | Provisioning or runtime error |
Quotas & Limits
API usage is subject to the same quotas as the SnapBench UI, plus a few API-specific caps:
| Limit | Scope | Configurable by |
|---|---|---|
Max runs per POST /scenarios/{id}/runs request | Per request | Platform default (apiMaxRunsPerRequest), overridable per-org |
| Max concurrent runs cluster-wide | Platform | Platform admin (maxConcurrentRuns) |
| Organization quotas (CPU, memory, credits) | Per org | Org admin / platform admin |
If a request exceeds the concurrent-run cap, the API returns 429 Too Many Requests. Retry after some runs end.
End-to-End Example
A typical script that launches a run and prints its public Kafka endpoint:
#!/bin/bash
set -e
SB_API_KEY="sb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
SCENARIO_ID="your-scenario-uuid"
BASE_URL="https://app.snapbench.io/api/v1"
# 1. Launch a run
RUN=$(curl -sS -X POST "$BASE_URL/scenarios/$SCENARIO_ID/runs" \
-H "Authorization: Bearer $SB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"count": 1, "ttlMinutes": 60}')
RUN_ID=$(echo "$RUN" | jq -r '.runs[0].id')
echo "Launched run: $RUN_ID"
# 2. Wait until it's RUNNING
while true; do
STATUS=$(curl -sS "$BASE_URL/runs/$RUN_ID" \
-H "Authorization: Bearer $SB_API_KEY" | jq -r '.status')
echo "Status: $STATUS"
[ "$STATUS" = "RUNNING" ] && break
[ "$STATUS" = "FAILED" ] && { echo "Run failed"; exit 1; }
sleep 5
done
# 3. Fetch public interfaces
curl -sS "$BASE_URL/runs/$RUN_ID/interfaces" \
-H "Authorization: Bearer $SB_API_KEY" | jqFinding IDs
- Scenario ID: Visible in the Studio header next to the scenario name, and via the Copy Scenario ID action in the Scenarios Library.
- Run ID: Returned in the response of
POST /scenarios/{id}/runs, or listed byGET /runs.
