---
title: Identity
path: reference/identity
status: published
---

# Identity Reference

Endpoint reference for the identity cache (partners, tenants, users, groups) mirrored from ScaiKey.

**Base path:** `/v1/identity/`

## Identity cache

ScaiVault keeps a local cache of identity data from ScaiKey for fast policy evaluation. The cache is updated in real time via webhooks from ScaiKey; you can also trigger manual syncs.

## GET /v1/identity/partners

List cached partners.

Query: `status`, `page`, `page_size`.

Response:

```json
{
  "partners": [
    {
      "id": "ptn_abc",
      "name": "Acme Corp",
      "slug": "acme-corp",
      "region": "us-east-1",
      "status": "ACTIVE",
      "last_synced_at": "..."
    }
  ],
  "total": 10
}
```

**Scope:** `identity:read`.

## GET /v1/identity/tenants

List cached tenants.

Query: `partner_id`, `status`, `page`, `page_size`.

**Scope:** `identity:read`.

## GET /v1/identity/tenants/{tenant_id}/users

List users in a tenant.

Query: `status`, `page`, `page_size`, `q` (email/name search).

Response:

```json
{
  "users": [
    {
      "id": "usr_abc",
      "tenant_id": "tnt_xyz",
      "email": "alice@acme.example",
      "display_name": "Alice Smith",
      "status": "ACTIVE",
      "mfa_enabled": true,
      "groups": ["grp_sre", "grp_oncall"],
      "roles": ["tenant_admin"],
      "last_synced_at": "..."
    }
  ],
  "total": 150
}
```

**Scope:** `identity:read`.

## GET /v1/identity/tenants/{tenant_id}/groups

List groups.

**Scope:** `identity:read`.

## GET /v1/identity/groups/{group_id}/members

List members.

Response:

```json
{
  "members": [
    {
      "user_id": "usr_abc",
      "email": "alice@acme.example",
      "membership_type": "DIRECT",
      "added_at": "..."
    }
  ],
  "total": 12
}
```

**Scope:** `identity:read`.

## GET /v1/identity/resolve/{identity_type}/{identity_id}

Resolve an identity from the cache, with group memberships.

Response:

```json
{
  "id": "usr_abc",
  "type": "user",
  "email": "alice@acme.example",
  "tenant_id": "tnt_xyz",
  "status": "ACTIVE",
  "groups": ["grp_sre", "grp_oncall"],
  "roles": ["tenant_admin"]
}
```

Returns `404 identity_not_found` if unknown.

**Scope:** `identity:read`.

## POST /v1/identity/sync

Trigger manual sync from ScaiKey.

Query: `partner_id`, `tenant_id` (optional; omit for full sync).

Response `202 Accepted`: `sync_id`, `status`, `started_at`.

**Scope:** `identity:admin`.

## GET /v1/identity/sync/history

```json
{
  "syncs": [
    {
      "id": 42,
      "sync_type": "FULL",
      "status": "COMPLETED",
      "partners_synced": 5,
      "tenants_synced": 25,
      "users_synced": 1500,
      "groups_synced": 200,
      "duration_ms": 45000,
      "started_at": "...",
      "completed_at": "..."
    }
  ]
}
```

**Scope:** `identity:read`.

## GET /v1/identity/roles

Available admin roles for assignment.

**Scope:** authenticated.

## GET /v1/identity/users/{user_id}/roles

## PUT /v1/identity/users/{user_id}/roles

Body: `{"roles": ["tenant_admin"]}`.

**Auth rules:**
- Only `super_admin` or `partner_admin` can modify roles.
- Only `super_admin` can grant `super_admin`.
- No self-elevation.

## POST /v1/identity/webhooks/scaikey

Webhook receiver for ScaiKey events. ScaiKey itself POSTs here; not called by user code.

Verifies `X-ScaiKey-Signature` and applies the event to the cache.

## Related

- [Multi-tenancy](../core-concepts/multi-tenancy)
- [Authentication](./authentication)
