View as Markdown

Access grants

An access grant gives a user one access point: the tenant, a client, a party, an entity, a cash account or a custody account. The user sees the access point and everything below it; what the user may do there comes from the user's groups. A grant has no role of its own. An admin sees everything and gets no grants. A lens is no access point: you share it on the lens with PUT /v1/lenses/{id}/shares.

The grant

idstring

Stable identifier. A UUID.

user_idstring

The user the grant is for.

subject_kindstring

tenant, client, party, entity, cash_account or custody_account.

subject_idstring or null

The access point. null for the tenant.

statusstring

active, expired or revoked.

originstring

v1 or legacy.

granted_atstring

When the grant was made.

granted_by_user_id, expires_atstring or null

Who made the grant, and until when it holds. expires_at is null without an expiry.

revoked_at, revoked_by_user_id, revoked_reasonstring or null

Set once the grant is revoked. A revoked grant stays readable.

user_rolestring or null

The user's role: admin or user. null when the person is no longer a member of the tenant.

group_idsstring[]

The groups the user is in now.


GET/v1/access-grants

List grants

Needs access:read. An admin gets every grant; anyone else gets their own. Pages in id order. Grants of Aleta staff and API keys are left out, as in GET /v1/users.

user_id, subject_kind, subject_idstring

Filters. user_id and subject_id must be UUIDs and subject_kind one of the six kinds above; anything else is a 400.

include_inactiveboolean

Revoked and expired grants too (the audit view). Default false.

limit, cursorinteger, string

Page size (default 100, at most 1 000) and the previous page's next_cursor.

Response
{
  "data": [
    {
      "id": "019e9b20-4c1d-7a2e-9f30-1b2c3d4e5f60",
      "user_id": "019e9a40-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
      "subject_kind": "custody_account",
      "subject_id": "019dfed3-16d5-7b8c-878c-aca5a2407b9e",
      "status": "active",
      "origin": "v1",
      "granted_at": "2026-10-17T09:00:00.000000Z",
      "granted_by_user_id": "019e9a40-0000-7000-8000-000000000001",
      "expires_at": null,
      "revoked_at": null,
      "revoked_by_user_id": null,
      "revoked_reason": null,
      "user_role": "user",
      "group_ids": ["019e9a11-2b6c-7d3e-8f10-6a2b3c4d5e6f"]
    }
  ],
  "next_cursor": null,
  "limit": 100
}
GET/v1/access-grants/{id}

Get a grant

One grant, also a revoked or expired one. 404 for a grant you may not see.


POST/v1/access-grants

Grant access

Only an admin grants access: a person, or an API key an admin owns (Aleta's fleet key too); the token needs access:write. 201 with the new grant, 200 with the active grant the user already holds on the access point. Takes ?dry_run=true and Idempotency-Key (see Writes) and is logged once.

user_idstring

A user of the tenant. 400 for an admin, Aleta staff, an API key or anyone not in the tenant.

subject_kindstring

One of the six kinds. 400 for lens.

subject_idstring

Left out for the tenant. 404 when the access point does not exist or you cannot see it.

expires_atstring

Optional: YYYY-MM-DD or an RFC 3339 timestamp in the future.

Unknown fields are a 400, role and include_sub_clients too. A second grant on the same access point with another expires_at is a 409 conflict; revoke the first.

cURL
curl -X POST https://api.aleta.ai/v1/access-grants \
  -H "Authorization: Bearer {access_token}" \
  -H "Idempotency-Key: {uuid}" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "019e9a40-1a2b-7c3d-8e4f-5a6b7c8d9e0f", "subject_kind": "custody_account", "subject_id": "019dfed3-16d5-7b8c-878c-aca5a2407b9e"}'
DELETE/v1/access-grants/{id}

Revoke a grant

Only an admin; the token needs access:write. 204, also for a grant that is revoked already. ?reason= is kept as revoked_reason; without it the reason is revoked via api-public. Takes ?dry_run=true and Idempotency-Key. The grant stays readable. 404 for a grant you may not see, a grant of Aleta staff or an API key (which the list leaves out) included, 409 legacy_managed for a grant from the legacy platform before your move.