ScalixScalix Docs
Sign up

Authentication

API keys explained properly: the five key types and their prefixes, project-scoped keys, scopes, expiry and rotation, and end-user app auth

Overview

Every request to api.scalix.world carries a key in the Authorization header:

bash
curl -H "Authorization: Bearer $SCALIX_API_KEY" \
  https://api.scalix.world/v1/functions

Keys are created in the console at Org → API Keys. The full key is shown once, at creation. After that the console only shows its prefix, so store it somewhere real when you create it.

Key types and prefixes

The prefix on a key tells you what it is. There are five:

Console namePrefixMade forScopes
Secret Keyscalix_sk_Server-side apps and SDKsThe scopes you select
Service Accountscalix_sa_CI/CD pipelinesThe scopes you select
Full Access Keyscalix_at_Getting started, trusted automationEvery data-plane scope, fixed
Personal Access Tokenscalix_pat_The CLI and personal toolingThe scopes you select
Publishable Keyscalix_pk_Browser bundles (end-user auth bootstrap)None, by design

Two of these behave differently from the rest, and it is worth knowing why:

  • A Full Access Key (scalix_at_) always carries every data-plane scope. The server enforces this at creation, so the type label always matches what the key can really do. It cannot carry platform scopes (admin:full and similar), and you cannot trim it down. If you want fewer permissions, use a Secret Key.
  • A Publishable Key (scalix_pk_) carries no scopes at all and never can. It exists to identify your project to the public /v1/auth/* routes from client-side code. On any other route the gateway rejects it. Safe to ship in a browser bundle; useless to an attacker who lifts it.

Project-scoped keys

A key is either org-wide or pinned to a single project, chosen at creation. Pin it.

Most of the platform acts within a project: databases, functions, storage, Run services, Computers. A project-scoped key matches that shape, and it keeps the blast radius of a leak to one project instead of your whole organization. A client's production app, for example, should run on its own project with its own key, not share one with everything else you operate.

Two rules that follow from how permissions work:

  • Only Owners and Admins can create org-wide keys. Members with project restrictions must pick a project.
  • A key can never mint a key more powerful than itself. Creating keys is a boundary-checked operation: the new key's scopes must be a subset of what the caller holds, and data-plane keys cannot create keys at all. Key management is for humans (or an owner-authenticated session), not for the keys themselves.

Scopes

There are 64 named scopes. They follow a service:action pattern; the ones you will meet first:

ScopeGrants
database:queryRun SQL against your databases
database:branchCreate and manage database branches
storage:read / storage:writeRead and write objects
functions:deploy / functions:invoke / functions:logsDeploy, call, and inspect functions
services:deploy / services:read / services:logsManage Scalix Run services
compute:deploy / compute:scale / compute:logsContainer workloads
ai:infer / ai:modelsAI inference and the model catalog
kv:read / kv:writeKey-value store
events:publish / events:readPub/Sub
registry:pull / registry:pushContainer registry
search:readScalix Search
metering:readYour own usage data

The console's key form shows the complete list with a description for each. Select the scopes the workload needs and no more; a dozen well-chosen scopes covers most production services.

When a request is refused: a 401 means the key itself was not accepted (wrong, revoked, or expired). A 403 means the key is real but lacks a scope the route requires, or it is a publishable key on a scoped route. If a data-plane call complains about project context, the key is org-wide and the route wants to know which project you mean; a project-scoped key answers that implicitly.

Expiry and rotation

Keys default to a 90-day expiry unless you choose a different period or No expiration at creation. The console's API Keys page shows each key's last-used time. A key showing Never or a stale date is your first candidate for revocation.

Rotation mints a replacement and keeps the old secret working for a grace window (24 hours by default) so deployed services can swap without downtime. Revocation is immediate and permanent. If a key has leaked, revoke it, do not rotate it: rotation's grace window keeps the leaked secret alive.

CLI login

bash
scalix-cloud login

The CLI prompts for a key, validates it against the API, and stores it in the OS keychain on macOS and Windows, or an owner-only (0600) ~/.scalix/token file on Linux. It is never written to ~/.scalix/config.toml.

Any key type that validates works here: a Personal Access Token is the intended fit, but a Secret Key or Full Access Key logs in the same way. You can also pass the key directly: scalix-cloud login scalix_pat_your_key_here.

Environment Variables

The CLI reads these environment variables (the SDKs take the API key as an explicit constructor argument):

VariableDescription
SCALIX_TOKENAPI key the CLI uses for authentication
SCALIX_API_URLAPI endpoint (default: https://api.scalix.world)

App authentication (your end users)

Everything above is about your access to the platform. For signing up and logging in your application's users, use the auth SDK against your project:

typescript
import { ScalixAuthClient } from "@scalix-world/auth";
 
const auth = new ScalixAuthClient({
  url: "https://api.scalix.world",
});
 
// Sign up a new user
const { user, session } = await auth.signUp("user@example.com", "secure-password");
 
// Sign in
const result = await auth.signInWithPassword("user@example.com", "secure-password");
 
// MFA enrollment
const factor = await auth.enrollMfa("totp", "My Phone");

The publishable key (scalix_pk_) is what identifies your project to these routes from the browser. End-user sessions are JWTs scoped to your application; they cannot touch the platform API.