Authentication
Authenticate API requests with workspace API keys using bearer tokens
Use API keys to authenticate server-to-server requests to andibase.
You can either create a key manually in the app or start a customer approval flow for an agent and exchange the approved device code for a workspace key.
Embedded apps use a separate runtime-key flow described below. Those keys are still Better Auth API keys, but they are short-lived, server-issued, and intended to stay in memory only.
Agent login flow
Agents can start a browser-based customer approval flow without asking the user to dig through the app first.
- Call
POST /api/agent/auth/requests. - Show the returned
userCodeorverificationUriCompleteto the customer. - The customer signs in at
/agent-loginand approves one workspace. - Poll
POST /api/agent/auth/exchangewith the returneddeviceCode. - Once approved, the response includes a workspace-scoped API key secret at
apiKey.key. - Persist that key securely and reuse it. Do not send the user through login again unless the key was revoked or intentionally expired.
Example start request:
curl "https://andiapi.com/api/agent/auth/requests" \
-H "Content-Type: application/json" \
-d '{
"agentName": "Claude",
"agentDescription": "Inspect and update workspace data",
"role": "admin"
}'If you omit role, agent login defaults to admin.
How authentication works
Create an API key from your workspace in the app:
- Open the workspace you want to access.
- Go to API Keys.
- Create a key and choose the role it should have.
- Copy the secret immediately. You will only see it once.
Each API key is scoped to the workspace where it was created. When you send the key, the API resolves that workspace from the key itself.
Embedded app runtime keys
Public apps published at /apps/:handle do not embed API keys in server-rendered HTML.
The host page calls POST /api/v1/experimental/apps/:handle/runtime-token after the iframe runtime posts andibase:ready. The server:
- Loads the app and workspace.
- Resolves the first-party session, if one exists.
- Chooses
memberaccess only for signed-in workspace members. - Otherwise chooses
publicaccess. - Recomputes permissions from the app row.
- Mints a short-lived Better Auth API key with embedded-app metadata.
The iframe stores the response in memory only and reads it through:
window.andibase.auth.getAccessToken()window.andibase.auth.getPermissions()window.andibase.auth.onAuthChanged(listener)window.andibase.fetch(path, init?)
Embedded app refresh
- Runtime keys default to a 5 minute TTL.
- The server returns
refreshAfteralongsideexpiresAt. - The iframe asks the parent page for a refresh before the key expires.
- Refresh does not require the old runtime key. The server re-evaluates the request using the host page request context and the latest app config.
- Old and new keys overlap until the old key expires naturally.
- Permission changes can start applying on the next successful refresh even before the previous key expires.
Send the key in the Authorization header
Use the key as a bearer token:
curl "https://andiapi.com/api/data-definitions" \
-H "Authorization: Bearer $ANDI_API_KEY"For clients that cannot send bearer tokens, x-api-key: <key> is also accepted, but Authorization: Bearer <key> is the recommended format.
Store the key securely
Do not hardcode API keys in source files or commit them to git.
Store the key in a secure environment variable such as ANDI_API_KEY:
export ANDI_API_KEY="andi_live_..."Then read it from your server runtime:
const apiKey = process.env.ANDI_API_KEY;
const response = await fetch("https://andiapi.com/api/data-definitions", {
headers: {
Authorization: `Bearer ${apiKey}`,
},
});That guidance applies to manual and agent-login API keys. Embedded app runtime keys are different: do not put them in query params, route params, localStorage, sessionStorage, IndexedDB, or server-rendered HTML.
Roles
When you create a key, you assign one of the hardcoded roles:
admin: full workspace access. This is the default for manual API keys and agent-login keys.editor: read and write access for apps, data, and files, plus workspace read access.viewer: read-only access across apps, data, files, and workspace metadata.
The API still enforces permissions internally. If a key does not have the required capability, the API returns 403 with a JSON body that names the missing permission.
Workspace behavior
API keys are already bound to one workspace, so you do not need to send a workspace header with bearer-token requests.
That makes them a good fit for backend services, workers, scripts, and integrations running outside the app.
Recommendations
- Use a different API key per environment or integration.
- Grant the smallest role that fits the integration.
- Rotate keys if they are exposed or no longer needed.
- Revoke keys from the workspace API Keys page when an integration is retired.