Workloads API
Submit requirements. Nodus matches a nodus:…
catalog route, runs to verified completion, and recovers when capacity is
reclaimed. You never pick a supplier.
# Playground
Describe the work and its constraints, not a machine SKU. Watch Nodus match a catalog route, run with checkpoints, and recover from a reclaim. No API key required.
- workload
- -
- catalog sku
- -
- fit
- -
- est. cost
- -
- status
- -
- generation
- -
- spend_usd
- -
# Install
From the monorepo (published PyPI later). Runtime dependency:
httpx.
$ pip install -e sdk/python # or: pip install nodus-sdk (when published)
# Authentication
Every request carries Authorization: Bearer <api_key>.
Sign in to the console with your email and password,
then issue a key under Access. Keys are stored as a SHA-256 hash and shown
once at creation, so copy it then. Revocation is checked on every request,
so cutting off a leaked key takes effect on the next call, and revoking a key
never signs you out of the console.
| Variable | Default | Notes |
|---|---|---|
NODUS_API_KEY |
— | Required. Issued from the console as nk_live_… or nk_test_…. |
NODUS_BASE_URL |
https://api.nodus.run |
Override for staging or a control plane you run yourself. |
Nothing here is bound to a host. Set
NODUS_BASE_URL or pass
nodus.Client(base_url=…); the contract is
the same.
# Quick start
Describe the work and constraints. Hardware fit, placement, and recovery stay with Nodus.
# export NODUS_API_KEY=nk_live_… >>> import nodus >>> >>> with nodus.Client() as client: ... wl = client.run( ... command=["train"], ... model="7B fine-tune", ... peak_memory_gb=24, ... expected_runtime_hours=1, ... budget=100, ... ) ... done = client.wait(wl.id) ... print(done.status, done.spend_usd) WorkloadStatus.COMPLETED 0.02
# HTTP surface
The SDK is a thin client over this surface. Everything is tenant-scoped, so another tenant’s workload id reads as absent rather than forbidden. Submission rules are in retries & idempotency.
| Endpoint | Contract |
|---|---|
POST /v1/workloads | Submit a brief. Requires Idempotency-Key. Returns 202 with the workload id and revision; a replay repeats the original response and sets Idempotent-Replayed: true. |
GET /v1/workloads | List for the authenticated tenant. limit (default 50, max 100), offset, and status — the presets active or terminal, or a comma-separated list of concrete statuses. The response carries next_offset when more rows remain. |
GET /v1/workloads/{id} | Status, customer route (nodus:…), spend, and per-stage progress |
GET /v1/workloads/{id}/events | Ordered lifecycle events. Pass after to read only what is new; up to 100 per call. |
GET /v1/workloads/{id}/ledger | Customer-safe ledger evidence + settlement |
POST /v1/workloads/{id}/cancel | Safe stop |
GET /v1/workloads/{id}/artifacts | Verified checkpoint / output manifests |
PUT /v1/webhooks | Register signed customer webhook endpoint (https, public hosts only) |
GET /v1/webhooks | Read webhook config (secret omitted) |
DELETE /v1/webhooks | Remove webhook |
POST /v1/console/signup | Redeem an invite → tenant, console account, first API key, and a session. Tenant id is assigned, never chosen. |
POST /v1/console/login | Email and password → session token. One answer for every failure, so the form cannot be used to enumerate accounts. |
POST /v1/console/logout | Revoke the current session |
GET /v1/console/session | Whoami for the current session |
GET /v1/console/keys | List key metadata. Never returns a secret. Session only; an API key is refused. |
POST /v1/console/keys | Issue a key. The raw value is in this response and nowhere else. |
POST /v1/console/keys/{id}/revoke | Revoke a key belonging to your tenant. Another tenant's id reads as absent. |
GET /v1/console/members | Roster and open invitations. Any member may read it. |
POST /v1/console/invites | Admin only. Mints a one-time invitation token, returned once. Nodus does not email it. |
POST /v1/console/invite/accept | Redeem an invitation into an account and a session. The email comes from the invite, never the request. |
POST /v1/console/members/{id}/role | Admin only. 409 rather than strand an account with no admin. |
POST /v1/console/members/{id}/remove | Admin only. Signs them out everywhere by cascade. |
POST /v1/console/password | Change your own password. Signs out every other session. |
POST /v1/console/members/{id}/reset | Admin only. Issues a one-time reset token for a locked-out teammate. |
GET / PUT /v1/console/limits | Read or set the monthly spend cap. Setting it is admin only; a null cap means unbounded. |
GET /v1/console/usage | Daily spend series plus month-to-date and the cap. |
GET /v1/console/audit | Console actions with actor: keys, members, invitations, limits. |
POST /v1/signup | Legacy: invite → tenant + key, with no console account. Prefer /v1/console/signup. |
PUT /v1/billing/profile | Set the billing contact |
GET /v1/billing/invoices | List invoices |
POST /v1/billing/invoices | Invoice unbilled charges for one workload |
GET /healthz | Liveness. No auth, no database read |
GET /readyz | Readiness. 503 while draining or when the database is unreachable |
# CLI
The nodus command ships with the SDK and reads
the same environment. Fastest way to submit a one-off brief from a terminal.
$ export NODUS_API_KEY=nk_live_… # submit and block until the work is done $ nodus run \ --model "7B fine-tune" \ --peak-memory-gb 80 --hours 18 --budget 400 \ --continuity checkpointed \ --wait --timeout 72000 \ -- python train.py --epochs 10 # inspect without blocking $ nodus list --status active $ nodus get wl_9f3c1b2a --wait $ nodus events wl_9f3c1b2a --follow $ nodus artifacts wl_9f3c1b2a $ nodus cancel wl_9f3c1b2a
Everything after -- runs inside the workload.
--wait exits non-zero on
failed or
cancelled, so it composes in CI.