Self-serve access

Workspace setup, agent account tokens, and runtime API keys.

LoreOS has two auth planes:

  • Account plane - workspace, team, app, API key, external-user cap, usage, and billing management.
  • Runtime plane - character, session, message, import, image, delivery, and metering calls for your product.

Keep them separate. A coding agent may use a short-lived account access token to set up your workspace, issue an app key, and manage users. Your server then uses the issued runtime API key for character runtime calls such as POST /v1/characters and POST /v1/sessions/{session_id}/messages.

The account-plane API is in preview. The backend device-flow/token path is implemented and live-tested, and the browser approval page is available at /console/device. Account routes are not yet part of the generated API Reference or public SDK surface. Treat this page and GET /v1/llms.txt as the preview contract until the account-plane graduation gates pass.

When to use each key

CredentialPrefixUsed byCan call
Demo sandbox keyreturned by POST /v1/demo/sandbox-keylocal tests and docs dogfoodcapped runtime /v1/* routes
Account access tokenlat_...coding agents and console automation/v1/account/* only
Runtime API keyapp keyyour backend servicepublic runtime /v1/* routes

Never put a runtime API key in a browser or mobile app. Never give an agent your Google, Clerk, or session-cookie credentials.

Agent-safe workspace setup

Use this flow when account-device approval is enabled and a coding agent needs to create a workspace app and issue a runtime API key without handling a human login.

  1. The agent starts device authorization:
$curl -X POST https://api.loreos.app/v1/account/device/start \
> -H "Content-Type: application/json" \
> -d '{
> "client_label": "codex-local-setup",
> "client_fingerprint": "opaque-agent-installation-id",
> "scopes": [
> "account:workspace:read",
> "account:apps:write",
> "account:api_keys:write",
> "account:external_users:write",
> "account:caps:write",
> "account:usage:read"
> ]
> }'
  1. The response includes:
1{
2 "schema_version": "v0",
3 "data": {
4 "device_code": "ldc_...",
5 "user_code": "ABCD-2345",
6 "verification_uri": "https://<loreos-console>/console/device?user_code=ABCD-2345",
7 "expires_at": "2026-06-19T12:00:00Z",
8 "interval_seconds": 5,
9 "requested_scopes": ["account:workspace:read", "account:apps:write"]
10 },
11 "next_actions": [
12 {
13 "command": "POST /v1/account/device/token",
14 "description": "Poll with device_code after the human approves the user_code."
15 }
16 ]
17}
  1. A human opens verification_uri, signs in with Clerk/Google, chooses or creates the workspace, reviews the scopes, and approves the code. The human identity check stays in the browser; the agent never receives browser cookies or OAuth credentials. The console approval page uses GET /v1/account/device/{user_code} behind the signed browser proxy to show the client label, requested scopes, status, and expiry before approval.

  2. The agent polls for the account token:

$curl -X POST https://api.loreos.app/v1/account/device/token \
> -H "Content-Type: application/json" \
> -d '{ "device_code": "ldc_..." }'

If the human has not approved yet, the response is data.status = "pending". After approval, the response includes a short-lived data.account_access_token.

  1. The agent confirms the token:
$curl https://api.loreos.app/v1/account/me \
> -H "Authorization: Bearer $LOREOS_ACCOUNT_TOKEN"
  1. The agent creates a sandbox or staging app:
$curl -X POST https://api.loreos.app/v1/account/apps \
> -H "Authorization: Bearer $LOREOS_ACCOUNT_TOKEN" \
> -H "Content-Type: application/json" \
> -d '{ "name": "Local staging", "environment": "sandbox" }'
  1. The agent issues a runtime API key for that app:
$curl -X POST https://api.loreos.app/v1/account/api-keys \
> -H "Authorization: Bearer $LOREOS_ACCOUNT_TOKEN" \
> -H "Content-Type: application/json" \
> -d '{ "app_id": "app_...", "label": "local-server" }'

Use the returned runtime API key as LOREOS_KEY on your server for normal runtime calls:

$curl https://api.loreos.app/v1/me \
> -H "Authorization: Bearer $LOREOS_KEY"

Managing end-user caps

Account tokens can also prepare end-user records and limits for the app they just created. Use this when your product wants per-user metering caps before sending live messages.

$curl -X PUT https://api.loreos.app/v1/account/apps/$APP_ID/external-users/user_123 \
> -H "Authorization: Bearer $LOREOS_ACCOUNT_TOKEN" \
> -H "Content-Type: application/json" \
> -d '{ "display_name": "Test user", "credit_limit": 5.0 }'
$
$curl -X POST https://api.loreos.app/v1/account/apps/$APP_ID/external-users/user_123/budget-policy \
> -H "Authorization: Bearer $LOREOS_ACCOUNT_TOKEN" \
> -H "Content-Type: application/json" \
> -d '{ "limit_credits": 5.0, "resource_type": "all", "enforcement": "hard" }'

Runtime message calls still use the runtime API key. LoreOS resolves external_user_ref inside the app and enforces caps before expensive model work starts.

Scopes

Request the smallest scope set the agent needs:

  • account:workspace:read - inspect workspace, apps, role, and billing status.
  • account:team:write - invite, update, or remove workspace members.
  • account:apps:write - create apps and manage production activation state.
  • account:api_keys:write - issue runtime API keys.
  • account:external_users:write - create, list, update, or delete app end-users.
  • account:caps:write - set app-level or user-level budget policies.
  • account:usage:read - read usage by app and external user.
  • account:billing:write - start billing checkout or portal flows.

Revocation

Account access tokens are short-lived and revocable. When an agent finishes setup, revoke the active token:

$curl -X POST https://api.loreos.app/v1/account/tokens/current/revoke \
> -H "Authorization: Bearer $LOREOS_ACCOUNT_TOKEN"

Revoking an account token does not revoke runtime API keys that were already issued. Rotate runtime API keys separately from the account plane.

Current limitations

  • The account routes are preview routes, so generated SDKs may not include them yet.
  • Device authorization start is public but rate-limited. 429 account_device_rate_limited means the code issuance window was exceeded; reuse an existing account token or wait.
  • 503 account_device_rate_limit_secret_missing means public self-serve device issuance is not configured on that deployment. Retry after the deployment is configured; demo sandbox keys remain available only for short-lived first tests.
  • Billing checkout and portal flows are wired for Stripe, but live paid-plan acceptance is intentionally separate from the Clerk/account-token path.
  • The public demo sandbox route is still the fastest no-login path for a first character reply. Use account tokens when you need persistent apps, API key issuance, team state, or per-user caps.