Admin Endpoints
Platform administration — stats, user management, and session oversight.
Authentication
/api/v1/admin/stats and /api/v1/admin/sessions endpoints require a Bulwark-issued JWT with the admin role.
/api/v1/admin/users and /api/v1/admin/users/{id} endpoints accept either:
- a JWT with the
adminrole (dashboard / MCP use), OR - an API key carrying the matching scope —
users:readfor list/get,users:writefor create/update/delete.
API-key auth is the path backend services should use (e.g. auto-creating users from an invitation-accept flow on a consumer app). Send the key as Authorization: Bearer bwk_live_... plus X-Bulwark-Tenant: <workspace-id>.
Keys are created + scoped via POST /api/v1/api-keys or the admin dashboard's picker.
Platform Stats
GET /api/v1/admin/stats
Headers
Authorization: Bearer <adminToken>X-Bulwark-Tenant: <tenant-id>X-Bulwark-App-Id: <app-id>— Optional. Filters results to a specific application.
Response 200
{
"data": {
"users": {
"total": 1240,
"active30d": 892,
"newThisMonth": 143
},
"agents": {
"total": 78,
"active": 64,
"revoked": 14
},
"sessions": {
"active": 203,
"completedToday": 1842
},
"apiCalls": {
"today": 48920,
"thisMonth": 1203840
}
}
}
List Users
GET /api/v1/admin/users
Query Parameters
limit— Results per page (default: 20)cursor— Pagination cursorsearch— Search by email or namerole— Filter by role (user,admin)
Response 200
{
"data": [
{
"id": "usr_01j...",
"email": "[email protected]",
"name": "Jane Doe",
"role": "user",
"status": "active",
"createdAt": "2026-01-15T00:00:00Z",
"lastLoginAt": "2026-03-17T22:00:00Z"
}
],
"pagination": { "cursor": "...", "hasMore": true }
}
Get User
GET /api/v1/admin/users/{userId}
Response 200
{
"data": {
"id": "usr_01j...",
"email": "[email protected]",
"name": "Jane Doe",
"role": "user",
"status": "active",
"agents": ["agent_01j..."],
"createdAt": "2026-01-15T00:00:00Z"
}
}
Create User
POST /api/v1/admin/users
Creates a user in the workspace's user pool. Intended for programmatic provisioning from a consumer app — e.g. auto-creating a Bulwark user the moment an invitation is accepted, so the invitee doesn't have to complete a separate signup.
Auth
Requires users:write scope (for API key) or admin role (for JWT).
Body
{
"email": "[email protected]",
"password": "optional-initial-password",
"display_name": "New User",
"email_verified": true,
"roles": ["user"]
}
email(required) — must be unique within the workspace user pool.password(optional) — if omitted, the user has no login credential and must complete a password-reset (or be provisioned a WebAuthn / passkey credential) before they can sign in.display_name,email_verified,roles— optional.rolesdefaults to["user"].
Response 201
Returns the full user detail — the caller can map the returned id to their own user record.
{
"id": "usr_01j...",
"tenant_id": "019d...",
"email": "[email protected]",
"email_verified": true,
"display_name": "New User",
"status": "active",
"roles": ["user"],
"created_at": "2026-04-16T16:00:00Z",
"updated_at": "2026-04-16T16:00:00Z"
}
Errors
400— missing or invalidemail.409— email already exists in the workspace user pool.401/403— authentication or scope/role check failed.
Update User Role
PATCH /api/v1/admin/users/{userId}
Body
{
"role": "admin"
}
Response 200
{
"data": {
"id": "usr_01j...",
"role": "admin",
"updatedAt": "2026-03-18T00:00:00Z"
}
}
Suspend User
POST /api/v1/admin/users/{userId}/suspend
Suspends the user account and invalidates all tokens.
Response 200
{
"data": {
"id": "usr_01j...",
"status": "suspended",
"suspendedAt": "2026-03-18T00:00:00Z"
}
}
List All Sessions
GET /api/v1/admin/sessions
Query Parameters
agentId— Filter by agentuserId— Filter by userstatus—active,completed,expired
Response 200
{
"data": [
{
"sessionId": "sess_01j...",
"agentId": "agent_01j...",
"userId": "usr_01j...",
"status": "active",
"createdAt": "2026-03-18T13:00:00Z"
}
],
"pagination": { "cursor": "...", "hasMore": false }
}