Authentication

Get a key, then send it on every request.

LoreOS has three credential types you will see during setup:

  • Runtime API key (ck_...) — the server-side app key for public runtime /v1/* calls such as characters, sessions, messages, imports, delivery, images, and usage.
  • Account access token (lat_...) — a scoped, revocable, expiring setup credential for /v1/account/* only (the device-flow response returns its expires_at; default lifetime is 30 days). Use it to create apps, issue runtime keys, manage caps, and inspect account usage.
  • Demo sandbox key — no signup, short-lived, and capped. Use it for local copy-paste testing and coding-agent quickstarts.

Clerk’s own Account API keys (ak_...) are not LoreOS keys. Do not use Clerk’s Account / API Keys / Add new key screen for LoreOS runtime calls; those keys are rejected by api.loreos.app.

No-key testing (demo sandbox key)

The demo sandbox key is the no-key path. POST /v1/demo/sandbox-key takes no auth and, when public issuance is enabled, returns a short-lived, capped sandbox key you can use to run the real quickstart locally:

$export LOREOS_KEY="$(curl -sS -X POST https://api.loreos.app/v1/demo/sandbox-key \
> | jq -r '.data.api_key')"
$export LOREOS_BASE="https://api.loreos.app"

Demo keys are short-lived and capped. The exact caps (defaults shown; an operator can tune them, but these are the deployed values):

  • one sandbox app — the key is bound to a fresh isolated sandbox tenant + app;
  • five characters (POST /v1/characters past the fifth → 403 demo_quota_exceeded);
  • fifteen sessions (past the fifteenth → 403 demo_quota_exceeded);
  • 150 user messages total (the 151st → 403 demo_quota_exceeded);
  • 2,000 characters per message (longer → 413 demo_input_too_large);
  • no image generation — image probes and inventory generation are blocked (403 demo_key_surface_disabled), and the key’s hard credit cap blocks metered work before any provider call regardless;
  • no managed Telegram and no webhook delivery (403 demo_key_surface_disabled);
  • no budget changes, no app creation, and no extra key issuance (403 demo_key_surface_disabled);
  • auto-expires (~24 hours) — every demo key carries an expiry and stops working after it (403 api_key_expired).

Demo keys are designed for local testing only. Do not deploy a demo key as production auth because it expires automatically and intentionally blocks product surfaces such as images, Telegram, webhooks, and additional key issuance.

Issuance is feature-flagged and rate-limited. This route is gated behind abuse controls and may be paused. Handle these responses:

  • 429 demo_sandbox_rate_limited — issuance rate limit reached. Issuance is capped per client (by default a few keys per IP and per fingerprint within a rolling ~1-hour window); the fix field tells you roughly how long to wait. Back off and retry after the window — do not loop-mint demo keys.
  • 503 demo_sandbox_disabled — public issuance is paused (maintenance or abuse controls). This is not transient from your side; use a persistent runtime key from self-serve account access, the console, or preview invite provisioning.

We do not publish a shared public LOREOS_KEY because LoreOS keys can create state and trigger metered model work.

The demo fits a real multi-turn try — five characters, 150 messages, and a day-long TTL are enough to feel reply latency, the async event log (via polling), and reply quality across a few conversations. But for image generation, webhook/Telegram delivery, or a repeated eval loop, use a persistent staging key. A demo key can’t generate images or use managed delivery, and re-minting one per run trips the issuance 429. Staging keys are issued through self-serve account access or preview provisioning; reuse one server-side instead of minting demo keys in a loop. See Staging and evaluation.

Self-serve account access

For persistent apps, use Self-serve access when it is enabled for your workspace. The high-level contract is:

  1. A coding agent calls POST /v1/account/device/start.
  2. A human opens the returned verification_uri, signs in with Clerk/Google, reviews the requested account scopes, and approves the code.
  3. The agent exchanges device_code with POST /v1/account/device/token and receives a short-lived lat_... account access token.
  4. The agent uses that account token only on /v1/account/* routes to create an app, issue a runtime API key, manage end-user caps, and inspect usage.
  5. Your backend uses the issued ck_... runtime API key on public runtime /v1/* routes.

Do not give an agent Google credentials, Clerk credentials, browser cookies, or a human session token. The agent only needs the LoreOS account access token after a human approval. Device-code issuance is rate-limited; handle 429 account_device_rate_limited by waiting or reusing an existing account token, not by looping.

Use your key

Send the key as a Bearer token on every request, against the base URL https://api.loreos.app:

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

GET /v1/me returns the app your runtime key resolves to — the quickest way to confirm that a demo, invite, or self-serve-issued app key works before you build anything else.

If GET /v1/me returns clerk_account_api_key_not_loreos_key, you pasted a Clerk ak_... key. Go back to the LoreOS console and issue a Runtime API Key. If it returns account_token_used_as_runtime_key, you pasted a lat_... account token; use it only for /v1/account/*, then issue a ck_... runtime key.

Keep keys safe

  • Treat keys like passwords — keep them server-side. Never ship a key in a browser or mobile app.
  • Each key is scoped to a single app; everything you create is isolated to that app.
  • Need to rotate a compromised key? Use the console Runtime API Keys panel or call POST /v1/account/apps/{app_id}/api-keys/{prefix}/rotate with an account token. Use POST /v1/account/apps/{app_id}/api-keys/{prefix}/revoke to immediately disable an old prefix.