Authentication
Bearer API keys, scopes, test vs live mode, and 401 auth discovery.
Norano's API uses scoped, revocable API keys, fully decoupled from the browser (Clerk) session. Send the key as a bearer token on every request:
Authorization: Bearer norano_sk_live_…Key format
norano_sk_live_<rand>— a live secret key.norano_sk_test_<rand>— a test-mode secret key (see below).
prefix + last4 (e.g. norano_sk_live_…a1b2).Scopes (least privilege)
A key carries only the scopes it needs. The gateway and the MCP server enforce them per route/tool — a read-only key literally cannot mutate or spend.
| Scope | Grants |
|---|---|
projects:read / projects:write | read / create projects |
plans:read / plans:write | read / upload + parse plans |
visualizations:write | generate visualizations |
tours:write | generate tours |
assets:read | read assets + signed URLs |
jobs:read | read job status |
webhooks:read / webhooks:write | read / manage webhook endpoints + delivery log |
usage:read | read per-key usage |
A read-only key holds only the *:read scopes + jobs:read.
Test mode
norano_sk_test_ keys exercise the full contract — job lifecycle, signed asset URLs, and signed webhooks — but the worker short-circuits paid providers and returns fixture assets. Test jobs transition queued → running → succeeded on a timer with cost_usd_cents = 0. Test and live data are isolated: a live key reading a test resource gets 403 test_mode_resource_in_live. Rehearse end to end at zero spend before your first real generation.
Discovery on 401
Unauthenticated requests get a 401 with the actionable error envelope (see errors) and a WWW-Authenticate header. The server also serves /.well-known/oauth-protected-resource, so OAuth-capable hosts can auto-discover the auth scheme. API keys are Phase 1; OAuth 2.1 is the additive forward path and keys keep working.
Safety for autonomous spenders
dry_run—POST /api/v1/visualizations { …, "dry_run": true }returns anestimated_cost_usd_centswith no enqueue and no spend.- Per-key spend caps — a key can carry
monthly_cap_usd_cents/total_cap_usd_cents; exceeding it returns402 budget_exceeded.