v0.1 (beta)

API

Authentication

Personal access tokens, JWT lifetime, refresh.

Two auth schemes are supported: short-lived JWTs for interactive sessions (the web app), and long-lived API keys for scripts, notebooks, and CI. Use whichever is more convenient — any endpoint accepts either.

API keys (recommended for scripts)

Generate a key from Profile → API → Create key. The full secret is shown once; copy it straight into an env var or a password manager. The short Client IDstays visible in the UI for identification — it's the first 12 characters of the key and is what appears in audit logs and billing breakdowns.

Pass the key via the X-API-Key header:

curl -H "X-API-Key: ofk_your-secret-here" \
     https://api.turbinex.app/jobs

Keys are prefixed with ofk_. Each is scoped to the user that created it, inherits that user's org, and counts against the org's plan limits. Usage per key is visible on the same Profile → API tab.

To revoke: open the key row and click the trash icon. Revocation is immediate — the next request on that key returns 401.

Note: you cannot create new API keys using API key authentication. Issuing keys requires an interactive JWT session.

JWT (interactive / password login)

For scripts that want to behave like a user:

POST https://api.turbinex.app/auth/login
Content-Type: application/json

{"email": "alice@example.com", "password": "..."}

Response:

{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 900
}

Pass the access token as Authorization: Bearer <token>. If MFA is enabled the first call returns {"mfa_required": true}; re-post with an otp_code field containing the 6-digit TOTP (or a recovery code).

Refresh

Access tokens last 15 minutes. Refresh them with:

POST https://api.turbinex.app/auth/token/refresh

{"refresh_token": "..."}

Refresh tokens last 30 days and rotate on every use — the response contains a new refresh_token you should swap in.

When to use which

  • API key — any headless caller. Simpler, no refresh loop, revocable from one place.
  • JWT — anything that needs password + MFA on behalf of a human, or that should expire with a session (e.g. a CLI login flow mirroring the browser).

Social login (SSO)

Google / Microsoft / GitHub flows are handled entirely in the browser:

  1. GET /auth/sso/{provider}/loginreturns a redirect URL to the provider's OAuth consent screen.
  2. After consent the provider redirects to /auth/sso/{provider}/callback with an authorization code.
  3. The callback exchanges the code for a provider token, fetches the userinfo, creates or links the user, and redirects back to the web app with an access token in the URL fragment (not the query string — fragments never hit server logs).

SSO isn't exposed as a scriptable API. If you want to use an SSO-authenticated identity from a script, log in once via the web UI, then create an API key from your profile.

What's in the JWT

Decoded claims:

{
  "sub": "user-uuid",
  "email": "alice@example.com",
  "org_id": "org-uuid",
  "role": "org_member",
  "exp": 1776923453
}

The server doesn't trust the token past signature verification — every request re-loads the user + org from Postgres — so revoking a user (deactivating or soft-deleting them) takes effect on the next request, not just on the next login. The same is true for API keys: flipping a key to inactive blocks the very next call.

Logout

Client-side: throw the tokens away. Server-side JWT revocation (for stolen-token scenarios) is on the roadmap — see Organization & roles for active-sessions mitigations in the meantime. For API keys, use the revoke button on Profile → API.