APIs

Studio recipes

These assume SIRIUS=http://localhost:8080 and a $TOK bearer on a secured deployment. Add -H "Authorization: Bearer $TOK" to each call. Concepts live on the Studio API page.

Create, file, sample, run

WS=$(curl -s -X POST "$SIRIUS/studio/workspaces" \
  -H 'content-type: application/json' \
  -d '{
    "tenant_id":"default",
    "name":"Normalize order",
    "runtime_pack":"javascript",
    "tags":["orders"]
  }' | jq -r .id)

curl -s -X PUT "$SIRIUS/studio/workspaces/$WS/files" \
  -H 'content-type: application/json' -d '{
    "tenant_id":"default",
    "path":"main.js",
    "entrypoint":true,
    "content":"const body = sirius.json.decode(msg.raw);\nbody.site = sirius.table.lookup(\"sites\", body.site_id, \"UNKNOWN\");\nresult = { message: body };"
  }'

curl -s -X POST "$SIRIUS/studio/workspaces/$WS/samples/import" \
  -H 'content-type: application/json' -d '{
    "tenant_id":"default",
    "name":"order-001",
    "content":"{\"id\":\"A-1\",\"site_id\":\"west\"}",
    "make_active":true
  }'

curl -s -X POST "$SIRIUS/studio/workspaces/$WS/run" \
  -H 'content-type: application/json' \
  -d '{"tenant_id":"default"}' | jq '{status, output, annotations}'

A missing result assignment fails with mapping script produced no result.

Capture a golden and run the suite

# Approve the current output as the expectation for the active sample
curl -s -X POST "$SIRIUS/studio/workspaces/$WS/samples/<sample-id>/capture-expectation" \
  -d '{"tenant_id":"default"}'

curl -s -X POST "$SIRIUS/studio/workspaces/$WS/test" \
  -d '{"tenant_id":"default"}' | jq '{total, passed, failed, errored}'

curl -s "$SIRIUS/studio/workspaces/$WS/coverage"

Comparison is JSON-normalized. 2 matches 2.0. The same goldens work after you change language packs.

Promote a milestone

curl -s -X POST "$SIRIUS/studio/workspaces/$WS/milestones" \
  -H 'content-type: application/json' -d '{
    "tenant_id":"default",
    "label":"v1.0",
    "note":"first release",
    "require_tests_pass":true,
    "capture_baseline":true
  }'

A red suite returns HTTP 422 and the failing report. Restore later with POST …/milestones/{id}/restore.

Switch language pack

curl -s -X POST "$SIRIUS/studio/workspaces/$WS/runtime-pack" \
  -H 'content-type: application/json' \
  -d '{"tenant_id":"default","runtime_pack":"python"}'

sirius.* does not change. Rewrite the entrypoint in the new syntax, then re-run the suite.

SQL against a connector

curl -s "$SIRIUS/studio/sql/connectors"

curl -s -X POST "$SIRIUS/studio/sql/query" \
  -H 'content-type: application/json' -d '{
    "tenant_id":"default",
    "connector_id":"warehouse",
    "sql":"select id, name from sites where region = ?",
    "params":["west"],
    "limit":50
  }'

Never a raw DSN. Writes commit. Four in-flight queries per tenant; extras are 429 too_many_queries with Retry-After: 1 and the statement does not run.

Export and import a workspace

curl -s "$SIRIUS/studio/workspaces/$WS/export" -o normalize.studio.json
curl -s -X POST "$SIRIUS/studio/workspaces/import" --data-binary @normalize.studio.json

Bundles are signed. They carry files, samples, and expectations — not host secrets.

Python

import requests

SIRIUS = "http://localhost:8080"
s = requests.Session()
s.headers.update({"Authorization": f"Bearer {token}"})

ws = s.post(f"{SIRIUS}/studio/workspaces", json={
    "tenant_id": "default",
    "name": "Normalize order",
}).json()

s.put(f"{SIRIUS}/studio/workspaces/{ws['id']}/files", json={
    "tenant_id": "default",
    "path": "main.js",
    "entrypoint": True,
    "content": "result = { message: sirius.json.decode(msg.raw) };",
})

run = s.post(
    f"{SIRIUS}/studio/workspaces/{ws['id']}/run",
    json={"tenant_id": "default"},
).json()
print(run["status"], run.get("output"))

Run is a write (studio:write). A viewer token can list the workspace and still receive 403 on /run.