Authentication
Every WebSocket connection is authenticated via either an API key or an OIDC id_token, sent in the first JSON message. REST endpoints (/jobs/*) accept the same two credential types in a single Authorization: Bearer header — see Downloads.
First-message handshake
Section titled “First-message handshake”The very first message you send on a new connection must be a compile.start message containing your credential — api_key or oidc_token, not both:
{ "type": "compile.start", "api_key": "pk_live_...", "entry": "src/main.ts", "release": true}If the key is valid, the server proceeds without sending an explicit acknowledgement — you will receive compile.queued when the job is enqueued.
If the credential is invalid, missing, or the first message is not compile.start, the server sends an auth.error message and closes the connection.
auth.error message
Section titled “auth.error message”{ "type": "auth.error", "message": "human-readable description", "code": "INVALID_KEY"}| Code | Cause |
|---|---|
MISSING_KEY | Neither api_key nor oidc_token was present on the first message |
INVALID_KEY | Key does not exist in the system |
KEY_EXPIRED | Key has passed its configured expiry date |
KEY_REVOKED | Key was manually revoked |
MISSING_ACCOUNT | oidc_token was sent without account_id and/or org_id |
INVALID_TOKEN | oidc_token failed signature/issuer/audience verification, or is missing a required claim |
REF_NOT_PROTECTED | oidc_token’s branch/tag isn’t a GitLab protected ref (see below) |
NOT_CONNECTED | No connection made by account_id matches oidc_token’s project/ref |
CREDENTIAL_REVOKED | The connection matching account_id + oidc_token’s project/ref was revoked from the dashboard |
ORG_MISMATCH | The matching connection bills to a different org than org_id claimed |
Key format
Section titled “Key format”Pure API keys start with pk_live_ for production keys and pk_test_ for test keys (test keys are for internal use). The full value is 40–60 characters.
OIDC authentication (GitLab CI)
Section titled “OIDC authentication (GitLab CI)”Instead of storing an API key as a CI secret, a GitLab pipeline can authenticate with a short-lived id_token GitLab itself mints per-job — no credential is stored anywhere, on either side.
Setup (once per project/branch): on the dashboard’s Integrations page, add a GitLab connection for the project path and branch you want to authorize. GitLab only stamps ref_protected: true onto an id_token for a protected branch or tag, and Pure requires that — so the branch you connect must be protected in GitLab’s own settings first. The page shows two IDs next to the connection once it’s created: your account ID (a user id) and the org ID it bills to — copy both, you’ll need them in the next step.
In .gitlab-ci.yml:
compile: id_tokens: PURE_ID_TOKEN: aud: https://api.pure.dev script: - curl -fsSL https://apt.pure.dev/install.sh | sh - pure build src/main.ts \ --oidc-token "$PURE_ID_TOKEN" --account <your-account-id> --org <your-org-id>--oidc-token (or the $PURE_OIDC_TOKEN environment variable, which the CLI checks automatically — so passing the id_token as an env var works too, no flag needed) takes precedence over any stored/PURE_API_KEY credential when set. --account/$PURE_ACCOUNT_ID and --org/$PURE_ORG_ID are required whenever an oidc token is used — an id_token alone doesn’t identify a single connection, since the same GitLab project/branch can be connected by more than one person, billing to more than one org (see below). Neither value is a secret — safe to hardcode directly in .gitlab-ci.yml, or set as a plain (unmasked) CI/CD variable.
What Pure checks, in order:
account_idandorg_idwere both provided — rejected outright (MISSING_ACCOUNT) before any token verification if either is missing.- The token verifies against GitLab’s own JWKS (
https://gitlab.com/oauth/discovery/keys), with the expected issuer (https://gitlab.com) and audience (https://api.pure.dev). ref_protectedistrue— an id_token from an unprotected branch is rejected outright, so a random merge-request branch can never authenticate as a connected project.- The token’s
project_path+ref, together withaccount_id, match an active (non-revoked) connection made by that user. A revoked connection behaves like a revoked API key: recognized, but rejected (CREDENTIAL_REVOKED). - That connection’s own org matches
org_id— a mismatch is rejected (ORG_MISMATCH) rather than silently billing wherever the connection happens to point.
There’s no ownership check on which GitLab projects a person may connect — connecting some/project doesn’t require proving you control it, the same way an AWS IAM role trust policy doesn’t require the trusting account to prove anything about the trusted one. Any number of different people, in the same org or different orgs, may independently connect the exact same project/ref; each such connection is authenticated separately by its own account_id. Only one connection per (your user, that exact project/ref) pair is allowed — connecting it again fails until you revoke the existing one.
Security
Section titled “Security”- Send the credential only in the first
compile.startmessage. Do not include it in subsequent messages on the same connection. - Never log the
compile.startmessage — it contains the raw key or token. - Use environment variables or a secrets manager to store an API key. Do not hardcode it. GitLab OIDC avoids this entirely — there’s no long-lived secret to store or leak.
- See API Keys for key rotation and revocation.