Skip to main content
Send that token as Authorization: Bearer <token> on every other request.

Four kinds of credential

They are not interchangeable, and using the wrong one is the most common integration mistake.
JWT, 8 hours
What POST /api/auth/login and the CLI device flow return. Identifies a person. Carries their role, so an admin’s token opens admin endpoints. This is the one you want for scripts that act on your own behalf.
30 days
Issued alongside the access token, and only ever as an httpOnly cookie — never in a response body, so browser JavaScript cannot read it. POST /api/auth/refresh exchanges it for a new access token. A command-line client re-runs the device flow instead.
30 days, one run
Injected into a training container as STARFORGE_TOKEN. Scoped to a single run and only accepted by /api/ingest/*. A job holds this and nothing else — it never sees your account credentials. See Reporting from training code.
revocable, no expiry
Authorizes application traffic to one model deployment and nothing else. Independent of any login session, so a service keeps working after the person who created it leaves. Revoke it from the console.
Roles are admin and operator (the console labels the latter “Member”). Admin-only endpoints return 403 for an operator token — not 401, which would wrongly suggest the token is bad.

Log in from a browser or a script

Ten attempts per IP per minute. Deployments using OIDC disable this route; check GET /api/auth/config to see which login methods a deployment offers before assuming.

Log in from a machine with no browser

The device flow, RFC 8628. This is what sf login --device-flow uses, and what you want on an SSH session or a build agent.
1

Ask for a code

2

Approve it in a browser

Open verification_uri_complete anywhere you are already signed in, on any device.
3

Poll until it is approved

Returns authorization_pending until somebody approves it, then the access token and expires_in. Poll no faster than every five seconds; twenty polls per minute is the ceiling.

Confirm it worked

Returns your username, role, and quota. A 401 here means the token is absent, malformed, or expired — try logging in again before looking anywhere else.

Handling expiry

An access token lasts eight hours by default (FORGE_JWT_HOURS on the deployment). When one expires, endpoints return 401. Two ways to recover, depending on what you are:
  • A browser session: POST /api/auth/refresh with the refresh cookie.
  • A script or CI job: log in again, or re-run the device flow. Do not cache a token across runs and hope; check GET /api/auth/me and re-authenticate on 401.
POST /api/auth/logout revokes the refresh token and, on deployments with Redis configured, invalidates the access token immediately rather than at expiry.
A token that JavaScript can read is a token an injected script can steal, and a 30-day refresh token is worth far more than an 8-hour access token. Keeping it in an httpOnly cookie means an XSS bug costs a session rather than a month of access. It also means a command-line client cannot use it at all — which is why the device flow exists as a separate path rather than an afterthought.