Service Identities
Machine-to-machine principals within an org — distinct from user accounts and AI service accounts. Each identity has its own role, can be issued SPIFFE SVIDs, and appears in the auth event log.
Authentication
Authorization: Bearer <jwt> (admin scope).
Endpoints
GET /api/organizations/:org_uuid/service-identities
List all service identities for an org.Output: ~~~json { "data": [{ "identity_id": "id-uuid", "name": "payment-processor", "description": "Handles billing webhooks", "role_id": 105, "created_at": "2026-05-01T00:00:00Z", "last_auth_at": "2026-05-11T09:55:00Z", "svid_count": 2 }] } ~~~
POST /api/organizations/:org_uuid/service-identities
Create a service identity.Input: ~~~json { "name": "payment-processor", "description": "...", "role_id": 105 } ~~~
Output: ~~~json { "identity_id": "id-uuid", "name": "payment-processor", "role_id": 105, "created_at": "..." } ~~~
GET /api/organizations/:org_uuid/service-identities/:identity_id
Get identity details including active SVIDs.PATCH /api/organizations/:org_uuid/service-identities/:identity_id
Update name, description, or role. Body: partial{ "name"?, "description"?, "role_id"? }.DELETE /api/organizations/:org_uuid/service-identities/:identity_id
Delete identity and revoke all its SVIDs. Returns 204. Irreversible.POST /api/organizations/:org_uuid/service-identities/automation-token
Issue an automation token for a service identity. Used for CI/CD pipelines and automated workflows.Input: ~~~json { "name": "ci-deploy-token", "identity_id": "id-uuid", "expires_in": 86400 } ~~~
Output: ~~~json { "token": "bb_svc_...", "name": "ci-deploy-token", "expires_at": "2026-05-17T00:00:00Z" } ~~~
Endpoint Summary
| Method | Path | Purpose |
|---|---|---|
| GET | /api/organizations/{org}/service-identities | List identities |
| POST | /api/organizations/{org}/service-identities | Create identity |
| GET | /api/organizations/{org}/service-identities/{id} | Get identity details |
| PATCH | /api/organizations/{org}/service-identities/{id} | Update identity |
| DELETE | /api/organizations/{org}/service-identities/{id} | Delete identity |
| POST | /api/organizations/{org}/service-identities/automation-token | Issue automation token |
SDK Examples
Python
~~~python
List service identities
identities = client.list_service_identities("org-uuid")Create a service identity
identity = client.create_service_identity("org-uuid", {"name": "ci-runner"})Issue an automation token
token = client.create_service_identity_automation_token("org-uuid", {"name": "ci-token"})Delete
client.delete_service_identity("org-uuid", "identity-uuid") ~~~Node.js / TypeScript
~~~typescript // List service identities const identities = await client.listServiceIdentities('org-uuid');
// Create a service identity const identity = await client.createServiceIdentity('org-uuid', { name: 'ci-runner' });
// Delete await client.deleteServiceIdentity('org-uuid', 'identity-uuid'); ~~~
Go
~~~go // List service identities identities, err := client.ListServiceIdentities(ctx, "org-uuid")
// Create a service identity identity, err := client.CreateServiceIdentity(ctx, "org-uuid", map[string]any{"name": "ci-runner"})
// Delete err = client.DeleteServiceIdentity(ctx, "org-uuid", "identity-uuid") ~~~
Rust
~~~rust // List service identities let identities = client.list_service_identities("org-uuid").await?;
// Create a service identity let identity = client.create_service_identity("org-uuid", &serde_json::json!({"name": "ci-runner"})).await?;
// Issue an automation token let token = client.create_service_identity_automation_token("org-uuid", &serde_json::json!({"name": "ci-token"})).await?;
// Delete client.delete_service_identity("org-uuid", "identity-uuid").await?; ~~~
Service Identities vs. Service Accounts
| | Service Identity | Service Account |
|---|---|---|
| Auth method | SPIFFE X.509 SVID (mTLS) | Opaque bearer token |
| Use case | Internal microservices, mTLS mesh | AI agents, API integrations |
| API | /service-identities | /service-accounts |
| Appears in auth events | Yes | Yes |
Error Reference
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_role | Unknown role_id |
| 403 | forbidden | Admin scope required |
| 404 | not_found | Identity or org does not exist |
| 409 | name_taken | Name already used within this org |