List connections
/connection
Lists the connections the caller owns plus every connection shared with them, directly, through a team they belong to, or organization-wide. No organization permission widens this: a private connection (no grants) appears only for its owner, whatever permission an org owner or admin holds, and there is no org-wide listing of connections. Statuses are refreshed as they are read, so this is also how a `needs_reauth` connection surfaces. A `pending` row whose sign-in finished but whose redirect never came back is bound shortly after the response, so it may still read `pending` and show as bound one load later. Rows the caller may share (owner or `edit` access) also carry `can_share: true` and a short `access_summary`; page `GET /connection/{id}/share` for the grants themselves.
Query Parameters
Substring match (LIKE "%value%", case-insensitive) on the connection name, the connected account label where present, the connector slug ("slack", "google-drive"), and the connector's catalog label ("Google Drive") — matching the search box's own "Search by name or connector…" placeholder against both spellings a connector can go by. connector_slug below is a different question: an exact-equality filter to only these connectors, not a search. LIKE wildcards are matched literally. Max 200 characters.
Filter by lifecycle status. Any other value is a 400.
pendingactiveneeds_reauthdisconnected
Filter to one or more connectors. Repeat the parameter or send one comma-separated value — both are the same filter. At most 25 values per request; more is a 400.
Filter to connections owned by one user. This narrows what the caller can already see; it is not a second access path, so it never surfaces another member’s private connections. An id that matches nobody returns an empty page rather than a 404.
Response Body
The connector's display data, so a client needs no GET /connector/{slug} per distinct connector. On GET /connection rows and GET /connection/{id} (which adds can_view_connector, available and auth_mode, and always states single_redirect_auth); absent from the command responses, which cannot change a connection's connector.
7 properties
GET /connection/{id} only, remote MCP connectors only, and only when can_view_connector: how the connector signs in, so a screen can say "No sign-in" instead of "API key".
oauth_autooauth_clientcustomnone
False only when the catalog no longer has the connector (Elaichi unpublished or deleted a platform connector): the connection is kept but nothing can work until it returns. On GET /connection/{id} it is true when the connector resolves; on a GET /connection row it is never true, only false or absent. Absent also when the catalog could not answer, so a brief outage never reads as an unpublished connector.
GET /connection/{id} only. Whether GET /connector/{slug} would answer this caller: false for a connector the catalog no longer resolves, without connector:view, and for an org-owned connector nobody shared with them (it 404s). Link to the connector only when true.
Catalog display name; the slug itself when the catalog cannot resolve it.
Logo URL; null when the connector has none.
The connector-row hint of the same name: connecting is most likely a single provider sign-in, so a client reserves a popup inside the Reconnect click. Always stated on GET /connection/{id} (false when can_view_connector is). On a list row it is stated only where the caller could open the connector, and ABSENT otherwise, which reads as unknown, never false.
Present only on a fork (an org-owned connector copied from another): the connector it was forked from. Omitted when the caller has no access to the fork or to a private upstream (naming it would disclose its slug), and when the upstream cannot be read.
Who owner_user_id is. Present on a connection the caller does not own and absent on their own. On every response that returns a connection (list, detail and the command responses), so a transfer names the new owner without a reload. name and email are absent for an owner who has left the organization ("Former member").
4 properties
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.
User id (usr_…) — same value as owner_user_id.
Display name, else the email.
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.
2 properties
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".
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.
The caller's relationship to this connection: owner, or a granted view/use/edit level. A connection the caller neither owns nor holds a grant on is not visible to them at all, whatever organization permission they hold.
Present only when can_share is true. A short summary of who has access; page GET /connection/{id}/share for the grants themselves.
5 properties
viewusenull
At most 5 grantees, broadest first (org, then teams, then members), for a hover preview.
4 properties
userteamorg
viewuse
Display name; null for org grants and for grantees no longer in the org.
Every grant, the org-wide one included.
How the caller reaches this connection, 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 connection 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.
ownerdirectteamorg
Present exactly when access_via is team, absent otherwise. The team the caller reaches this connection through — one of their own teams, never a disclosure about anybody else.
2 properties
Team id (team_…).
Team display name, or null when the team no longer resolves in the directory — the same null contract every resolved grantee name carries.
Present on every list and detail row. Whether the caller may edit this connection's own settings: the owner, or edit access.
Present on every list and detail row. Whether the caller may grant or revoke access to this connection. It matches can_share and is separate from can_manage: an edit grantee whose role omits connection:share can reconfigure or reconnect the connection but cannot change who else has access. Mirrors DELETE /connection/{id}/share/{aclId}.
Whether the caller may share this connection: the owner, edit access, or a team admin on a team-granted one, and connection:share. Computed by the API, so read it rather than re-deriving it from owner_user_id and permissions.
Present on every list and detail row. Whether the caller may transfer or delete this connection: the owner only. Narrower than can_manage, because an edit grant lets someone use and reconfigure a connection, never give it away or destroy it.
Display name for connected_by_user_id (name, else email). Present on every response that returns a connection, commands included. A null label beside a non-null connected_by_user_id means the person has left the organization; show "Former member". Compare the two fields, never one alone: a null id means "not recorded", a null label means "departed".
Who authenticated this account (usr_…): the member whose third-party credential Elaichi holds. Written once at creation and never rewritten. It differs from owner_user_id on purpose: POST /connection/{id}/transfer moves the owner and does not touch the stored credential, so after a transfer these are two different people and only this one should be shown as "Connected by". Null means not recorded, never "nobody": connections created before this field existed are null. Show nothing for a null.
Which connector this account is on.
Connection id (conn_…).
Owning member (usr_…); calls run as this identity. The owner has implicit edit, plus delete and transfer, which no share confers. Move it with POST /connection/{id}/transfer. This is who is accountable for the connection now, which after a transfer is not who authenticated it; see connected_by_user_id.
Identifier of the stored credential Elaichi holds for this connection. Opaque; null until the connect flow completes.
Present only when the caller may see who the connection is shared with: the owner or edit access. A view or use recipient is never told who else it is shared with. Absent (not empty) when the caller may not see it.
8 properties
User id (usr_…) or team id (team_…). Null for a grantee_type: "org" grant.
user and team grants target one grantee_id; org applies to every member of the organization and takes no id.
userteamorg
Grant id (acl_…), the {aclId} that DELETE .../share/{aclId} takes.
Same ladder for every shareable resource, low to high. view — see it exists, read its metadata/config; cannot exercise it. use — view + exercise it, resource-specific: run tools through a connection; execute a toolbox's tools through its bound connections (this DELEGATES — the caller runs through each entry's pinning editor's own authority, not necessarily their own); stamp a new toolbox by copying a template's entries; create connections from a connector. edit — use + change its settings, entries and its own grants.
viewuseedit
The shared resource's id (a connector's slug, for that type).
connectiontoolboxtemplateconnectorautomationcollectiondashboardknowledge_basebundlefile
pending = created but not yet authenticated (open connect_url); active = usable; needs_reauth = the credential expired or was revoked upstream, call reconnect; disconnected = no longer usable. Refreshed when connections are read.
pendingactiveneeds_reauthdisconnected
curl -X GET 'https://api.elaichi.ai/connection' \
-H 'Authorization: Bearer $ELAICHI_API_TOKEN' \
-H 'Content-Type: application/json'const response = await fetch('https://api.elaichi.ai/connection', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + process.env.ELAICHI_API_TOKEN,
'Content-Type': 'application/json',
},
});
const data = await response.json();
console.log(data);import os
import requests
url = "https://api.elaichi.ai/connection"
headers = {
"Authorization": f"Bearer {os.environ['ELAICHI_API_TOKEN']}",
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers)
print(response.json())