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/jobsKeys 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:
GET /auth/sso/{provider}/loginreturns a redirect URL to the provider's OAuth consent screen.- After consent the provider redirects to
/auth/sso/{provider}/callbackwith an authorization code. - 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.