Creating an API Key
Stealthium uses API keys to authenticate agents running on your machines. This guide shows you how to sign in via the REST API and generate a key entirely from the command line — no UI required after the initial OAuth step.
How Authentication Works
Stealthium signs users in through GitHub or Google OAuth. (Deployments can also enable email/password login — GET /api/v1/auth/methods tells you what yours supports.)
Domain restriction: Only email addresses whose domain belongs to an active Stealthium customer can log in. If you get a
domain_not_allowederror, contact your Stealthium administrator to register your company's email domain.
The flow is:
- You open the OAuth login URL in a browser once.
- After approving, Stealthium redirects back to your
frontend_urlwith a short-lived, single-usecodein the URL. - You exchange that
codefor a JWT session token atPOST /api/v1/auth/token. - You use the JWT as a Bearer token for all subsequent API calls, including creating API keys.
Step 1 — Trigger OAuth Login
Open one of these URLs in a browser, choosing your preferred provider:
GitHub:
https://api.backend.stealthium.io/api/v1/auth/github?frontend_url=http://localhost:5173
Google:
https://api.backend.stealthium.io/api/v1/auth/google?frontend_url=http://localhost:5173
The frontend_url is where Stealthium will redirect after login, appending ?code=<auth-code>. For local use, http://localhost:5173 works fine. The URL must be on the Stealthium allowlist — if you get an Invalid Frontend URL error, contact your admin to add your URL.
After you approve the OAuth prompt, your browser will be redirected to:
http://localhost:5173/auth/callback?code=<AUTH-CODE>
Copy the code value from the URL. It is not a session token yet — it's a single-use authorization code that must be exchanged in the next step.
Auth codes are single-use and expire ~60 seconds after they're issued. If the exchange in Step 2 fails for any reason, the code is burned — restart from Step 1.
Step 2 — Exchange the Code for a Token
curl -s -X POST https://api.backend.stealthium.io/api/v1/auth/token \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"code": "<AUTH-CODE>",
"redirect_uri": "http://localhost:5173"
}'
redirect_uri must be exactly the frontend_url you started the flow with, or the exchange fails with a 401.
Response:
{
"access_token": "<YOUR-JWT>",
"refresh_token": "<YOUR-REFRESH-TOKEN>",
"token_type": "Bearer",
"expires_in": 21600
}
access_token is your session JWT — use it as the Bearer token in every call below. (Browsers that omit the Accept: application/json header get the session as HttpOnly cookies instead; that's what the Stealthium web app uses.)
The access token lasts 6 hours. When it expires, get a fresh one with your refresh token instead of logging in again:
curl -s -X POST https://api.backend.stealthium.io/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"refresh_token": "<YOUR-REFRESH-TOKEN>"}'
Refresh tokens last 24 hours and are not extended by use, so a session caps out at 24 hours before you must log in again.
Step 3 — Verify Your Session (Optional)
Confirm the token works and see your user info:
curl -s https://api.backend.stealthium.io/api/v1/me \
-H "Authorization: Bearer <YOUR-JWT>"
Response:
{
"user": {
"id": 1,
"email": "you@yourcompany.com",
"name": "Your Name",
"avatar": "https://..."
}
}
Step 4 — Create an API Key
An API key belongs to a workspace, so the request must name one (you must be an owner or member of it). List your workspaces first if you don't know the id:
curl -s https://api.backend.stealthium.io/api/v1/workspaces/ \
-H "Authorization: Bearer <YOUR-JWT>"
Then create the key:
curl -s -X POST https://api.backend.stealthium.io/api/v1/keys/ \
-H "Authorization: Bearer <YOUR-JWT>" \
-H "Content-Type: application/json" \
-d '{
"name": "Northeast Cluster",
"description": "Production GPU hosts",
"workspace_id": 1
}'
Response (201 Created):
{
"api_key": {
"id": 42,
"name": "Northeast Cluster",
"key": "4e0234cd-307a-4f9a-a8e3-eb237752763d",
"description": "Production GPU hosts",
"workspace_id": 1,
"workspace_name": "Production",
"customer_id": 1,
"is_active": true,
"expires_at": "",
"last_used_at": "",
"created_at": "2026-03-19T10:00:00Z",
"updated_at": "2026-03-19T10:00:00Z"
},
"message": "API key created successfully"
}
API keys are plain UUIDs — no prefix. The agent validates the format and refuses to start with anything else, so always copy the key exactly as returned.
Step 5 — Use the Key in Your Agent
Paste the key into your Stealthium agent configuration.
Debian / Ubuntu package
echo "[orion]" | sudo tee /etc/stealthium/config.toml
echo 'api_key = "4e0234cd-307a-4f9a-a8e3-eb237752763d"' | sudo tee -a /etc/stealthium/config.toml
Docker environment variable
docker run -d \
--name stealthium-agent \
-e STEALTHIUM_API_KEY="4e0234cd-307a-4f9a-a8e3-eb237752763d" \
-e LD_LIBRARY_PATH="/host-usr/lib:/host-usr/local/lib:/home/kubernetes/bin/nvidia/lib64" \
--restart always \
--privileged \
--cap-add NET_ADMIN \
--pid host \
-v /sys/kernel/debug:/sys/kernel/debug:ro \
-v /sys/fs/bpf:/sys/fs/bpf \
-v /lib/modules:/lib/modules:ro \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
-v /sys/kernel/tracing:/sys/kernel/tracing \
-v /run/dbus/system_bus_socket:/run/dbus/system_bus_socket:rw \
-v /etc/stealthium:/etc/stealthium:rw \
-v /usr:/host-usr:ro \
registry.backend.stealthium.io/stealthium/release:latest
Helm (Kubernetes)
helm upgrade --install stealthium-agent \
oci://registry.backend.stealthium.io/stealthium/release/stealthium-agent \
--namespace stealthium \
--create-namespace \
--set stealthium.apiKey=4e0234cd-307a-4f9a-a8e3-eb237752763d \
--set registryCredentials.registry=registry.backend.stealthium.io \
--set registryCredentials.create=true \
--set registryCredentials.username=harbor-user \
--set registryCredentials.password='harbor-password'
Without --version, Helm installs the latest published chart. To see what's available:
helm show chart oci://registry.backend.stealthium.io/stealthium/release/stealthium-agent
Other Key Management Commands
List all your keys
curl -s https://api.backend.stealthium.io/api/v1/keys/ \
-H "Authorization: Bearer <YOUR-JWT>"
Rotate a key
Generates a new secret for an existing key while keeping its id and history:
curl -s -X POST https://api.backend.stealthium.io/api/v1/keys/<key-id>/rotate \
-H "Authorization: Bearer <YOUR-JWT>"
Delete a key
curl -s -X DELETE https://api.backend.stealthium.io/api/v1/keys/<key-id> \
-H "Authorization: Bearer <YOUR-JWT>"
Troubleshooting
"domain_not_allowed" after OAuth
Your email domain doesn't belong to an active Stealthium customer. Ask a Stealthium admin to register your company's email domain.
"Invalid Frontend URL"
The frontend_url you passed is not on the server's allowlist. Use an approved URL (e.g. http://localhost:5173 for local use) or ask your admin to add your URL.
"Invalid Code" when exchanging
Auth codes are single-use and expire after ~1 minute, and the redirect_uri in the exchange must exactly match the frontend_url the flow started with. A failed attempt burns the code — restart from Step 1.
GitHub login — no email found
If your GitHub email is set to private, Stealthium automatically fetches your email from the GitHub API. Make sure your GitHub account's primary email address is verified.
Compromised key
Rotate it — the key id stays the same, so nothing else needs updating on the Stealthium side:
curl -s -X POST https://api.backend.stealthium.io/api/v1/keys/<key-id>/rotate \
-H "Authorization: Bearer <YOUR-JWT>"
Then update your agent configuration with the new key value.