darkpyonix guide

Manager HTTP API

The manager HTTP API

Editors, Ember, ash and the CLI all use the same API. The contract is docs/api/manager.openapi.yaml; a test checks that the manager serves exactly those paths.

Two modes

ModeListens onLifetimeTokens
ephemeral (default)127.0.0.1, random portexits after --idle-timeout seconds without requests or streams (120 by default)one token, written to managers/<pid>.json (0600)
dedicated (--dedicated)the host and port you setruns until stoppeda master token and share tokens, stored hashed in manager.db

Outside access always goes through a dedicated manager. Kernels listen on loopback only.

Authentication

Every request carries Authorization: Bearer <token>. Only the event stream and share links also accept ?token=, because a browser EventSource cannot set headers. GET /health needs no token.

Share tokens are bound to one kernel. A token for another kernel answers 404, not 403, so it does not reveal which kernels exist.

Paths

PathWhat
GET /healthLiveness. The only path without a token.
GET /api/managerMode, version, uptime and the caller's permission.
GET /api/kernels, POST /api/kernelsList running kernels; start or attach to the kernel for a path (200 if running, 201 if started).
GET, DELETE /api/kernels/{kernel_id}Status; shut down. ?force=true is the only way to kill.
POST /api/kernels/{kernel_id}/interruptInterrupt the running cell.
POST /api/kernels/{kernel_id}/restartSoft or hard restart.
GET /api/kernels/{kernel_id}/namespaceUser variables.
GET, POST /api/kernels/{kernel_id}/runsList run logs; start a run (mode, cells or cell_ids, params, source, on_busy).
GET, DELETE /api/kernels/{kernel_id}/runs/{run_ref}One run log (latest or an id); cancel a queued run.
GET /api/kernels/{kernel_id}/runs/{run_ref}/waitLong poll until the run ends, for clients that cannot hold a stream.
GET /api/kernels/{kernel_id}/eventsServer-Sent Events. Resume with Last-Event-ID or ?since=.
GET /api/kernels/{kernel_id}/document, GET /api/documentsThe file's cells with the latest outputs mapped on; parse any file without a kernel.
/api/kernels/{kernel_id}/cells…, …/presenceCollaborative editing: create, edit, move, lock cells; focus and cursor.
/api/kernels/{kernel_id}/shares…Share tokens (dedicated manager).

Outputs use the nbformat 4 output schema as is, so anything that reads Jupyter outputs reads these. A running manager also serves the rendered API reference at /docs/.

An example

shell
# Start (or attach to) the kernel for a file. 200 if it was running, 201 if started.
curl -s -X POST "$URL/api/kernels" -H "Authorization: Bearer $TOKEN" \
     -H 'Content-Type: application/json' -d '{"path": "/home/me/experiments/train.py"}'

# Run cells 1 and 3, queue behind a running run instead of failing with 409.
curl -s -X POST "$URL/api/kernels/$KID/runs" -H "Authorization: Bearer $TOKEN" \
     -H 'Content-Type: application/json' \
     -d '{"mode": "cells", "cells": [1, 3], "params": {"lr": 0.02}, "on_busy": "queue"}'

# Follow events. EventSource cannot set headers, so SSE also accepts ?token=.
curl -N "$URL/api/kernels/$KID/events?token=$TOKEN"

# Stop means interrupt.
curl -s -X POST "$URL/api/kernels/$KID/interrupt" -H "Authorization: Bearer $TOKEN"

A second run while the kernel is busy answers 409 with the current run, unless the request sets "on_busy": "queue".

Events

GET /api/kernels/{kernel_id}/events is a Server-Sent Events stream: run started and finished, cell started and finished, outputs, and document changes. The SSE id is the kernel's event sequence number. A client that reconnects with Last-Event-ID gets what it missed while the kernel's replay buffer still has it.

No versions

Paths have no version segment (INTENT D16). The API only grows: fields, optional request fields, paths and error codes are added, never renamed or removed. A replaced field stays, marked deprecated. Clients ignore fields they do not know.

What is changing

Changing

Long-lived streams (events, the run-wait long poll) will be handed by the manager to the kernel as a socket, so they keep flowing when the manager exits changing #47. The 2025 authentication is being restored: one password and one master token per manager under /api/auth, and access tokens that the kernel itself holds, so they work through any manager changing #48. Permissions become a set of five capabilities (read, history, execute, edit, manage) instead of viewer tiers, and collaboration moves to the 2025 WebSocket sync changing #49. Managers and kernels will admit only the same OS account changing #55. Short REST calls such as runs and interrupt keep their shape.