# List restrictions

> Source: https://elaichi.ai/docs/api-reference/restrictions/restriction/listrestrictions/

`GET /restriction`

Resource: **Restriction** · API: **Restrictions**

## Response body

- **`result`** _(array<object>)_
  - **`id`** _(string)_
    Restriction id (`rstr_…`).
  - **`target_type`** _(string)_
    Whether this rule applies to everyone holding a role, or to one specific member.
    Allowed: `role`, `user`
  - **`target_id`** _(string)_
    Role id (`role_…`) or user id (`usr_…`), matching `target_type`.
  - **`mode`** _(string)_
    `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.
    Allowed: `allow`, `block`
  - **`connector_slugs`** _(array<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`** _(array<object>)_
    Individual tools covered by the rule, on connectors `connector_slugs` does not already name whole.
    - **`connector_slug`** _(string)_
      Connector slug — connectors are keyed by slug, not by id.
    - **`tool_name`** _(string)_
      Exact tool name from `GET /restriction/connector/{slug}/tools`.
    - **`tool_label`** _(string)_
      Person-readable phrase for this tool ("create a contact"), computed server-side from `tool_name`. Read-only. Render this instead of the raw id, and never rebuild it client-side — the humanizer lives on the server and a second copy drifts from it. 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."), computed server-side so every client says the same thing. Read-only, derived from `mode`/`connector_slugs`/`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 — resolving a display name would be one catalog read per slug per row. Render this rather than composing your own; a client-derived summary is how "an allow rule that names nothing" came to read as "All connectors".
  - **`created_by`** _(string,null)_
    User id (`usr_…`) of the author.
  - **`created_by_label`** _(string,null)_
    Display name (or email) of the author, resolved server-side in the SAME batch as `target_label` — one query for the whole page, so no client ever looks an author up row by row. `null` while `created_by` is a real id means the author has LEFT the org (the resolver joins through the org's own member index), which is a fact about the person, not a lookup that failed — render it as "Former member", the same word `GET /audit-log`'s `actor` summary uses. Also `null` when `created_by` itself is.
  - **`updated_by`** _(string,null)_
    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,null)_
    Display name (or email) for `updated_by`, resolved in the same one batch as `created_by_label`, with the same "Former member" meaning for a null beside a real id. Compare the two IDS, never the two labels, to decide whether somebody other than the author last wrote the row: 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)_
  - **`updated_at`** _(string)_
  - **`target_label`** _(string,null)_
    Display name (or email) of a `user` target, resolved server-side one batch per page so the console never looks members up row by row. Always `null` on a `role` target — role names live in the org DO, which that batch cannot reach, so the console resolves them against the role catalog it already holds — 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) — the ones a row's badges and hover can print, resolved in ONE batch for the whole page, so it is bounded however many connectors the rule holds. Read it before any client-side connector lookup, which only knows the connectors it has already fetched. 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, in one batch. Bounded by the write schema (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 the two guards the write routes themselves 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. Computed by calling those same guard functions, never re-derived, so a row showing `can_manage: true` cannot 403 on write. Read routes need only `restriction:view`, so this is `false` for a viewer.
- **`next_cursor`** _(string,null)_
- **`prev_cursor`** _(string,null)_

## Code examples

### curl

```bash
curl -X GET 'https://api.elaichi.ai/restriction' \
  -H 'Authorization: Bearer $ELAICHI_API_TOKEN' \
  -H 'Content-Type: application/json'
```

### JavaScript

```javascript
const response = await fetch('https://api.elaichi.ai/restriction', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer ' + process.env.ELAICHI_API_TOKEN,
    'Content-Type': 'application/json',
  },
});

const data = await response.json();
console.log(data);
```

### Python

```python
import os
import requests

url = "https://api.elaichi.ai/restriction"
headers = {
    "Authorization": f"Bearer {os.environ['ELAICHI_API_TOKEN']}",
    "Content-Type": "application/json",
}

response = requests.get(url, headers=headers)
print(response.json())
```
