---
title: "List connectors"
method: GET
path: "/connector"
tags: ["Connectors"]
---

# List connectors

`GET /connector`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/connector`
- Auth: HTTP bearer

Lists the platform catalog plus this organization's own custom connectors. Every member sees the platform catalog. A custom connector is listed only for its owner and the members it is shared with, and is absent (and `404` by slug) for everyone else, whatever their role; `connector:view` and `connector:manage` widen nothing. Connectors the caller's restrictions block are returned, flagged `restricted` and `restricted_by`, not filtered out. Platform catalog rows omit `can_manage` and carry `can_use: true`; on an org-owned row `can_manage` reflects only an `edit` grant of the caller's own. Cursor-paginated: a page holds `limit` rows whenever that many are visible, `prev_cursor` is always null, and the cursor is opaque and valid only for the `search`, `category` and `custom` values it was returned for (anything else is a `400`). A page can occasionally come back empty with a `next_cursor` when many consecutive connectors are hidden from the caller; keep paging until `next_cursor` is null.

## Query parameters

- `search` string
- `category` string
- `custom` boolean
- `limit` integer
- `cursor` string

## Headers

- `X-Organization-Id` string

## Response `200`

OK

- object
  - `result` object[], required
    - `slug` string: Stable connector key — this is the identifier everywhere, not an id.
    - `label` string
    - `category` string
    - `logo` string, nullable
    - `description` string, nullable
    - `owner` string: Catalog owner. Org-owned values mark this org's custom connectors. Always this string — the owning MEMBER is `owner_member`, a separate field, so a client never has to tell a string from an object.
    - `owner_member` object, nullable: The resolved owning member, the same shape as a toolbox's `owner`. Org-owned rows the caller reaches (ownership or a grant) only: an object when somebody OTHER than the caller owns the connector (just `{ id }` for an owner who has left the org); `null` when the connector has no owner yet (an ownerless connector — see `POST /connector/{slug}/owner`); absent when the caller owns it (`owner_user_id` already says so) or reaches it by nothing but `connector:view`.
      - `id` string: User id (`usr_…`) — same value as `owner_user_id`.
      - `name` string, nullable
      - `email` string, email
      - `avatar_url` string, nullable: The person's picture: their stored profile picture, else a Gravatar URL (`d=404`, 96px) derived from their email (the address itself is not sent), else null. Draw initials when it is null or the image fails to load.
    - `custom` boolean: True for a connector this organization authored or forked.
    - `kind` 'catalog' | 'remote_mcp': `remote_mcp` for an organization's own bring-your-own remote MCP connector (its tools are discovered per connection, not read from the catalog), `catalog` for every other connector. Read it instead of guessing from the slug. On the detail, a remote MCP connector also carries `remote_mcp` (`url`, `auth_mode`, `oauth_registration`, `catalog_owner`, `listed_tool_count`, the number of tools `GET /connector/{slug}/tool` lists to this caller with no filter (turned-off tools included for a caller who can manage the connector), and `support_contact`, the email or https link Elaichi has on file for a connector it publishes, null otherwise) and `auth`. Its `tool_count` is the number of tools that are switched on.
    - `byoa` boolean: True when the connector needs the customer's own OAuth app (bring your own app): a placeholder client id, a real id with a placeholder secret, or a real id with no platform OAuth secret stored for it.
    - `single_redirect_auth` boolean: A hint, not a promise: true when connecting this connector is most likely a provider sign-in with nothing to fill in first — exactly one auth method, and that method can redirect (OAuth). A list row judges the auth methods only; `GET /connector/{slug}` also rules out a method with form fields or a `permissions_text` notice. A client may use it to get a popup window ready inside the click that starts a connect. `direct_connect_url` on the `POST /connection` / reconnect response stays authoritative.
    - `can_fork` boolean: Whether the caller may fork the connector. False for a remote MCP connector (`POST /connector/{slug}/fork` answers `409 connector_not_forkable`), for a connector the caller is restricted from, without `connector:create`, and when the plan does not include custom connectors. On `GET /connector` rows and `GET /connector/{slug}`.
    - `owner_user_id` string: Owning member (`usr_…`). Present only on an org-owned row the caller reaches (ownership or a grant) and that has an owner. An ownerless connector has none until `POST /connector/{slug}/owner` assigns one, and a member browsing with `connector:view` alone is not told whose it is. The owner has implicit `edit`, plus delete and transfer, which no share confers.
    - `can_use` boolean: Whether the caller may create (or re-authenticate) a connection from this connector. That needs the `use` level that `POST /connection` and `POST /connection/{id}/reconnect` enforce (403 `connector_not_shared` otherwise): ownership or a `use`-or-better grant (direct, team or org-wide) on an org-owned connector, and always true on a platform catalog row. This is about sharing and is independent of `restricted`: a connector shared for viewing only is listed but cannot be connected, so leave Connect off rather than show a button that refuses. A connector nobody shared with the caller is not listed.
    - `can_manage` boolean: Present only on org-owned/custom connector rows (omitted for platform catalog rows, which have no sharing). Whether the caller may edit this connector's config: ownership or an `edit` grant of their own. The `connector:manage` permission alone does not imply it, so org owners and admins do not manage a connector nobody shared with them.
    - `can_transfer` boolean: Org-owned rows only. Whether the caller may transfer this connector — ownership, full stop; no `connector:manage` fallback. Mirrors `POST /connector/{slug}/transfer`. False for everyone on an ownerless connector (transfer needs an owner). Not the delete gate — see `can_delete`.
    - `can_delete` boolean: Org-owned rows only. Whether the caller may delete this connector: the owner, and only the owner, so false for everyone on an ownerless connector. Mirrors `DELETE /connector/{slug}`.
    - `can_assign_owner` boolean: Org-owned rows only. Whether the caller may give this ownerless connector an owner: it has no owner row AND the caller holds `connector:manage`. Mirrors `POST /connector/{slug}/owner` naming another member. Independent of the caller's reach, so a manager browsing the catalog can see that a connector needs an owner; it says nothing about who has access.
    - `can_claim` boolean: Org-owned rows only. Whether the caller may make THEMSELVES the owner: `can_assign_owner` AND a real `edit` grant of their own. `connector:manage` alone never makes its holder the owner of a connector nobody shared with them. Mirrors `POST /connector/{slug}/owner` naming the caller.
    - `can_revoke_share` boolean: Org-owned rows only. Whether the caller may grant or revoke access to this connector: `edit` access or ownership, and `connector:share`. This is separate from `can_manage`: an `edit` grantee whose role omits `connector:share` can reconfigure the connector but cannot change who else has access. Mirrors `DELETE /connector/{slug}/share/{aclId}`.
    - `restricted` boolean: True when the caller's restrictions block this whole connector. A blocked connector is LISTED and flagged, never omitted — a picker that only got "no match" could not tell "your admin blocked it" from "that provider does not exist". It still cannot be connected: `POST /connection` and `GET /connector/{slug}/tools` refuse it.
    - `restricted_by` 'role' | 'user' | 'null', nullable: Which precedence layer the winning rule came from, or null when nothing blocks this connector. Adds *which* to `restricted`'s *whether* and nothing else — no rule id, author, reason or coverage. Same field and same meaning as on `GET /connector/{slug}` and on a connection row.
    - `restricted_inherited_from` object, nullable: Set when this connector is restricted for the caller only because the connector it was forked from is. A fork inherits its upstream’s restrictions on purpose (forking a blocked connector is not a bypass), but nothing was set on the fork itself, so this says where the block came from. Null when not restricted, when a rule names this connector directly, or when the upstream could not be traced. Asking for access still targets this connector: approving the fork’s own request opens that fork for that person only (whether the block comes through their role or a rule written about them personally) and the original stays restricted for them; the approved request reads `restriction_lifted: true`. A sibling of `restricted_by`, which stays the precedence layer. Do not derive it yourself from the fork’s upstream.
      - `slug` string, nullable, required: The upstream connector the restriction is inherited from. For API consumers; never render it. Null — together with `label` — when the caller may not be told the upstream (an org-owned upstream they hold no grant on, or one that was deleted): a slug names the connector as surely as its label does.
      - `label` string, nullable, required: The upstream's display name — null, together with `slug`, when the caller may not be told it. The UI then says "a connector this was forked from".
    - `access_via` 'owner' | 'direct' | 'team' | 'org': How the caller reaches this connector, not who else can. `owner`: they own it. `direct`: a grant names them personally. `team`: a grant to a team they belong to (or administer), named in `access_via_team`. `org`: an organization-wide grant. When several sources apply, the broadest wins and the access level plays no part: owner, else `org`, else `team`, else `direct`. A caller with `edit` personally and `view` org-wide reads `org`, because this field says how far the connector reaches, not what the caller may do with it. It describes only the caller's own access, so a `view` or `use` grantee still gets it while the list of other grantees stays hidden. Absent when nothing reaches the caller (for example, the former owner after a transfer of a resource that was never shared); absent never means `org`.
    - `access_via_team` object: Present exactly when `access_via` is `team`, absent otherwise. The team the caller reaches this connector through — one of their own teams, never a disclosure about anybody else.
      - `id` string: Team id (`team_…`).
      - `name` string, nullable: Team display name, or null when the team no longer resolves in the directory — the same null contract every resolved grantee name carries.
  - `next_cursor` string, nullable, required
  - `prev_cursor` string, nullable, required

## 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)
