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 admin role (dashboard / MCP use), OR
  • an API key carrying the matching scope — users:read for list/get, users:write for 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 cursor
  • search — Search by email or name
  • role — 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. roles defaults 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 invalid email.
  • 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 agent
  • userId — Filter by user
  • statusactive, 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 }
}