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"
}
| Field | Description |
|---|
access_token | HS256 Bearer JWT. Pass in Authorization: Bearer <access_token>. |
refresh_token | Use to obtain a new access token when the current one expires. |
token_type | Always bearer. |
expires_in | Seconds until the access token expires. Access tokens are valid for 72 hours (259 200 s). |
scope | Space-separated list of scopes granted to this token. |
workspace_id | The 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
| Operation | Endpoint |
|---|
| List service accounts | GET /v1/service-accounts |
| Get service account | GET /v1/service-accounts/{id} |
| Delete service account | DELETE /v1/service-accounts/{id} |
| List tokens | GET /v1/service-accounts/{id}/tokens (see token metadata, not the secret) |
| Revoke a token | DELETE /v1/service-accounts/{id}/tokens/{tok_id} |
Multi-factor authentication (MFA)
Workspace members can enroll TOTP or SMS factors. MFA is managed through:
| Operation | Endpoint |
|---|
| List enrolled factors | GET /v1/mfa/factors |
| Enroll a factor | POST /v1/mfa/factors |
| Verify a factor | POST /v1/mfa/factors/{id}/verify |
| Remove a factor | DELETE /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
| Endpoint | Purpose |
|---|
GET /v1/auth/sso/providers | List SSO providers configured for the workspace. |
GET /v1/auth/sso/authorize | Initiate an SSO flow — returns a redirect_url and state. |
GET /v1/auth/sso/callback | OAuth/OIDC callback — Causeloop exchanges the code and issues a session. |
SSO connection management (requires admin)
| Endpoint | Purpose |
|---|
GET /v1/sso/connections | List configured SSO connections. |
POST /v1/sso/connections | Create 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}/test | Test a connection against the IdP. |
GET /v1/sso/connections/{id}/metadata | Download 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:
| Endpoint | Purpose |
|---|
GET /v1/scim/tokens | List SCIM tokens for the workspace. |
POST /v1/scim/tokens | Create a SCIM token. |
DELETE /v1/scim/tokens/{id} | Revoke a SCIM token. |
SCIM resource endpoints
| Endpoint | Purpose |
|---|
GET /scim/v2/{tenant}/ServiceProviderConfig | Advertise supported SCIM features to the IdP. |
GET /scim/v2/{tenant}/Users | List / search users. |
POST /scim/v2/{tenant}/Users | Provision 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}/Groups | List groups. |
POST /scim/v2/{tenant}/Groups | Create 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.