Skip to content

API Reference

The Nexus REST API runs on Gin and listens on port 8080. Base URL: http://<host>:8080.

/auth/* routes and the health probes are unauthenticated. Everything under /api/v1/* passes through DualAuthMiddleware, which accepts either credential type:

MethodHeaderUse caseScope
Bearer JWTAuthorization: Bearer <jwt>Interactive sessionsUser; add X-Tenant-ID: <id> to scope to a tenant
API keyX-API-Key: <key>Programmatic clientsTenant-scoped

The middleware tries the Bearer JWT first; if absent or invalid, it falls back to X-API-Key. If neither is valid it returns 401.

  • Tenant and key management (POST/GET/DELETE /tenants, */keys) require a JWT — they act on behalf of a user.
  • Agent and observability routes work with either a JWT (scoped via X-Tenant-ID) or an API key (already tenant-scoped).
MethodPathAuthPurpose
POST/auth/registernoneRegister a user
POST/auth/loginnoneLogin → access + refresh JWT
POST/auth/refreshnoneRotate and refresh the access token
GET/api/v1/meJWT/KeyCurrent user / tenant
POST/api/v1/tenantsJWTCreate tenant (+ namespace)
GET/api/v1/tenantsJWTList tenants
DELETE/api/v1/tenants/:idJWTDelete tenant
POST/api/v1/tenants/:id/keysJWTCreate API key
GET/api/v1/tenants/:id/keysJWTList API keys
DELETE/api/v1/tenants/:id/keys/:hashJWTRevoke API key
POST/api/v1/agentsJWT/KeyCreate / register agent
GET/api/v1/agentsJWT/KeyList agents
GET/api/v1/agents/:nameJWT/KeyGet agent spec + status
PUT/api/v1/agents/:nameJWT/KeyUpdate agent
DELETE/api/v1/agents/:nameJWT/KeyDelete agent
GET/api/v1/agents/:name/statusJWT/KeyPhase, nodeAck, lastSyncedAt
GET/api/v1/agents/:name/logsJWT/KeyAgent logs
GET/api/v1/agents/:name/metricsJWT/KeyAgent metrics
GET/healthz, /readyznoneLiveness / readiness probes

A full flow: register → login → create tenant → create API key → deploy an agent → check status.

Terminal window
API_URL="http://localhost:8080"
curl -sf -X POST "$API_URL/auth/register" \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"a-strong-password","displayName":"Admin"}'

Representative response (201 Created):

{
"accessToken": "eyJ...",
"refreshToken": "...",
"user": { "id": "usr_...", "email": "admin@example.com", "displayName": "Admin" }
}

If the email already exists the endpoint returns 409; log in instead.

Terminal window
TOKEN=$(curl -sf -X POST "$API_URL/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"a-strong-password"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['accessToken'])")
Terminal window
TENANT=$(curl -sf -X POST "$API_URL/api/v1/tenants" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"displayName":"My Organisation","nodeProfile":"full"}')
TENANT_ID=$(echo "$TENANT" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

Representative response (201 Created):

{ "id": "t_...", "crName": "tenant-...", "displayName": "My Organisation" }
Terminal window
KEY=$(curl -sf -X POST "$API_URL/api/v1/tenants/$TENANT_ID/keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"label":"ci"}')
API_KEY=$(echo "$KEY" | python3 -c "import sys,json; print(json.load(sys.stdin)['rawKey'])")

Representative response (201 Created):

{ "rawKey": "...", "label": "ci" }

The agent endpoints read the agent spec YAML as the raw request body (not a JSON wrapper). The agent name is extracted from the spec’s metadata.name.

Terminal window
curl -sf -X POST "$API_URL/api/v1/agents" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/yaml" \
--data-binary @support-bot.yaml

Where support-bot.yaml is a full astromesh/v1 Agent spec:

apiVersion: astromesh/v1
kind: Agent
metadata:
name: support-bot
version: "1.0.0"
spec:
identity:
display_name: "Support Bot"
model:
primary:
provider: ollama
model: "llama3.1:8b"
orchestration:
pattern: react

Representative response (201 Created):

{ "name": "support-bot", "namespace": "tenant-..." }
Terminal window
curl -sf -H "X-API-Key: $API_KEY" "$API_URL/api/v1/agents/support-bot/status"

The status endpoint proxies to the tenant’s astromesh-node and returns its live view of the agent.

  • Content type. /auth/*, tenant, and key endpoints use JSON. The agent POST/PUT endpoints take the raw agent spec YAML in the body.
  • Errors. Failures return { "error": "<message>" } with the appropriate status:
    • 400 — invalid body or agent spec validation failure.
    • 401 — missing/invalid JWT or API key.
    • 403 — authenticated but not authorized for the tenant.
    • 404 — agent or user not found.
    • 409 — email already registered.
    • 502 — the upstream astromesh-node could not be reached (status/metrics).
  • Token rotation. POST /auth/refresh rotates the refresh token: the old one is revoked and a new access + refresh pair is issued.
  • Agent listing. GET /api/v1/agents returns a summary array (name, phase, createdAt); GET /api/v1/agents/:name returns the full spec plus status.phase and status.nodeAck.
  • Quickstart — end-to-end bootstrap and deploy.
  • Architecture — the CRDs and reconcilers behind these endpoints.