---
title: Admin API
path: reference/admin-api
status: published
---

# Admin API

Everything you can manage in ScaiKey is exposed at `/api/v1/admin/...`. Authentication is Bearer JWT; the token must carry an admin role (`super_admin`, `partner_admin`, `tenant_admin`) **or** be a platform `client_credentials` token with `admin:read` and/or `admin:write` scope.

## Authentication

```
Authorization: Bearer <jwt>
```

For interactive admins, this is a user JWT obtained via the admin UI's login flow. For automated integrations, it's a `client_credentials` token from a `GLOBAL` `SERVICE` app whose `allowed_scopes` includes `admin:read` (read endpoints) or `admin:write` (write endpoints).

If you get `403 Platform token requires admin:read or admin:write scope`, your service token's scopes are missing those entries — fix it at the application's `allowed_scopes`, not at the token request. See [Troubleshooting → Platform token 403](/docs/scaikey/troubleshooting/platform-token-403).

## Resources

Every resource follows the standard REST shape: `GET /` (list, paginated), `POST /` (create), `GET /{id}` (read), `PATCH /{id}` (partial update), `DELETE /{id}` (soft delete).

### Partners

```
GET    /api/v1/admin/partners
POST   /api/v1/admin/partners
GET    /api/v1/admin/partners/{id}
PATCH  /api/v1/admin/partners/{id}
DELETE /api/v1/admin/partners/{id}
```

Partner IDs are prefixed `prt_`. Fields include `name`, `slug`, `status`, `contact_email`, and three resource limit columns (`max_tenants`, `max_users_per_tenant`, `max_applications_per_tenant`). Limits are top-level integer fields, not a nested JSON blob.

`super_admin` only.

### Tenants

```
GET    /api/v1/admin/tenants
POST   /api/v1/admin/tenants
GET    /api/v1/admin/tenants/{id}
PATCH  /api/v1/admin/tenants/{id}
DELETE /api/v1/admin/tenants/{id}
```

Tenant IDs are prefixed `tnt_`. PATCH accepts `name`, `slug`, `status`, `contact_email`, `partner_id` (cross-partner transfer), `settings` (JSON), `branding` (JSON).

`super_admin` writes; `partner_admin` and `tenant_admin` read within their scope.

### Users

```
GET    /api/v1/admin/users
POST   /api/v1/admin/users
GET    /api/v1/admin/users/{id}
PATCH  /api/v1/admin/users/{id}
DELETE /api/v1/admin/users/{id}
POST   /api/v1/admin/users/{id}/reset-password
POST   /api/v1/admin/users/{id}/mfa/disable
```

User IDs prefixed `usr_`. Custom attributes (AD-compatible) live in `custom_attributes` JSON. PATCH never carries the password — use `reset-password` for that.

### Groups

```
GET    /api/v1/admin/groups
POST   /api/v1/admin/groups
GET    /api/v1/admin/groups/{id}
PATCH  /api/v1/admin/groups/{id}
DELETE /api/v1/admin/groups/{id}
POST   /api/v1/admin/groups/{id}/members
DELETE /api/v1/admin/groups/{id}/members/{user_id}
POST   /api/v1/admin/groups/{id}/nested
DELETE /api/v1/admin/groups/{id}/nested/{child_group_id}
```

Group IDs prefixed `grp_`. Nesting is fully supported — a group can contain other groups recursively.

### Applications

```
GET    /api/v1/admin/applications
POST   /api/v1/admin/applications
GET    /api/v1/admin/applications/{id}
PATCH  /api/v1/admin/applications/{id}
DELETE /api/v1/admin/applications/{id}
```

App IDs prefixed `app_`. The most-edited fields are `allowed_scopes` (list of permitted scopes), `redirect_uris`, `allowed_origins`, `token_lifetime`, and `token_exchange_allowed`. See [Concepts → Applications](/docs/scaikey/concepts/applications) for the full field set.

### Identity providers

```
GET    /api/v1/admin/identity-providers
POST   /api/v1/admin/identity-providers
PATCH  /api/v1/admin/identity-providers/{id}
DELETE /api/v1/admin/identity-providers/{id}
```

OIDC and SAML IdPs for federation. ID prefix `idp_`.

### MCP agents

```
GET    /api/v1/admin/agents
POST   /api/v1/admin/agents
GET    /api/v1/admin/agents/{id}
PATCH  /api/v1/admin/agents/{id}
DELETE /api/v1/admin/agents/{id}
```

AI agent identities for the MCP integration. ID prefix `agt_`. Carries `allowed_tools` and `allowed_scopes` lists, plus an optional `rate_limit_rpm`.

### Sessions

```
GET    /api/v1/admin/sessions
GET    /api/v1/admin/sessions/{id}
POST   /api/v1/admin/sessions/{id}/revoke
```

Active SSO sessions across the platform. Revoking terminates the session immediately and clears the SSO cookie on next browser hit.

### Audit log

```
GET    /api/v1/admin/audit
GET    /api/v1/admin/audit/{id}
```

Read-only. Every admin write and every authentication event is recorded with actor, action, resource, result, and IP/user-agent metadata.

### Dashboard

```
GET    /api/v1/admin/dashboard/stats
GET    /api/v1/admin/dashboard/activity
```

Aggregate counters and recent activity feed — what the admin UI's home page renders.

## Hierarchical access rules

Most read endpoints accept admins of any tier (filtered to what they're allowed to see). Most write endpoints check a hierarchical access rule:

- `super_admin` — everything.
- `partner_admin` — partners and tenants under their own partner, and any resource within those tenants.
- `tenant_admin` — only their own tenant's resources.

Cross-tier writes (e.g. `tenant_admin` trying to PATCH a `GLOBAL` app) get `403 Access denied`.

## Pagination

List endpoints accept `?page=N` and `?per_page=M` (default 20, max 100). Responses include `pagination: { page, per_page, total, total_pages }`.

## Pydantic schemas

If you're generating types, the live OpenAPI spec is at `$SCAIKEY/openapi.json` on non-production builds. The Pydantic models behind it live in `backend/src/scaikey/schemas/` in the open-source backend repo.
