Use the native HTTP and WebSocket API
Talk to Nimbus from any language — create tenants, write documents, run queries, and subscribe to live results over WebSocket.
Nimbus speaks plain HTTP and WebSocket, so any language with an HTTP client can use it without an SDK or codegen. This guide walks through authenticating, scoping requests to a tenant, working with documents, and subscribing to live query results.
If you have not run a server yet, start with the self-host quickstart.
1. Get the local admin token
A server started with nimbus start protects its native API with a local
admin token. Nimbus creates the token on first boot and stores it as a JSON
file:
| Platform | Token file |
|---|---|
| Linux | ~/.local/share/nimbus/auth/token |
| macOS | ~/Library/Application Support/nimbus/auth/token |
| Windows | %LOCALAPPDATA%\nimbus\auth\token.json |
Read the token field and export it for the rest of this guide:
# Linux
export NIMBUS_TOKEN=$(jq -r .token ~/.local/share/nimbus/auth/token)
# macOS
export NIMBUS_TOKEN=$(jq -r .token "$HOME/Library/Application Support/nimbus/auth/token")Send it on every request, either as a bearer token or in the
X-Nimbus-Admin-Token header:
curl -s http://localhost:8080/api/tenants \
-H "Authorization: Bearer $NIMBUS_TOKEN"Requests without a valid credential get a 401 with code
auth.unauthorized. Browser-based callers must also use loopback origins. See
the HTTP API reference for the full access
rules.
2. Scope requests to a tenant
The URL path scopes every data operation to a tenant:
/api/tenants/{tenant_id}/.... Create a tenant first:
curl -s -X POST http://localhost:8080/api/tenants \
-H "Authorization: Bearer $NIMBUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "demo"}'The server replies 201 Created with {"id": "demo"}. Tenants are fully
isolated from each other: documents, schemas, scheduled jobs, and
subscriptions never cross tenant boundaries.
3. Insert and read documents
Insert a document by naming a table and its fields. Nimbus creates tables implicitly on the first write:
curl -s -X POST http://localhost:8080/api/tenants/demo/documents \
-H "Authorization: Bearer $NIMBUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"table": "messages", "fields": {"text": "hello world", "author": "you"}}'The response is 201 Created with the generated document id:
{"id": "01jx2x9w7d2f0v6q8t3k5r9e1b"}Read it back. Single documents and table listings are GET requests:
# One document
curl -s http://localhost:8080/api/tenants/demo/documents/messages/<id> \
-H "Authorization: Bearer $NIMBUS_TOKEN"
# Every document in the table
curl -s http://localhost:8080/api/tenants/demo/documents/messages \
-H "Authorization: Bearer $NIMBUS_TOKEN"Returned documents carry three system fields alongside your own: _id,
_creationTime, and _updateTime (epoch milliseconds). Update with PATCH
(a partial patch object) and delete with DELETE on the same
/documents/{table}/{document_id} path.
4. Run queries
POST a query object to filter, order, and limit results. The request requires
filters. Pass an empty array to match everything:
curl -s -X POST http://localhost:8080/api/tenants/demo/query \
-H "Authorization: Bearer $NIMBUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"table": "messages",
"filters": [{"field": "author", "op": "eq", "value": "you"}],
"order": {"field": "_creationTime", "direction": "desc"},
"limit": 10
}'For large result sets, use /query/paginated with a page_size and follow
the returned cursor. The HTTP API reference
lists both endpoints, all filter operators, and the paginated shapes.
5. Subscribe to live results over WebSocket
You can register the same query as a subscription. The server pushes a
fresh snapshot whenever a mutation changes the result. Connect to /ws
with the nimbus.v2 subprotocol and identify the tenant with an
X-Tenant-Id header or a tenant_id query parameter.
This example uses the ws package, which lets you set headers during the
upgrade:
import WebSocket from "ws";
const socket = new WebSocket("ws://localhost:8080/ws?tenant_id=demo", ["nimbus.v2"], {
headers: { Authorization: `Bearer ${process.env.NIMBUS_TOKEN}` },
});
socket.on("message", (raw) => {
const frame = JSON.parse(raw.toString());
switch (frame.type) {
case "hello":
// Complete the handshake, then subscribe.
socket.send(JSON.stringify({ type: "client_hello", protocol: "nimbus.v2" }));
socket.send(
JSON.stringify({
type: "subscribe",
request_id: "messages-1",
query: { table: "messages", filters: [] },
}),
);
break;
case "subscription_result":
// frame.data is the full current result set for the query.
console.log(`subscription ${frame.subscription_id}:`, frame.data);
break;
case "op.error":
case "error":
case "fatal_error":
console.error(frame.error.code, frame.error.message);
break;
}
});Two handshake rules to respect: reply to the server's hello frame with
client_hello within 10 seconds, and send only JSON text frames. The full
frame catalog, handshake failure modes, and reconnect semantics are in the
WebSocket protocol reference.
Handle errors
HTTP and WebSocket errors use one envelope:
{
"error": {
"code": "op.invalid_input",
"message": "invalid document id `abc`",
"requestId": "req-...",
"timestamp": "2026-06-10T17:03:21Z",
"severity": "error",
"retryable": false,
"detail": null,
"remediation": { "action": "fix_request", "message": "Correct the request payload before retrying." }
}
}Branch on code, retry when retryable is true, and surface
remediation.message to operators. The complete code catalog with HTTP
status mappings is in the error reference.
Next steps
- Example apps: a browser playground and the shared tasks list on the native SDK.
- HTTP API reference: every endpoint, request shape, and response shape.
- WebSocket protocol reference:
the
nimbus.v2frame contract. - Error reference: error codes, severities, and status mappings.
- Agents: the same server's resource APIs through the JavaScript SDK.
DynamoDB example apps
A runnable DynamoDB app on Nimbus — the shared tasks list driven by the stock AWS SDK against the Nimbus DynamoDB endpoint.
Native example apps
Runnable apps on the native @nimbus/nimbus SDK — a browser playground and the shared tasks list, with reactive documents over HTTP writes and live WebSocket reads.