Authentication
Universe authenticates every protected request with a bearer token passed in the Authorization header. Tokens carry one of two permission levels, ALL or PUBLIC, which decide endpoint access and rate limiting.
The API uses bearer-token authentication. Each request to a protected endpoint must include a valid token in the Authorization header. Tokens are created and managed through the console, and each token is bound to a single permission level that governs what it may do.
The Authorization header
Send the token with the Bearer scheme on every protected request:
Authorization: Bearer YOUR_TOKEN
A complete request looks like this:
curl http://<master>:7000/api/instances \
-H "Authorization: Bearer YOUR_TOKEN"
Only GET /api/ping and GET /api/metrics are unauthenticated. Every other endpoint, including all WebSocket handshakes, requires a token.
Permission levels
Tokens carry one of two scopes:
| Scope | Access | Rate limit |
|---|---|---|
ALL | Full admin access to every endpoint: instance management, configuration changes, template edits, command execution, and log retrieval. | Exempt. Admin keys bypass rate limiting entirely. |
PUBLIC | Read-only access to public endpoints. No instance endpoint is public, so instance operations are unavailable to public keys. | Limited to 100 calls per 60 seconds by default. |
Every instance endpoint, including GET /api/instances, GET /api/instances/{id}, and the log routes, requires ALL permission. A PUBLIC key cannot reach them.
Generating tokens
Create keys from the Master console (or over REST via the Commands API) with the key create command, passing a label and the desired permission level:
# Create an admin key with full access
key create my-admin-key ALL
# Create a read-only public key
key create dashboard PUBLIC
Failure responses
A missing, malformed, or invalid token returns 401 Unauthorized with an error field:
{
"error": "Unauthorized"
}
A PUBLIC key that exceeds its rate window returns 429 Too Many Requests with the retry delay in milliseconds:
{
"error": "Rate limit exceeded. Retry after 45000ms.",
"retryAfterMs": 45000
}
Reaching an endpoint that is out of scope for your token (for example a public key calling an instance route) is rejected at the authorization layer. Treat a 401 on an instance route as a sign the token lacks ALL permission.
Authenticating WebSockets
WebSocket endpoints use the same bearer token, supplied as an Authorization header during the HTTP upgrade handshake. The token is validated before the connection is established.
GET /api/instances/a1b2c3/live-log HTTP/1.1
Host: <master>:7000
Upgrade: websocket
Connection: Upgrade
Authorization: Bearer YOUR_TOKEN If your WebSocket client cannot set custom headers on the handshake, terminate the socket behind a proxy that injects the Authorization header. See the WebSockets page for the live-log and console endpoints.