API Tokens
API tokens give scripts, CI pipelines, and backend services programmatic access to your app with an explicit privilege list. Each token is a JWT signed with your app’s secret and carries exactly the privileges you grant it at creation, nothing more. The signed token string is returned once when the token is created and is never stored or shown again; only the metadata record (name, privileges, expiry, last use) remains readable afterwards.
Tokens come in two scopes:
- App-scoped tokens act across your whole app, with no workspace restriction.
- Workspace-scoped tokens are pinned to a single workspace (called a tenant in the API) and are what you hand to a customer’s integration.
To use an API token against the Bridge API, send it in the x-api-key header. To let your customers mint and manage their own tokens from inside your product, use the SDK-side guide at API tokens and the drop-in token management UI. You can also manage tokens visually in Control Center (the Bridge admin dashboard).
Treat a freshly created token like a password: capture the
tokenfield from the create response immediately and store it in your secrets manager. If it is lost, revoke the record and create a new token.
Authentication
Section titled “Authentication”Three auth models appear on this page, and each endpoint below states which one it uses:
-
App API key (
/account/api-token/workspace*and/account/api-token/app*): authenticate with your app’s API key in thex-api-keyheader. Workspace-scoped endpoints additionally require thex-tenant-idheader to pick the workspace.x-api-key: YOUR_APP_API_KEY x-tenant-id: TENANT_ID (workspace endpoints only) -
User access token (
/account/api-token/me/*): authenticate as a signed-in user withAuthorization: Bearer <USER_ACCESS_TOKEN>(the token your app holds after login, see Authentication). The app is derived from the token’saidclaim, so no app header is needed. Creating and revoking requires theOWNERorADMINrole. -
None (
/account/api-token/introspect): intentionally unauthenticated; the API token being introspected is itself the credential.
The token record
Section titled “The token record”All list and create endpoints return token records with the same shape:
| Field | Type | Description |
|---|---|---|
| id | string | The token record’s ID (used to revoke it) |
| name | string | Human-readable label |
| privileges | string[] | Privilege keys the token carries |
| tenantId | string? | The workspace the token is pinned to; null for app-scoped tokens |
| expireAt | string? | ISO-8601 expiry; null when the token never expires |
| lastUsedAt | string? | ISO-8601 timestamp of the token’s last authenticated use; null if never used |
| createdAt | string? | ISO-8601 creation timestamp |
Workspace-scoped tokens
Section titled “Workspace-scoped tokens”Tokens pinned to a single workspace. These endpoints use app API key auth plus the x-tenant-id header.
Create a workspace token
Section titled “Create a workspace token”Create a token restricted to one workspace. The workspace member identified by tenantUserId must hold the OWNER or ADMIN role in that workspace, otherwise the call returns HTTP 403. If your app configures an allow-list of token privileges (allowedTokenPrivileges), requesting a privilege outside that list also returns HTTP 403.
HTTP Request
Section titled “HTTP Request”POST https://api.thebridge.dev/account/api-token/workspace
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
x-api-key | string | Required | Your app API key |
x-tenant-id | string | Required | ID of the workspace the token is created in |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Human-readable label for the token |
privileges | string[] | Required | Privilege keys the token should carry (e.g. USER_READ) |
expireAt | string | Optional | ISO-8601 expiry timestamp. Omit for a non-expiring token |
tenantUserId | string | Required | ID of the workspace member (must be OWNER or ADMIN) creating this token |
Response HTTP 201
Section titled “Response HTTP 201”{ token, record }. token is the signed JWT, returned only this once; record is the token record.
Request example
curl --request POST 'https://api.thebridge.dev/account/api-token/workspace' \
--header 'x-api-key: YOUR_APP_API_KEY' \
--header 'x-tenant-id: TENANT_ID' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "CI deploy token",
"privileges": ["USER_READ", "TENANT_READ"],
"expireAt": "2027-01-01T00:00:00.000Z",
"tenantUserId": "TENANT_USER_ID"
}'Response example:
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJhcHBJZCI6IjY0YTUuLi4ifQ.k2n8xJ...",
"record": {
"id": "665f1c2a9b3e4d5a6c7b8901",
"name": "CI deploy token",
"privileges": ["USER_READ", "TENANT_READ"],
"tenantId": "650cd8510ccba777cc9623d0",
"expireAt": "2027-01-01T00:00:00.000Z",
"lastUsedAt": null,
"createdAt": "2026-07-07T09:00:00.000Z"
}
}
POST Try it out
https://api.thebridge.dev/account/api-token/workspaceList workspace tokens
Section titled “List workspace tokens”List all token records for one workspace, newest first. Token strings are never included, only metadata.
HTTP Request
Section titled “HTTP Request”GET https://api.thebridge.dev/account/api-token/workspace
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
x-api-key | string | Required | Your app API key |
x-tenant-id | string | Required | ID of the workspace to list tokens for |
Response HTTP 200
Section titled “Response HTTP 200”Array of token records.
Request example
curl --request GET 'https://api.thebridge.dev/account/api-token/workspace' \
--header 'x-api-key: YOUR_APP_API_KEY' \
--header 'x-tenant-id: TENANT_ID'Response example:
[
{
"id": "665f1c2a9b3e4d5a6c7b8901",
"name": "CI deploy token",
"privileges": ["USER_READ", "TENANT_READ"],
"tenantId": "650cd8510ccba777cc9623d0",
"expireAt": "2027-01-01T00:00:00.000Z",
"lastUsedAt": "2026-07-06T18:22:41.000Z",
"createdAt": "2026-07-07T09:00:00.000Z"
}
]
GET Try it out
https://api.thebridge.dev/account/api-token/workspaceRevoke a workspace token
Section titled “Revoke a workspace token”Delete a workspace token record. Revocation is instant: the backing record is checked on every authenticated call, so the JWT stops working immediately even if its own expiry has not passed. Returns HTTP 404 if the token does not exist or belongs to another app.
HTTP Request
Section titled “HTTP Request”DELETE https://api.thebridge.dev/account/api-token/workspace/:TOKEN_ID
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
x-api-key | string | Required | Your app API key |
x-tenant-id | string | Required | ID of the workspace the token belongs to |
Response HTTP 200
Section titled “Response HTTP 200”{ "success": true }
Request example
curl --request DELETE 'https://api.thebridge.dev/account/api-token/workspace/TOKEN_ID' \
--header 'x-api-key: YOUR_APP_API_KEY' \
--header 'x-tenant-id: TENANT_ID'Response example:
{ "success": true }
DELETE Try it out
https://api.thebridge.dev/account/api-token/workspace/:TOKEN_IDApp-scoped tokens
Section titled “App-scoped tokens”Tokens that act across the whole app, with no workspace restriction. These endpoints use app API key auth (no x-tenant-id).
List app tokens
Section titled “List app tokens”List all token records for your app, newest first. This includes workspace-scoped records too (their tenantId is set); app-scoped records have tenantId: null.
HTTP Request
Section titled “HTTP Request”GET https://api.thebridge.dev/account/api-token/app
Response HTTP 200
Section titled “Response HTTP 200”Array of token records.
Request example
curl --request GET 'https://api.thebridge.dev/account/api-token/app' \
--header 'x-api-key: YOUR_APP_API_KEY'Response example:
[
{
"id": "665f1d449b3e4d5a6c7b8944",
"name": "Provisioning service",
"privileges": ["USER_READ", "USER_WRITE", "TENANT_READ"],
"tenantId": null,
"expireAt": null,
"lastUsedAt": "2026-07-07T06:14:02.000Z",
"createdAt": "2026-06-01T12:00:00.000Z"
}
]
GET Try it out
https://api.thebridge.dev/account/api-token/appCreate an app token
Section titled “Create an app token”Create a token that is not restricted to any workspace. Use these for your own backend services and automation.
HTTP Request
Section titled “HTTP Request”POST https://api.thebridge.dev/account/api-token/app
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Human-readable label for the token |
privileges | string[] | Required | Privilege keys the token should carry |
expireAt | string | Optional | ISO-8601 expiry timestamp. Omit for a non-expiring token |
Response HTTP 201
Section titled “Response HTTP 201”{ token, record }. token is the signed JWT, returned only this once; record is the token record with tenantId: null.
Request example
curl --request POST 'https://api.thebridge.dev/account/api-token/app' \
--header 'x-api-key: YOUR_APP_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Provisioning service",
"privileges": ["USER_READ", "USER_WRITE", "TENANT_READ"]
}'Response example:
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJhcHBJZCI6IjY0YTUuLi4ifQ.p9w3aB...",
"record": {
"id": "665f1d449b3e4d5a6c7b8944",
"name": "Provisioning service",
"privileges": ["USER_READ", "USER_WRITE", "TENANT_READ"],
"tenantId": null,
"expireAt": null,
"lastUsedAt": null,
"createdAt": "2026-07-07T09:05:00.000Z"
}
}
POST Try it out
https://api.thebridge.dev/account/api-token/appRevoke an app token
Section titled “Revoke an app token”Delete an app token record. Revocation is instant (see Revoke a workspace token). Returns HTTP 404 if the token does not exist or belongs to another app.
HTTP Request
Section titled “HTTP Request”DELETE https://api.thebridge.dev/account/api-token/app/:TOKEN_ID
Response HTTP 200
Section titled “Response HTTP 200”{ "success": true }
Request example
curl --request DELETE 'https://api.thebridge.dev/account/api-token/app/TOKEN_ID' \
--header 'x-api-key: YOUR_APP_API_KEY'Response example:
{ "success": true }
DELETE Try it out
https://api.thebridge.dev/account/api-token/app/:TOKEN_IDManaging tokens as a signed-in user
Section titled “Managing tokens as a signed-in user”These endpoints power in-product token management (they are what the token management UI calls). They authenticate with the signed-in user’s access token, not the app API key:
Authorization: Bearer <USER_ACCESS_TOKEN>
The app is derived from the access token itself, so no app header is needed. Any authenticated user can list tokens and privileges; creating and revoking requires the OWNER or ADMIN role and returns HTTP 403 otherwise.
List available privileges
Section titled “List available privileges”The privilege keys defined for the app, for building a privilege picker in your token-creation UI.
HTTP Request
Section titled “HTTP Request”GET https://api.thebridge.dev/account/api-token/me/app/available-privileges
Response HTTP 200
Section titled “Response HTTP 200”Array of { key, description } objects.
Request example
curl --request GET 'https://api.thebridge.dev/account/api-token/me/app/available-privileges' \
--header 'Authorization: Bearer USER_ACCESS_TOKEN'Response example:
[
{ "key": "USER_READ", "description": "Read users and roles" },
{ "key": "USER_WRITE", "description": "Create and update users" },
{ "key": "TENANT_READ", "description": "Read workspace data" }
]
List your app’s tokens
Section titled “List your app’s tokens”List all token records for the signed-in user’s app, newest first.
HTTP Request
Section titled “HTTP Request”GET https://api.thebridge.dev/account/api-token/me/app
Response HTTP 200
Section titled “Response HTTP 200”Array of token records.
Request example
curl --request GET 'https://api.thebridge.dev/account/api-token/me/app' \
--header 'Authorization: Bearer USER_ACCESS_TOKEN'Response example:
[
{
"id": "665f1d449b3e4d5a6c7b8944",
"name": "Provisioning service",
"privileges": ["USER_READ", "USER_WRITE"],
"tenantId": null,
"expireAt": null,
"lastUsedAt": "2026-07-07T06:14:02.000Z",
"createdAt": "2026-06-01T12:00:00.000Z"
}
]
Create a token as a user
Section titled “Create a token as a user”Create an app-scoped token on behalf of the signed-in user. The user must hold the OWNER or ADMIN role.
HTTP Request
Section titled “HTTP Request”POST https://api.thebridge.dev/account/api-token/me/app
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Human-readable label for the token |
privileges | string[] | Required | Privilege keys the token should carry (pick from available privileges) |
expireAt | string | Optional | ISO-8601 expiry timestamp. Omit for a non-expiring token |
Response HTTP 201
Section titled “Response HTTP 201”{ token, record }. token is the signed JWT, returned only this once; record is the token record.
Request example
curl --request POST 'https://api.thebridge.dev/account/api-token/me/app' \
--header 'Authorization: Bearer USER_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Reporting script",
"privileges": ["USER_READ"],
"expireAt": "2026-12-31T23:59:59.000Z"
}'Response example:
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJhcHBJZCI6IjY0YTUuLi4ifQ.h7t2mQ...",
"record": {
"id": "665f1f019b3e4d5a6c7b89aa",
"name": "Reporting script",
"privileges": ["USER_READ"],
"tenantId": null,
"expireAt": "2026-12-31T23:59:59.000Z",
"lastUsedAt": null,
"createdAt": "2026-07-07T09:10:00.000Z"
}
}
Revoke a token as a user
Section titled “Revoke a token as a user”Delete a token record on behalf of the signed-in user. The user must hold the OWNER or ADMIN role. Revocation is instant. Returns HTTP 404 if the token does not exist or belongs to another app.
HTTP Request
Section titled “HTTP Request”DELETE https://api.thebridge.dev/account/api-token/me/app/:TOKEN_ID
Response HTTP 200
Section titled “Response HTTP 200”{ "success": true }
Request example
curl --request DELETE 'https://api.thebridge.dev/account/api-token/me/app/TOKEN_ID' \
--header 'Authorization: Bearer USER_ACCESS_TOKEN'Response example:
{ "success": true }
Token introspection
Section titled “Token introspection”Introspect a token
Section titled “Introspect a token”Check whether an API token is active and read its verified claims, in the style of RFC 7662. This is what backend Bridge plugins (for example bridge-nestjs) call when they receive an API token in x-api-key: instead of verifying the signature locally, they ask The Bridge, which re-checks the backing record on every call and therefore reflects revocation instantly.
This endpoint is intentionally unauthenticated: the presented token is itself the credential, and the response only echoes claims already inside that token. Any forged, invalid, expired, or revoked token yields { "active": false } and nothing else. Since only the issuing app’s secret verifies the signature, compare the returned appId against your own app ID before trusting the result.
HTTP Request
Section titled “HTTP Request”POST https://api.thebridge.dev/account/api-token/introspect
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Required | The API token (JWT) to introspect |
Response HTTP 201
Section titled “Response HTTP 201”For an active token:
| Field | Type | Description |
|---|---|---|
| active | boolean | true when the token verifies and its record is live |
| sub | string | The token record’s ID |
| appId | string | The app the token was issued for. Compare against your own app ID |
| tenantId | string? | The workspace the token is pinned to; null for app-scoped tokens |
| type | string | Always api |
| privileges | string[] | Privilege keys the token carries |
| exp | number? | Unix expiry timestamp from the JWT; null for non-expiring tokens |
For anything else the body is exactly { "active": false }.
Request example
curl --request POST 'https://api.thebridge.dev/account/api-token/introspect' \
--header 'Content-Type: application/json' \
--data-raw '{ "token": "eyJhbGciOiJIUzI1NiJ9..." }'Response example (active token):
{
"active": true,
"sub": "665f1c2a9b3e4d5a6c7b8901",
"appId": "64a5f8e2b1c93a0012d45678",
"tenantId": "650cd8510ccba777cc9623d0",
"type": "api",
"privileges": ["USER_READ", "TENANT_READ"],
"exp": 1798761600
}
Response example (inactive token):
{ "active": false }
POST Try it out
https://api.thebridge.dev/account/api-token/introspect