Skip to main content

REST API

helyosd exposes a versioned REST API that the helyos CLI — and any HTTP client you write — uses to manage projects, deployments, pods, nodes, routes, and tokens. This page is the complete endpoint reference: every route, its HTTP method, whether it needs authentication, and what it does.

If you mostly use the CLI, you rarely touch the API directly. But the API is the contract behind every command, and knowing it makes scripting, automation, and debugging straightforward.

Base URL and port

The API listens on port 6443 by default (override with the daemon's --port flag). All resource endpoints are namespaced under /api/v1/.

Whether you reach it over https:// or http:// depends on the TLS mode:

  • HTTPS by default. With the default --tls auto, the daemon serves HTTPS on any non-loopback bind and generates a self-signed certificate on first start.
  • Plain HTTP on loopback. When bound to a loopback address (127.0.0.1), auto keeps the API on plain HTTP for local convenience.

So a typical local base URL is http://localhost:6443, and a typical remote base URL is https://cluster.example.com:6443.

info

Because the daemon uses a self-signed certificate by default, plain curl against an HTTPS endpoint fails certificate verification. Either pin the CA (see CA pinning below) or use curl -k for quick local testing. For details on the TLS model, see Automatic TLS and TLS & CA pinning.

Authentication

Every route under /api/v1/ is protected with a Bearer token, except version and ca, which are public so a client can probe reachability and pin the CA before it has a token. The two public non-versioned routes /health and /metrics are also unauthenticated.

Send the token in the standard Authorization header:

Authorization: Bearer <token>

For example, with curl:

curl -sk https://localhost:6443/api/v1/whoami \
-H "Authorization: Bearer $HELYOS_API_TOKEN"

API tokens have the prefix nxa-api_ followed by 64 hex characters. The daemon generates one on first run and logs it once as HELYOS_API_TOKEN=...; you can also supply your own via the --api-token flag or the HELYOS_API_TOKEN environment variable. Tokens are stored as Argon2id hashes — the plaintext is never persisted.

A request with a missing or invalid token receives:

{ "error": "missing or invalid bearer token" }

with HTTP status 401 Unauthorized.

note

If the daemon is started with no API token configured at all, the Bearer middleware passes requests through unauthenticated. This is intended only for local development. A non-loopback bind requires a token. For the full security model, see API tokens and Security model.

Public endpoints

These routes never require authentication.

MethodPathAuthDescription
GET/healthnoneLiveness / health check
GET/metricsnonePrometheus metrics
GET/api/v1/versionnoneDaemon version and TLS reachability probe
GET/api/v1/canoneSelf-signed CA PEM and SHA-256 fingerprint (for pinning)

Bearer-protected endpoints

Every route below requires a valid Authorization: Bearer <token> header.

Identity and tokens

MethodPathAuthDescription
GET/api/v1/whoamiBearerIdentity of the calling token
POST/api/v1/tokensBearerMint a named API token (secret shown once)
GET/api/v1/tokensBearerList API tokens (never the secret)
DELETE/api/v1/tokens/{name}BearerRevoke an API token by name

Projects

MethodPathAuthDescription
GET/api/v1/projectsBearerList projects
POST/api/v1/projectsBearerCreate a project
POST/api/v1/projects/{name}/suspendBearerSuspend a project (stops its deployments)
POST/api/v1/projects/{name}/resumeBearerResume a suspended project
DELETE/api/v1/projects/{name}BearerDelete a project

Deployments and pods

MethodPathAuthDescription
POST/api/v1/deployBearerDeploy from a spec
GET/api/v1/deploymentsBearerList deployments
POST/api/v1/projects/{p}/deployments/{d}/scaleBearerScale a deployment
POST/api/v1/projects/{p}/deployments/{d}/stopBearerStop a deployment
DELETE/api/v1/projects/{p}/deployments/{d}BearerRemove a deployment
GET/api/v1/projects/{p}/deployments/{d}/logsBearerStream deployment logs
GET/api/v1/podsBearerList pods

Secrets

MethodPathAuthDescription
GET/api/v1/projects/{p}/secretsBearerList a project's secret names
POST/api/v1/projects/{p}/secrets/{n}BearerSet a secret
DELETE/api/v1/projects/{p}/secrets/{n}BearerDelete a secret

Nodes and events

MethodPathAuthDescription
GET/api/v1/nodesBearerList nodes
GET/api/v1/nodes/statsBearerNode resource stats
POST/api/v1/nodes/{name}/drainBearerDrain a node
DELETE/api/v1/nodes/{name}BearerRemove a node
GET/api/v1/eventsBearerCluster event stream (Server-Sent Events)

Routes and certificates

MethodPathAuthDescription
GET/api/v1/routesBearerList routes
POST/api/v1/routesBearerAdd a route
DELETE/api/v1/routes/{domain}BearerRemove a route by domain
POST/api/v1/certs/importBearerImport a TLS certificate

Cluster and configuration

MethodPathAuthDescription
POST/api/v1/cluster/initBearerInitialize the cluster
GET/api/v1/cluster/tokenBearerShow the cluster join token
POST/api/v1/cluster/token/rotateBearerRotate the cluster join token
GET/api/v1/cluster/schedulerBearerGet scheduler config
POST/api/v1/cluster/schedulerBearerSet scheduler config
GET/api/v1/cluster/config/proxyBearerGet proxy config
POST/api/v1/cluster/config/proxyBearerSet proxy config

The CA pinning flow

GET /api/v1/ca is public so a fresh client can fetch the daemon's self-signed CA and verify it out of band before sending any credentials. The response contains the CA in PEM form and its SHA-256 fingerprint:

curl -sk https://cluster.example.com:6443/api/v1/ca
{
"pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n",
"sha256": "ab:cd:ef:01:23:45:..."
}

You then pass that fingerprint to helyos login so the CLI pins it for all future connections:

helyos login https://cluster.example.com:6443 \
--token "$HELYOS_API_TOKEN" \
--ca-fingerprint ab:cd:ef:01:23:45:...
tip

If the daemon is running with TLS off or with a bring-your-own certificate, /api/v1/ca returns 404 Not Found with { "error": "no self-signed CA (TLS off or BYO cert)" }. There is no self-signed CA to pin in those cases.

For the end-to-end remote setup, see Remote access.

The whoami flow

GET /api/v1/whoami returns the identity of the token presented in the Authorization header. It is the simplest way to confirm a token is valid and see its scope and metadata:

curl -sk https://localhost:6443/api/v1/whoami \
-H "Authorization: Bearer $HELYOS_API_TOKEN"
{
"name": "ci-bot",
"scope": "admin",
"created_at": "2026-06-07T10:00:00Z",
"expires_at": null,
"last_used_at": "2026-06-07T12:30:00Z"
}

The CLI exposes this as helyos whoami.

The token-mint flow

You can mint additional named tokens at runtime with POST /api/v1/tokens. The request body accepts a required name and optional scope and ttl_secs (a time-to-live in seconds; a non-positive or omitted value means the token never expires).

curl -sk https://localhost:6443/api/v1/tokens \
-H "Authorization: Bearer $HELYOS_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "ci-bot", "ttl_secs": 2592000 }'

The response includes the plaintext secret — this is the only time it is ever returned:

{
"id": "...",
"name": "ci-bot",
"token": "nxa-api_0123456789abcdef...",
"scope": "admin",
"created_at": "2026-06-07T12:00:00Z",
"expires_at": "2026-07-07T12:00:00Z"
}
warning

The secret is shown once and never again — the daemon only stores its Argon2id hash. Capture it immediately. If you lose it, revoke the token and mint a new one.

In v1 every token has admin scope; the scope field is stored but not yet enforced.

List tokens (the secret and hash are never returned) and revoke a token by name:

# List
curl -sk https://localhost:6443/api/v1/tokens \
-H "Authorization: Bearer $HELYOS_API_TOKEN"

# Revoke — returns 204 No Content on success, 404 if no active token has that name
curl -sk -X DELETE https://localhost:6443/api/v1/tokens/ci-bot \
-H "Authorization: Bearer $HELYOS_API_TOKEN"

The CLI wraps these as helyos auth token create, helyos auth token ls, and helyos auth token revoke.

note

These named API tokens (prefix nxa-api_) are distinct from the cluster join token (prefix nxa_) used by workers to join a master. The join token is managed via the /api/v1/cluster/token endpoints. See Clustering.

Deploying via the API

The POST /api/v1/deploy endpoint takes a deployment spec as JSON. The CLI sends YAML-sourced specs through this route; you can do the same directly:

curl -sk https://localhost:6443/api/v1/deploy \
-H "Authorization: Bearer $HELYOS_API_TOKEN" \
-H 'Content-Type: application/json' \
-d @spec.json

The spec fields are documented in the Deployment spec reference.

Next steps

  • API tokens — how tokens are generated, scoped, and revoked
  • TLS & CA pinning — verifying the daemon's certificate
  • Remote accesshelyos login and connection contexts end to end
  • CLI reference — the command-line equivalents of these endpoints
  • Daemon flagshelyosd options including --port, --tls, and --api-token