API
Overview
Base URL, auth model, error shape, rate limits.
TurbineX has a REST API that covers everything the UI does — submit jobs, download output, manage turbine configs, pull results into a notebook. The UI and your scripts talk to the same endpoints; you authenticate with a JWT and get per-org scoping for free.
Base URL
Production API lives at https://api.turbinex.app. The web app reaches the same hosts through a Next.js rewrite (/api/* → https://api.turbinex.app/*), so if you're debugging in the browser you'll see /api/... paths, but scripts should hit the bare hostname.
Authentication
Every request (bar the handful of public endpoints below) needs a Bearer JWT in the Authorization header. Access tokens expire in 15 minutes; refresh tokens in 30 days. See Authentication for the login, refresh, and PAT (personal access token) flows.
Public endpoints
Mounted under /api/public/ — no auth needed, scoped by share token. Used by the read-only Share Space viewer:
GET /api/public/studies/{token}— study header + metadataGET /api/public/studies/{token}/artifacts— list uploaded filesGET /api/public/studies/{token}/artifacts/{id}/download— download a single artifact
Tokens are 64-char URL-safe strings, generated server-side, and only valid while the study's share-link is enabled. Owners toggle / rotate / disable from the Share Space tab on each study.
curl -H "Authorization: Bearer $TURBINEX_TOKEN" \
https://api.turbinex.app/jobsError shape
Every error response is JSON with a detail field:
{
"detail": "Monthly token cap reached: 50,000 tokens. ..."
}Common status codes:
401 Unauthorized— missing / expired token.402 Payment Required— spend cap or token cap hit.403 Forbidden— request was authenticated but not permitted. Common cases: member trying to change org settings, unverified account hitting a verified-only endpoint (custom-turbine create, parametric submit, certification report), or PUT/DELETE on a demo-derived turbine row (clone the demo first).404 Not Found— also returned for private-scope leaks (e.g. a note whose owner's private visibility hides it from you); we deliberately don't distinguish “doesn't exist” from “you can't see it”.409 Conflict— duplicate resource (e.g. turbine name collision in your org).429 Too Many Requests— per-user and per-org rate limits. Response includesRetry-After.
Rate limits
Per-user rate limits depend on plan:
- Free — 30 req/min per user, 60 req/min per org.
- Pro — 300 req/min per user, 600 req/min per org.
- Enterprise — 1,000 req/min per user, 2,000 req/min per org.
The server responds with X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After headers on 429s.
Idempotency
Job submission isn't idempotent by default — submitting the same ZIP twice queues two runs, billed as two runs. If you need dedupe, hash the ZIP client-side and skip the submit when the hash matches a recent job. A server-side idempotency key header is on the roadmap.
Pagination
List endpoints return a PaginatedResponse<T>:
{
"items": [...],
"total": 42,
"page": 1,
"page_size": 20,
"total_pages": 3
}Pass ?page=&page_size= query params. Max page_size varies per endpoint (50–200).
Where to go next
- Authentication — getting a token.
- Jobs — submit, list, cancel, download.
- Results — channels, time-series, statistics.