REST API Reference¶
This page documents the notebook REST surface, mounted under /v1/notebooks. Strata Core also exposes a POST /v1/materialize endpoint for direct artifact materialization; see the Library Quickstart for that surface.
The remote-worker contract — /v1/execute, /v1/notebook-execute, /v1/execute-manifest, /health — is documented separately on the Executor Protocol page. Those endpoints live on a different process (strata-worker), not the main server.
Session ID vs Notebook ID
Route parameters use the session ID (a UUID generated when the notebook is opened), not the persistent notebook_id from notebook.toml. The session ID is returned by the open and create endpoints.
Conventions¶
Canonical machine-readable spec¶
The server exposes a live OpenAPI document at runtime:
| Path | What it serves |
|---|---|
GET /openapi.json |
Full OpenAPI 3.1 schema — request and response models for every endpoint, generated from the FastAPI route definitions. |
GET /docs |
Swagger UI for interactive try-it-out. |
GET /redoc |
ReDoc browser for the same schema. |
When this page and the live spec disagree, the live spec wins — it's generated from the source of truth. This page exists for orientation and walks through the high-traffic flows.
Authentication¶
Authentication depends on deployment_mode:
| Mode | Default auth | Required headers |
|---|---|---|
personal |
None (single user) | None |
personal + STRATA_PERSONAL_MODE_USER_HEADER |
Caller identity from the named header (set by an authenticating proxy) | The header you configured (e.g. X-Authenticated-User) |
service + auth_mode="trusted_proxy" |
Proxy-injected identity | X-Strata-Principal, X-Strata-Scopes, X-Strata-Proxy-Token; X-Tenant-ID if multi-tenant |
In service mode, every /v1/* endpoint requires X-Strata-Principal (the proxy-asserted user identity) and the X-Strata-Proxy-Token shared secret. Two further restrictions narrow what each endpoint accepts:
Personal-mode-only endpoints. These notebook-session-lifecycle operations return 400 Bad Request outside personal mode (long-lived sessions and filesystem notebook management don't fit a multi-tenant service deployment). Artifact and registry writes, by contrast, are available in service mode when service_writes_enabled is on, with the artifacts:write scope — see Service Mode.
| Endpoint | Why personal-mode-only |
|---|---|
DELETE /v1/notebooks/{session_id} |
Filesystem delete of a notebook directory |
POST /v1/notebooks/delete-by-path |
Same, addressed by path |
GET /v1/notebooks/discover |
Walks the storage root for any notebook |
Notebook session lifecycle (/open, /create, session reconnect) |
Long-lived sessions land on one server process; service-mode multi-tenant deploys use the artifact API instead |
Scope-gated endpoints. These require a scope token in X-Strata-Scopes beyond authenticated principal:
| Endpoint | Required scope |
|---|---|
POST /v1/cache/clear |
admin:cache |
All other endpoints documented below need only X-Strata-Principal + X-Strata-Proxy-Token in service mode, and no auth in personal mode. Endpoints below carry a Personal mode only callout where applicable; otherwise treat them as available in both modes.
Personal mode with no header configured is effectively trust-on-first-call — anyone reaching the server can use it. Deploying personal mode to a public URL without an auth proxy is a trust-model decision; see Fly.io deployment for the load-bearing details.
Error shape¶
All 4xx and 5xx responses use FastAPI's standard JSON shape:
Validation errors (422) come from Pydantic and contain structured field info:
{
"detail": [
{
"loc": ["body", "python_version"],
"msg": "String should have at most 16 characters",
"type": "string_too_long"
}
]
}
Status codes you'll see¶
| Status | Common cause |
|---|---|
200 |
Success |
204 |
Success, no body (e.g. DELETE operations) |
400 |
Malformed request (invalid path, bad enum value, ACL block) |
401 |
Service mode auth header missing or proxy-token mismatch |
403 |
Authenticated, but missing the required scope (e.g. admin:cache) — returned as 404 if STRATA_HIDE_FORBIDDEN_AS_NOT_FOUND=true (the default) |
404 |
Notebook session not found, or hidden 403 (see above) |
409 |
Conflict — concurrent environment job, conflicting cell edit, or attempt to use a destructive endpoint outside personal mode |
413 |
Request body or scan response exceeded the configured byte cap |
422 |
Pydantic validation error on the request body |
429 |
Rate limit exceeded — global, per-client, or per-tenant |
500 |
Server bug — captured to logs with the request ID |
Request IDs¶
Every request gets an X-Request-ID response header (and the same value is echoed if the client sent one in). Log lines and traces include this ID — copy it when filing bugs.
Tenancy¶
In multi-tenant deployments, the X-Tenant-ID header (1–64 alphanumeric, _, -) scopes every endpoint to that tenant's namespace. The tenant ID is hashed into cache keys, artifact paths, and QoS limiter pools. ACL evaluation is deny-first: explicit denies cannot be overridden by allows. See Service Mode for the full contract.
Notebook Lifecycle¶
Create Notebook¶
{
"parent_path": "/path/to/directory",
"name": "My Notebook",
"python_version": "3.13",
"starter_cell": true
}
Returns notebook state with session_id.
Open Notebook¶
Returns notebook state with session_id and dag.
Import Jupyter Notebook¶
Form fields:
| Field | Type | Description |
|---|---|---|
file |
file (required) | The .ipynb upload. Hard cap of 50 MB. |
name |
string | Override the notebook name (defaults to the upload's filename stem). |
parent_path |
string | Override the storage location (must lie inside the configured storage root). |
Converts the upload through strata import and opens a session on
the result. Returns the same notebook state shape as POST
/v1/notebooks/create plus an import_report field with the
converter's per-cell findings (translated magics, captured deps,
warnings, full report markdown). See
Import from Jupyter for the magic
translation table and limitations.
Delete Notebook¶
Deletes the notebook directory and closes the session.
Discover Notebooks¶
Lists notebook directories under the configured storage root. Returns
{ "root", "notebooks": [{ "path", "name", "notebook_id", "updated_at" }] }
sorted newest-first. Used by the "Open existing" UI so users pick from a list
instead of typing a filesystem path. Personal mode only.
Delete Notebook By Path¶
Deletes a notebook directory by filesystem path. This is primarily a personal-mode management endpoint.
Rename Notebook¶
Sessions¶
List Sessions¶
Returns { "sessions": [{ "session_id", "name", "path", ... }] }.
Get Session¶
Returns full notebook state (same shape as open). Used for page refresh reconnection.
Cells¶
List Cells¶
Add Cell¶
language may be python, prompt, markdown, or sql. Defaults to python.
Update Cell Source¶
Returns updated cell, DAG, and all cells (with refreshed staleness).
Delete Cell¶
Reorder Cells¶
Execute Cell (REST)¶
The optional mode query parameter selects the run mode: normal (default —
use the cache and materialize stale upstreams), rerun (bypass the target
cell's cache, still materialize upstreams), or force (run against whatever
upstream artifacts already exist). An unrecognized mode returns 400.
Tip
For interactive use, prefer the WebSocket cell_execute message. The REST endpoint is for programmatic access.
Run Cell Tests (REST)¶
Runs the committed cells/{cell_id}.test.py via pytest against a re-executed
copy of the cell and returns per-test outcomes: { "cell_id", "passed",
"failed", "errored", "skipped", "pytest_unavailable", "ran_at", "tests": [{
"name", "nodeid", "outcome", "message" }] }. Python cells only — a non-Python
cell or one with no test source returns 400. The REST twin of the WebSocket
cell_run_tests message, for clients (the CLI, agents) that don't drive a
socket.
List Loop Cell Iterations¶
Lists stored iteration artifacts for a @loop cell. The variable query
parameter defaults to the loop's carry variable if omitted. Non-loop cells
and loops with no completed iterations return an empty list, safe to poll
from the inspect panel.
Returns { "cell_id", "variable", "iterations": [{ "iteration", "artifact_uri",
"artifact_id", "version", "content_type", "byte_size", "row_count",
"created_at" }] }.
DAG¶
Get DAG¶
Returns edges, roots, leaves, and topological order.
Environment¶
List Dependencies¶
Add Dependency¶
Remove Dependency¶
Get Environment State¶
Sync Environment¶
Runs uv sync synchronously and invalidates any stale cell runtimes. Returns
the full environment payload plus lockfile_changed, operation_log
(command, duration, stdout/stderr), and the per-cell staleness map.
For long syncs prefer the background POST /environment/jobs path, this
endpoint blocks the request until the sync finishes.
Get Current Environment Job¶
Start Environment Job¶
Actions: add, remove, sync, import.
For import, send exactly one of requirements or environment_yaml.
Export Requirements¶
Import Requirements¶
Preview Requirements Import¶
Import environment.yaml¶
Preview environment.yaml Import¶
Workers¶
List Workers¶
Update Notebook Worker¶
Update Worker Catalog¶
Mounts¶
Update Notebook Mounts¶
Connections¶
List Notebook Connections¶
Returns:
Replace Notebook Connections¶
The list is canonical: sending an empty list deletes the entire [connections]
block. Literal auth values are blanked on disk during the write round-trip, but
kept in-memory until the session reloads.
Returns:
Enumerate Connection Schema¶
Enumerates the tables and columns visible through the named connection. Used by
the schema sidebar. Opens the connection on the read path and returns backend
errors directly as 4xx so auth / driver / connectivity failures are visible
to the UI.
Export¶
Export Notebook¶
One endpoint, three output formats:
fmt |
Returns |
|---|---|
zip (default) |
Reproducible bundle, notebook.toml, pyproject.toml, uv.lock, cells, provenance.json. |
markdown |
Single-file rendering for sharing / docs ingestion. Same engine as strata export. |
html |
Standalone HTML with embedded CSS + Pygments syntax highlighting. |
Markdown and HTML renderings additionally accept include_inactive_variants=true to stack all variants of every group. Prompt-cell responses are intentionally excluded from rendered formats (see Export).
AI¶
Get AI Status¶
List Provider Models¶
Update Notebook AI Model¶
Chat Completion¶
Streaming Chat¶
Server-Sent Events stream with delta, done, and error events.
Agent Run¶
Reset Agent Session¶
Clears the assistant's in-memory conversation / tool session for that notebook.
Runtime¶
Get Server Runtime Config¶
Returns deployment mode, available Python versions, and default paths for the server as a whole. Not notebook-scoped.
Update Notebook Default Timeout¶
timeout is seconds (0 < t ≤ 86400) or null to clear back to the system
default. Returns the new timeout and the refreshed cell list.
Update Notebook Default Env¶
Replaces the [env] block in notebook.toml. Sensitive values (keys matching
KEY/SECRET/TOKEN/PASSWORD/CREDENTIAL) are blanked on disk but kept
in-memory for the session so key-dependent cells keep working. Returns the
merged env, per-key sources, and refreshed cell list.
Update Secret Manager Config¶
{
"provider": "infisical",
"project_id": "your-project-id",
"environment": "dev",
"path": "/",
"base_url": null
}
Persists the [secret_manager] block to notebook.toml and immediately
refetches. An empty payload (all fields null) removes the block:
"disconnect from secret manager". Credentials are never part of this payload;
they must be exported in the server's shell environment.
Refresh Secret Manager¶
Re-fetches secrets from the configured manager and merges them into env.
Never returns 500 on fetch failure, the error surfaces in
env_fetch_error so the UI can display it next to the Refresh button.
Core API¶
Materialize¶
{
"inputs": ["file:///warehouse#db.events"],
"transform": {
"executor": "scan@v1",
"params": { "columns": ["id", "value"] }
},
"mode": "stream",
"name": "my_result"
}
Get Stream¶
Returns Arrow IPC stream.