Skip to main content
All Causeloop API requests are authenticated with a Bearer JWT in the Authorization header. There are two ways to obtain a token:
  • Human users — exchange a Clerk session JWT for a Causeloop Bearer token.
  • Machine-to-machine — create a service account and issue it a long-lived bearer token.

The Clerk exchange flow

Causeloop’s frontend authenticates users through Clerk. Once Clerk issues a session JWT, your client exchanges it for a Causeloop-native token. This is the token you use for all subsequent API calls.

Exchange endpoint

POST /v1/auth/exchange
Content-Type: application/json
Request body
{
  "subject_token": "<clerk_session_jwt>"
}
Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "clp_refresh_...",
  "token_type": "bearer",
  "expires_in": 259200,
  "scope": "issues:read patterns:read ...",
  "workspace_id": "ws_01abc123"
}
FieldDescription
access_tokenHS256 Bearer JWT. Pass in Authorization: Bearer <access_token>.
refresh_tokenUse to obtain a new access token when the current one expires.
token_typeAlways bearer.
expires_inSeconds until the access token expires. Access tokens are valid for 72 hours (259 200 s).
scopeSpace-separated list of scopes granted to this token.
workspace_idThe workspace this token is bound to.
curl -X POST https://api.causeloop.ai/v1/auth/exchange \
  -H "Content-Type: application/json" \
  -d '{"subject_token": "<clerk_session_jwt>"}'

Refreshing a token

When an access token expires, exchange the refresh_token for a new one:
POST /v1/auth/refresh
Content-Type: application/json

{"refresh_token": "clp_refresh_..."}
The response has the same shape as the exchange response, with a fresh access_token and a new refresh_token.
Store refresh tokens in HttpOnly, Secure, SameSite=Strict cookies rather than localStorage to mitigate XSS token theft.

Making authenticated requests

Once you have an access token, include it in every request:
Authorization: Bearer <access_token>
curl https://api.causeloop.ai/v1/issues \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
A missing or invalid token returns 401 Unauthorized:
{
  "code": "unauthorized",
  "message": "Missing or invalid Authorization header",
  "details": {}
}

Service accounts (machine-to-machine)

For automation pipelines, CI/CD, and backend integrations that cannot run a Clerk session, use service accounts. Service accounts have their own long-lived bearer tokens with explicit scopes, and do not require user interaction.
Service account endpoints require workspace:admin scope.

Create a service account

POST /v1/service-accounts
Authorization: Bearer <admin_token>
Content-Type: application/json

{
  "name": "ci-pipeline",
  "scopes": ["issues:read", "issues:write", "patterns:read"]
}
Response (201 Created)
{
  "id": "sa_01abc123",
  "name": "ci-pipeline",
  "scopes": ["issues:read", "issues:write", "patterns:read"],
  "status": "active",
  "workspace_id": "ws_01abc123",
  "created_at": "2024-01-15T10:00:00Z"
}

Issue a token for a service account

POST /v1/service-accounts/{id}/tokens
Authorization: Bearer <admin_token>
Content-Type: application/json

{
  "name": "deploy-2024-01",
  "expires_at": "2025-01-15T10:00:00Z"
}
Response (201 Created)
{
  "id": "sat_01abc456",
  "token": "clp_sa_...",
  "name": "deploy-2024-01",
  "expires_at": "2025-01-15T10:00:00Z"
}
The token value is shown only once at creation time. Store it securely — it cannot be retrieved later. Only a SHA-256 hash is stored by Causeloop.
Use the returned token value as the Authorization: Bearer token in all API calls made by the service account.

Manage service account tokens

OperationEndpoint
List service accountsGET /v1/service-accounts
Get service accountGET /v1/service-accounts/{id}
Delete service accountDELETE /v1/service-accounts/{id}
List tokensGET /v1/service-accounts/{id}/tokens (see token metadata, not the secret)
Revoke a tokenDELETE /v1/service-accounts/{id}/tokens/{tok_id}

Multi-factor authentication (MFA)

Workspace members can enroll TOTP or SMS factors. MFA is managed through:
OperationEndpoint
List enrolled factorsGET /v1/mfa/factors
Enroll a factorPOST /v1/mfa/factors
Verify a factorPOST /v1/mfa/factors/{id}/verify
Remove a factorDELETE /v1/mfa/factors/{id}
When a workspace enforces MFA, users who have not enrolled will receive a 403 Forbidden with code mfa_required.

Single Sign-On (SSO)

Causeloop supports SAML and OIDC SSO connections for enterprise workspaces (Google, Okta, Azure AD, and custom IdPs). SSO flow endpoints
EndpointPurpose
GET /v1/auth/sso/providersList SSO providers configured for the workspace.
GET /v1/auth/sso/authorizeInitiate an SSO flow — returns a redirect_url and state.
GET /v1/auth/sso/callbackOAuth/OIDC callback — Causeloop exchanges the code and issues a session.
SSO connection management (requires admin)
EndpointPurpose
GET /v1/sso/connectionsList configured SSO connections.
POST /v1/sso/connectionsCreate a new SSO connection (SAML or OIDC).
GET /v1/sso/connections/{id}Get connection details.
PATCH /v1/sso/connections/{id}Update a connection.
DELETE /v1/sso/connections/{id}Delete a connection.
POST /v1/sso/connections/{id}/testTest a connection against the IdP.
GET /v1/sso/connections/{id}/metadataDownload SAML SP metadata XML.

SCIM provisioning

Causeloop provides a SCIM 2.0 endpoint for automated user and group provisioning from identity providers like Okta and Azure AD. Base URL: https://api.causeloop.ai/scim/v2/{tenant} Authentication uses a dedicated SCIM bearer token (not a user token). Create and manage SCIM tokens:
EndpointPurpose
GET /v1/scim/tokensList SCIM tokens for the workspace.
POST /v1/scim/tokensCreate a SCIM token.
DELETE /v1/scim/tokens/{id}Revoke a SCIM token.
SCIM resource endpoints
EndpointPurpose
GET /scim/v2/{tenant}/ServiceProviderConfigAdvertise supported SCIM features to the IdP.
GET /scim/v2/{tenant}/UsersList / search users.
POST /scim/v2/{tenant}/UsersProvision a new user.
GET /scim/v2/{tenant}/Users/{id}Get a user.
PUT /scim/v2/{tenant}/Users/{id}Replace a user.
PATCH /scim/v2/{tenant}/Users/{id}Partial update (deactivate, rename).
DELETE /scim/v2/{tenant}/Users/{id}Deprovision a user.
GET /scim/v2/{tenant}/GroupsList groups.
POST /scim/v2/{tenant}/GroupsCreate a group.
PATCH /scim/v2/{tenant}/Groups/{id}Update group membership.
DELETE /scim/v2/{tenant}/Groups/{id}Delete a group.
SCIM tokens are stored as SHA-256 hashes. The plaintext value is returned only at creation.