---
title: "Get a restriction"
method: GET
path: "/restriction/{id}"
tags: ["Restrictions"]
---

# Get a restriction

`GET /restriction/{id}`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/restriction/{id}`
- Auth: HTTP bearer

Returns one restriction. Requires `restriction:view`.

## Path parameters

- `id` string, required

## Headers

- `X-Organization-Id` string

## Response `200`

OK

- object
  - `id` string: Restriction id (`rstr_…`).
  - `target_type` 'role' | 'user': Whether this rule applies to everyone holding a role, or to one specific member.
  - `target_id` string: Role id (`role_…`) or user id (`usr_…`), matching `target_type`.
  - `mode` 'allow' | 'block': `allow` makes the listed connectors and tools the ONLY ones the target may use; `block` removes exactly the listed ones and leaves everything else reachable. The allowlist engages on the MODE, not on what the rule names: an `allow` rule with empty `connector_slugs` and empty `tools` blocks every connector and every tool for its target. A member is bound by their role's rules and their own `allow`/`block` rules at once; a connector or tool is reachable only when both admit it. `except` no longer appears here: the way to lift a role rule for one member is an approved access grant (`POST /access-request/{id}/resolve`), not a rule you write or read through this endpoint.
  - `connector_slugs` string[]: Whole connectors covered by the rule. A slug here settles every tool on that connector, so it must not also appear as a `tools[].connector_slug`.
  - `tools` object[]: Individual tools covered by the rule, on connectors `connector_slugs` does not already name whole.
    - `connector_slug` string, required: Connector slug — connectors are keyed by slug, not by id.
    - `tool_name` string, required: Exact tool name from `GET /restriction/connector/{slug}/tools`.
    - `tool_label` string: Person-readable phrase for this tool ("create a contact"), generated from `tool_name`. Read-only. Show this instead of the raw id. The connector is deliberately not folded in: it is right beside this as `connector_slug`.
  - `summary` string: One plain sentence saying what this rule does ("Allows botify, plus 2 tools in slack. Everything else is blocked."), so every client says the same thing. Read-only, derived from `mode`, `connector_slugs` and `tools`, never stored. It describes what is enforced: tool entries on a connector already named whole are inert, so they do not appear in it. Connectors are named by slug. Show this rather than composing your own.
  - `created_by` string, nullable: User id (`usr_…`) of the author.
  - `created_by_label` string, nullable: Display name (or email) of the author. `null` while `created_by` is a real id means the author has left the org; show it as "Former member", the same word `GET /audit-log`'s `actor` summary uses. Also `null` when `created_by` itself is.
  - `updated_by` string, nullable: User id (`usr_…`) of whoever wrote the row LAST — the author until somebody else edits it. Null only on a row written before this field existed; the self-target rule reads that as "not you", so such a row constrains its author like anyone else's.
  - `updated_by_label` string, nullable: Display name (or email) for `updated_by`, with the same "Former member" meaning for a null beside a real id. To decide whether somebody other than the author last wrote the row, compare the two ids, never the two labels: two people can share a display name, and both labels are null once both have left.
  - `legacy_override` boolean: True on a member row that still REPLACES its member's role rules — the meaning every member row had before role and member rules combined, kept on the rows whose conversion could not be proven to leave the member's access unchanged (a role allowlist beside member rows with none). While any of a member's rows carries it, no role rule reaches them, including ones added later. Read-only except that `PATCH` may send `false` to clear it on all of that member's rows, which only ever narrows them.
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `target_label` string, nullable: Display name (or email) of a `user` target. Always `null` on a `role` target (look the role up by `target_id` in `GET /role`), and `null` on a stale target whose member has been deleted.
  - `connector_labels` object: Slug to catalog display name for the first 8 connectors the rule enforces (whole connectors first, then tool-only ones), enough for a row's badges and hover text. A slug the catalog could not name (deleted, or the catalog unreachable) is absent: fall back to the slug.
  - `scope_connectors` object: One-row responses only (`GET /restriction/{id}`, `POST /restriction`, `PATCH /restriction/{id}`; never a list row): label and logo for every connector the rule scopes (its whole connectors and the connectors its tools belong to), keyed by slug. At most 1000 connectors plus the connectors of 1000 tools. A slug the catalog cannot resolve reads its slug as `label` and a null `logo`.
  - `can_manage` boolean: Whether the caller may create, edit or delete this row: `restriction:manage`, plus two extra checks the write routes enforce. A user-targeted row additionally needs `restriction:override`, and a row targeting the caller (or a role whose permission set equals theirs exactly) is refused so nobody can free themselves from a restriction. A row showing `can_manage: true` will not 403 on write. Read routes need only `restriction:view`, so this is `false` for a viewer.

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited

---

[API](https://skmtc.dev/elaichi/apis/elaichi-api.md) · [All operations](https://skmtc.dev/elaichi/apis/elaichi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/elaichi/apis/elaichi-api/revisions/b22cfb7b6d15?raw)
