Authentication
Authenticate to the Blue API with a personal access token and the blue-* request headers.
The Blue API authenticates every request with a personal access token (PAT) — a Token ID and a Secret you generate in the app and send as headers on each request. There are no API keys or OAuth apps to register; a token belongs to a user and inherits that user’s permissions.
The base endpoint is https://api.blue.app/graphql for HTTP requests and wss://api.blue.app/graphql for subscriptions.
Authenticate a request
Send your credentials on every request using these headers:
curl -X POST https://api.blue.app/graphql \
-H "Content-Type: application/json" \
-H "blue-token-id: YOUR_TOKEN_ID" \
-H "blue-token-secret: YOUR_TOKEN_SECRET" \
-H "blue-org-id: YOUR_ORG_ID" \
-d '{"query": "query Me { user { id email fullName } }"}'| Header | Required | Description |
|---|---|---|
blue-token-id | Yes | Your token’s public identifier (the uid). |
blue-token-secret | Yes | The token secret returned once at creation. |
blue-org-id | Most operations | The organization to act in. Accepts the company ID or its slug. |
blue-workspace-id | Some operations | The workspace to scope to. Accepts the project ID or its slug. Required for project-scoped reads and writes (records, lists, custom fields). |
Header names are case-insensitive, so blue-token-id and Blue-Token-Id are equivalent.
blue-org-id and blue-workspace-id both accept either the cuid or the human-readable slug — the slug is the segment you see in the app URL: blue.app/company/{company-slug}/project/{project-slug}/.
These headers were previously named x-bloo-token-id, x-bloo-token-secret, x-bloo-company-id, and x-bloo-project-id (and the older x-company-id / x-project-id). All of those are still accepted, so existing integrations keep working unchanged. Use the blue-* names for anything new.
Create a token
Tokens are created in the app, not via the API. (The createPersonalAccessToken mutation exists but rejects any request made with token headers, so it can only be called from a logged-in browser session.)
- Open Blue and click your profile avatar in the top-right corner.
- Choose API from the profile menu.
- Click Generate a Token.
- Give the token a name, and optionally set an expiration date. Past the expiration date the token stops working (see Expiration).
- Click create. Blue shows you the Token ID and the Secret once.
Token ID and Secret
A token has two parts:
- Token ID — your token’s public identifier (the
uidfield onPersonalAccessToken). It is an unprefixed identifier and is not secret. Send it asblue-token-id. - Secret — the password half of the credential. It is prefixed with
pat_for easy identification (for example,pat_clm4n8qwx000008l0g4oxdqn7). Send it asblue-token-secret.
Blue stores the secret as a bcrypt hash, so it cannot be retrieved after creation — not even by Blue’s team. Copy it somewhere safe the moment it’s shown. If you lose it, delete the token and create a new one. Anyone with both the Token ID and Secret can act as you in Blue, so treat them like a password and never commit them to source control.
Find your Company and Project IDs
Organizations (Organization in the API) are the top-level entity; workspaces (Workspace) live inside them. Both the company and project values you pass in headers can be the ID or the slug, and the slug is visible in the app URL:
blue.app/company/{company-slug}/project/{project-slug}/Expiration
If you set an expiration date when creating a token, the API rejects it once that date has passed — a request with an expired token authenticates as if no credentials were sent, returning UNAUTHENTICATED. Tokens created without an expiration date never expire and remain valid until you delete them.
Revoke a token
Delete a token to revoke it immediately. You can do this from the same API tab in the app, or with the deletePersonalAccessToken mutation — which, like creation, must be called from a logged-in session rather than with token headers.
mutation RevokeToken {
deletePersonalAccessToken(input: { id: "token_123" })
}The mutation returns true on success and throws PERSONAL_ACCESS_TOKEN_NOT_FOUND if no token with that id belongs to you. Deleting a token takes effect on the next request.
Authentication errors
| Code | When |
|---|---|
UNAUTHENTICATED | The Token ID/Secret pair is missing, the secret does not match, or the token has expired. The request is treated as unauthenticated. |
PERSONAL_ACCESS_TOKEN_NOT_FOUND | A token-management mutation (deletePersonalAccessToken) references a token id that doesn’t belong to you. |
FORBIDDEN | You attempt to create or delete a token while authenticating with token headers; these mutations require a logged-in session. |
See Error Codes for the full list.
Authenticating subscriptions
GraphQL subscriptions connect over WebSocket at wss://api.blue.app/graphql and authenticate through connectionParams rather than HTTP headers. Pass the same blue-* headers in connectionParams, or pass a session JWT as Authorization: Bearer <jwt>. See Connect and authenticate for the connection payload and a full example.