Authentication
API tokens, the two headers every request needs, and token scopes.
API tokens
Programmatic access uses API tokens with the pa_live_ prefix. Create one
in the app under Workspace Settings → API Tokens, or via the API itself
(POST /v1/user/api-tokens).
The token value is shown once at creation and stored hashed — copy it
immediately and keep it secret. Rotate by regenerating
(POST /v1/user/api-tokens/{id}/regenerate) or by creating a replacement
and revoking the old one.
The two headers
Every authenticated request carries the token; nearly every request also names a workspace:
curl "$API_BASE/v1/pipelines" \
-H "Authorization: Bearer pa_live_..." \
-H "X-Workspace-Id: $WORKSPACE_ID"from predictai import PredictAI
client = PredictAI(token="pa_live_…", workspace_id="ws_…")
data = client.pipelines.get_pipelines()
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…", workspaceId: "ws_…" });
const data = await client.pipelines.getPipelines();
| Header | Purpose | If missing |
|---|---|---|
Authorization: Bearer <token> | Authenticates the caller | 401 authorization_required |
X-Workspace-Id: <workspace id> | Selects the workspace the request operates on | 400 Workspace ID required |
Don't know your workspace ID? List them with
GET /v1/workspace.
Scopes
A token carries a set of scopes shaped <resource>.<action>. Requests
outside the token's scopes are rejected with 403. Grant the minimum your
integration needs:
| Area | Scopes |
|---|---|
| Workspaces | workspaces.read, workspaces.write |
| Goals | goals.read, goals.write |
| Data | data.read, data.write, signals.read, signals.write |
| Discovery | discovery.read, discovery.write |
| Modeling | segments.read, segments.write, models.read, models.write, trainings.read, trainings.run |
| Serving | deployments.read, deployments.write, inferences.read, inferences.create |
New tokens default to workspaces.read, goals.read, models.read,
inferences.create — enough to run forecasts, nothing more.
Regions
Your account and each workspace live in a home region. You don't have to
know which one: point anything at the canonical https://api.predict.ai
and the platform routes you. If a request lands in the wrong region, the
API responds 409 with an error.code of wrong_cell and the correct
base URL in error.details.redirect_api_base_url — retry there:
{
"error": {
"code": "wrong_cell",
"message": "This account/workspace is served by another region. Retry on the indicated host.",
"details": {
"home_cell": "eu-1",
"redirect_api_base_url": "https://eu.api.predict.ai"
}
},
"status": "This account/workspace is served by another region. Retry on the indicated host."
}The official SDKs do this for you: they follow the redirect once, cache the returned base URL, and route every subsequent request (including WebSockets) to your home region. If you're writing a raw HTTP client, treat it the same way — a one-time redirect worth caching. Your exact base URL is also shown next to your API token in the app, if you want to configure it up front.
Unauthenticated endpoints
Three surfaces skip bearer auth: GET /health, GET /version, and
ingestion webhooks, which authenticate the
external caller with a per-source HMAC-SHA256 signature over the raw body
instead.

