Authentication
How X-API-Key binds to organization and instance, and why /v2 has no cp-* headers.
Every Nora /v2 endpoint authenticates with a single header: X-API-Key.
No bearer tokens, no OAuth, no cookies, no separate org or instance
headers. The key is the whole credential — the backend derives
everything else from it.
The one header
X-API-Key: sk_live_...That's it. You'll never send an org-scoping header, an instance-
scoping header, or a bearer token alongside it. /v2 has no
legacy cp-* scoping headers — if a snippet you're porting from an
older /cp integration shows any of them, drop them — /v2 ignores
them and scopes only by the key.
How a key binds
Every key encodes a tuple: (organization, instance). When Nora receives a request, it looks up the key and resolves that tuple on the server. There's no way to "call a different org with the same key" — every query the backend runs is scoped by whatever org and instance the key maps to.
Concretely: if you need to call sandbox and production, that's
two keys. If you need to call two different organizations, that's two
keys. Keys are not portable.
Sandbox vs production
| Environment | Base URL | Key prefix |
|---|---|---|
| Sandbox | https://sandbox.api.nora.finance | sk_test_ |
| Production | https://api.nora.finance | sk_live_ |
The prefix is informational — the authoritative binding is in the
server-side lookup. Pointing a sandbox key at api.nora.finance, or a
production key at sandbox.api.nora.finance, always returns a 403
(API key targets sandbox but this runtime serves production). There is
no cross-environment call. A 403 with IP not present on allowlist of this API key means the request came from an address outside the key's
allowlist, which is enforced fail-closed by default. Add at least one
entry before your first call: in production a key with no allowlist
entries is rejected with that same 403.
Rotation
There is no in-place rotate endpoint. The rotation pattern is:
- Create a new key in the dashboard (give it a dated name, e.g.
backend-2026-04). - Swap the secret into your config (env var, secret manager, etc.).
- Deploy and verify traffic flows cleanly on the new key.
- Revoke the old key.
Revoked keys return 401 with code: "INVALID_API_KEY" and
message: "API key is not active"; a never-valid key has the same code
and message: "Invalid API key"; an expired key has
code: "API_KEY_EXPIRED". Branch on message for the first two.
Gotchas
- Plaintext is shown once. The secret is displayed at create time; Nora never stores or re-displays it. Write it to your secret manager before you close the modal.
- Keys are instance-scoped. One key cannot span sandbox and production, even within the same org. Don't try.
- Never embed keys in client-side code.
X-API-Keyis a server- side credential. If it ends up in a browser bundle, mobile app, or public repo, treat it as compromised and rotate immediately. - No
cp-*headers. If you're migrating from a/cpintegration, strip every legacy scoping header from your request code —/v2doesn't read them.
See also
- Authentication (getting started) — the action-oriented "set up your first key" walkthrough
- Dashboard → API keys — UI for creating, listing, and revoking keys
- Error handling — the
401responses you'll see