---
title: "Create a toolbox, or stamp one from a template"
method: POST
path: "/toolbox"
tags: ["Toolboxes"]
---

# Create a toolbox, or stamp one from a template

`POST /toolbox`

## Request

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

Creates a toolbox. Requires `toolbox:create`. There are two ways to build one, and they combine. Pass `template_id` to stamp it: the template's entries are copied once, at creation time (never a live link), and you need `use` access to the template. With `connection_map` (connector_slug -> connection_id), each stamped proxy entry's connector is filled from one of the caller's own usable connections, and the caller becomes that entry's delegator; a connector `connection_map` does not name is left `connection_id: null` ("needs connection") rather than rejected. And/or pass `entries` for hand-written ones beyond whatever stamping copied, validated the way `PATCH /toolbox/{id}` validates them. `name` defaults to the template's name when stamping and is otherwise required. `shares` grants access at creation time and additionally needs `toolbox:share`. Sharing delegates (the grantee runs tools on the sharer's own connections), which is what the response's `delegation` summary discloses. It is always present, not only when `shares` was sent, so it can be read before the first grant.

## Headers

- `X-Organization-Id` string

## Request body

- object
  - `name` string: Required unless template_id is set, where it defaults to the template's own name.
  - `description` string, nullable
  - `template_id` string: Template id (`tpl_…`) to stamp from. Requires `use` access to it.
  - `connection_map` object: connector_slug -> connection_id (`conn_…`), filling stamped proxy entries. Ignored when template_id is absent.
  - `entries` object[]
    - `type` 'proxy' | 'synthetic': Defaults to `proxy`.
    - `synthetic_tool_id` string, nullable: Required for `synthetic` entries (`syn_…`).
    - `connector_slug` string, nullable: Connector slug — connectors are keyed by slug, not by id.
    - `tool_name` string, nullable: Exact tool name from `GET /connector/{slug}/tools`.
    - `overrides` object: How the tool is presented to the model. Each key REPLACES the derived value.
      - `name` string
      - `description` string
      - `input_schema` object: Must be a JSON Schema object with `"type": "object"`. Replaces the derived schema entirely.
      - `defaults` object: Default argument values the caller may still override.
    - `frozen_params` object: Arguments pinned by the author. Unlike `overrides.defaults`, a caller cannot change these.
    - `enabled` boolean
    - `id` string, nullable: Optional identity hint (`tbxe_…` on a toolbox, `tple_…` on a template): the `id` of a row this resource already has. On `PATCH /toolbox/{id}` and `PATCH /template/{id}` a row echoed back with its own id keeps it, so a client that keys per-row state by entry id (a switch mid-save) is not orphaned by the replacement. It is a hint, never an assertion: an id that is not one of THIS resource's current rows, is repeated, or would put the row out of stored order (rows list in id order) is ignored and the row gets a fresh id — and so is a value that is not a usable string (not a string, or over 200 characters). Never a 400, and never adopted from another resource. Omit it for a new row. Ignored on create.
    - `connection_id` string, nullable: Pin this entry to one connection (`conn_…`) the editor making the request can use; they become its delegator. `null` = "needs connection." On `PATCH /toolbox/{id}`, an incoming entry whose (connection_id, tool_name) pair matches an existing row keeps that row's original delegator rather than re-stamping the caller; only genuinely new pairs get the usability check and the caller's own stamp.
  - `shares` ShareRequest[]: Grants to create alongside the resource. Omit, or send `[]`, for a private one. A non-empty array additionally needs `<resource>:share`.
    - `grantee_type` 'user' | 'team' | 'org', required: `user` and `team` grants target one `grantee_id`; `org` applies to every member of the organization and takes no id.
    - `grantee_id` string, nullable: User id (`usr_…`) or team id (`team_…`). Omit or send null for `grantee_type: "org"`.
    - `level` 'view' | 'use' | 'edit', required: 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.
  - `skill` string, nullable: Markdown guidance on how to use these tools well. Trimmed, then capped at 10,000 Unicode code points (an emoji counts once) — longer is a `400` naming the limit, never a silent cut. `null` or an empty string clears it; omit the key to leave it unchanged. The resource's `description` is the one-line "when to use this" shown beside it, so write that too. Moderated like the description. When stamping, omitting it copies the template's skill (and `skill_origin_template_id` names the template); sending it — a string, or null for none — wins.

## Response `201`

Created

- object
  - `id` string: Toolbox id — a stored row (`tbx_…`), or a dynamic id (`global:{user_id}` / `connection:{connection_id}`).
  - `name` string
  - `description` string, nullable
  - `owner_user_id` string: Creator (`usr_…`). For a dynamic row, the caller.
  - `type` 'stored' | 'global' | 'connection': `stored` = a real, shareable row. `global`/`connection` = computed per request, always `readonly: true`.
  - `readonly` boolean: True for the dynamic global/per-connection toolboxes — never editable, shareable, transferable or deletable.
  - `template_id` string, nullable: Provenance only (stamped at creation, never a live link) — null for a from-scratch toolbox and for every dynamic row. May dangle after the template is deleted.
  - `connection_id` string: Present only for `type: "connection"` dynamic rows.
  - `connector_slug` string: Present only for `type: "connection"` dynamic rows.
  - `access_level` string: The caller's access: `owner`, or a granted `view`/`use`/`edit` level. Always `owner` for a dynamic row.
  - `owner` object, nullable: Owner summary — resolved for a row the caller does not themselves own (a toolbox shared with them), so the UI always knows whose row it is looking at. Absent for a toolbox the caller owns.
    - `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.
  - `entry_count` integer: Omitted for dynamic rows, which have no stored entries of their own.
  - `needs_connection_count` integer: Number of proxy entries with no connection pinned (`connection_id` is null), which is what a "N need connection" status is built from. Excludes synthetic entries, which pin no `connection_id` of their own by design. Omitted for dynamic rows (nothing to bind). Broken delegation (`delegation_ok: false`) only surfaces in the detail, inside `entries[]`.
  - `connectors` object: Which integrations this toolbox's tools come from, summarized as at most a handful of connectors. Present on every `GET /toolbox` row: a stored row summarizes its own entries, a `connection:{id}` row is that connection's one connector, and a `global:{user_id}` row summarizes the connections it spans. Also present on every command response (`POST /toolbox`, `GET /toolbox/{id}`, `PATCH /toolbox/{id}`, `POST /toolbox/{id}/transfer`), so a client that merges one into its list does not show a just-edited toolbox as having no integrations. `total: 0` means no connector-backed tools (empty, or synthetic-only), never "not computed".
    - `total` integer: Distinct connector slugs across the toolbox.
    - `preview` object[]: At most 5 connectors, ordered by entry count descending then slug ascending, so the dominant integration leads and the order is stable across requests. Each entry arrives resolved: there is no follow-up `GET /connector/{slug}` to make.
      - `slug` string: Connector slug — connectors are keyed by slug, not by id.
      - `name` string: Catalog label. Falls back to the slug when the connector no longer resolves (deleted from the catalog), so a row always has something to draw.
      - `logo` string, nullable: The connector's square `icon` when it has one, else its wordmark `logo`, else null (the connector carries neither picture, or could not be resolved). Draw it in a square tile; render initials from `name` when it is null.
  - `created_at` string, date-time, nullable: Null for dynamic rows, which are computed, never stored.
  - `updated_at` string, date-time, nullable
  - `access_summary` object: Present on a `GET /toolbox` stored row exactly when that row's `can_see_shares` is `true`: the caller owns it, holds `edit`, or administers a team it is granted to. Absent from dynamic rows, and deliberately absent for a `view` or `use` grantee, because who else has access is information about colleagues. Read `can_see_shares` to tell "not permitted" from "not carried"; never infer it from this field's absence.
    - `org_level` 'view' | 'use' | 'edit' | 'null', nullable: Level of the org-wide grant, or null when there is none.
    - `team_count` integer
    - `user_count` integer
    - `total` integer: Every grant, the org-wide one included.
    - `preview` object[]: At most 5 grantees, broadest first (org, then teams, then members), for a hover preview.
      - `grantee_type` 'user' | 'team' | 'org'
      - `grantee_id` string, nullable
      - `level` 'view' | 'use' | 'edit'
      - `name` string, nullable: Display name; null for org grants and for grantees no longer in the org.
  - `shares` AclEntry[]: A short preview of who the toolbox is shared with (same cap as `access_summary`). Present only on `GET /toolbox/{id}` when the caller may see who it is shared with. Never on a list row (`GET /toolbox`); page `GET /toolbox/{id}/share` for the full, cursor-paginated list.
    - `id` string: Grant id (`acl_…`), the `{aclId}` that `DELETE .../share/{aclId}` takes.
    - `resource_type` 'connection' | 'toolbox' | 'template' | 'connector' | 'file'
    - `resource_id` string: The shared resource's id (a connector's slug, for that type).
    - `grantee_type` 'user' | 'team' | 'org': `user` and `team` grants target one `grantee_id`; `org` applies to every member of the organization and takes no id.
    - `grantee_id` string, nullable: User id (`usr_…`) or team id (`team_…`). Null for a `grantee_type: "org"` grant.
    - `level` 'view' | 'use' | 'edit': 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.
    - `created_at` string, date-time
    - `updated_at` string, date-time
  - `connected_app_summary` object: The OAuth-connected apps that reach this toolbox, as a short summary. Present only on `GET /toolbox/{id}` for a stored toolbox, and only when the caller may see who it is shared with (the same condition as `access_summary`). Never the full set: page `GET /toolbox/{id}/connected-app` for that.
    - `count` integer
    - `preview` object[]: At most 5 apps, for a hover preview.
      - `grant_id` string: OAuth grant id (`ogrt_…`) — what `DELETE /oauth/grant/{id}` takes, scoped to the grant's own user.
      - `client_id` string
      - `client_name` string, nullable: Null when the OAuth client row is gone.
      - `user` object
        - `id` string: User id (`usr_…`).
        - `name` string: Omitted along with `email` when the id no longer resolves to an org member.
        - `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.
      - `via` 'toolbox' | 'all_tools': `toolbox`: this toolbox is named explicitly on the grant. `all_tools`: an "All my tools" authorization by a user who can currently use this toolbox — computed live, not a stored fact.
  - `has_skill` boolean: Whether a skill is written. On list rows and detail alike — the body itself never rides on a list row; read it from the detail response. Omitted on a dynamic row, which has no skill of its own.
  - `skill_may_be_stale` boolean: True once the entries changed after the skill was last written; cleared by the next write of `skill`. Never true without a skill. Omitted on a dynamic row.
  - `can_use` boolean: Whether the caller may execute this toolbox's tools — based on the caller's ownership or grant level. Present on every list and detail row for both templates and toolboxes.
  - `can_share` boolean: Whether the caller may share this toolbox — owner, `edit` access, or `toolbox:share`. No `toolbox:manage` fallback. Mirrors `POST /toolbox/{id}/share`'s own check.
  - `can_manage` boolean: Whether the caller may edit this toolbox's own settings — owner, or `edit` access. No `toolbox:manage` fallback. Mirrors `PATCH /toolbox/{id}`.
  - `can_transfer` boolean: Whether the caller may transfer or delete this toolbox — ownership, full stop. No `toolbox:manage` fallback. Mirrors `POST /toolbox/{id}/transfer` and `DELETE /toolbox/{id}`.
  - `can_revoke_share` boolean: Whether the caller may grant or revoke access to this toolbox. It matches `can_share` and is separate from `can_manage`: an `edit` grantee whose role omits `toolbox:share` can edit the toolbox but cannot change who else has access. Mirrors `DELETE /toolbox/{id}/share/{aclId}`.
  - `access_via` 'owner' | 'direct' | 'team' | 'org': How the caller reaches this toolbox, 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 toolbox 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 toolbox 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.
  - `entries` object[]: Resolved entries — always present, at every access level.
    - `id` string: Entry id (`tbxe_…`) — stable across updates only if you send it back unchanged.
    - `type` 'proxy' | 'synthetic'
    - `synthetic_tool_id` string, nullable: Set for `synthetic` entries (`syn_…`).
    - `connector_slug` string, nullable: Connector slug for `proxy` entries; null for synthetic.
    - `connection_id` string, nullable: `null` = "needs connection" — stamped-but-unfilled, or a pin that broke. Never set for synthetic entries.
    - `delegated_by_user_id` string, nullable: Set by the server, never a client input: whose `use` grant on `connection_id` this pin rides on. If this user loses `use` on the connection, the entry goes unmet for every executor, not just them. Null if and only if `connection_id` is null.
    - `tool_name` string, nullable: Connector tool name for `proxy` entries.
    - `overrides` object: Presentation overrides — see the entry input schema for the same shape, request-side.
      - `name` string
      - `description` string
      - `input_schema` object
      - `defaults` object
    - `frozen_params` object
    - `enabled` boolean
    - `connection_status` 'pending' | 'active' | 'needs_reauth' | 'disconnected' | 'null', nullable: Detail responses only: the pinned connection's live status, when resolved.
    - `unmet` boolean: Detail responses only: no usable connection backs this entry — pin is empty, broken, or the delegator lost `use`.
    - `unmet_reason` 'connector_not_shared' | 'null', nullable: Detail responses only: the one `unmet` cause worth naming, null for every other. `connector_not_shared`: the pinned connection is live and delegation-intact, but its OWNER no longer holds `use` on the org-owned connector it runs through, so the entry is listed (flagged) and never advertised, and every call through it is refused. Re-sharing the connector clears it with no edit to the toolbox. Not repairable by re-pinning — `can_repin` stays false for it.
    - `tool_available` boolean: Detail responses only: false when the catalog (or the synthetic-tool store) no longer has this tool.
    - `delegation_ok` boolean: Detail responses only: false when `connection_id` is set but `delegated_by_user_id` no longer holds `use` on it. Always true when `connection_id` is null.
    - `delegated_by_access_via` 'owner' | 'direct' | 'team' | 'org' | 'null', nullable: Detail responses only: how `delegated_by_user_id` holds `connection_id`, using the same precedence as the caller's own `access_via` (owner, else org, else team, else direct; the broadest wins). `delegation_ok` says the delegation still stands; this says what it stands on, so a client can avoid implying a personal grant where an org-wide one is doing the work. Null for a synthetic entry (its steps, not the row, hold connections), for a pin with no connection or no recorded delegator, and whenever the delegation no longer works (`delegation_ok: false`): the delegator is no longer an active member, or their access has fallen below `use`.
    - `can_repin` boolean: Detail responses only, and the only field here that differs by reader: whether the caller may repair this entry with `POST /toolbox/{id}/repin`. True when the entry is broken (`delegation_ok: false` on a proxy entry that pins a connection), the caller holds `use` on that connection, and the caller holds `edit` (or ownership) on this toolbox. `delegation_ok: false` is the same answer for everybody who opens the toolbox; this says who among them can do something about it.
    - `can_view_connector` boolean: Present on the toolbox's own responses, per reader: whether the caller may open `connector_slug` (`GET /connector/{slug}` and its `/tools`). False when the entry is pinned to an organization-owned custom connector that nobody has shared with the caller; those routes answer 404 for them. The entry still carries its label and logo and still runs on its delegator's access; this only says the connector page and its tool picker are not for this reader. Always true for a platform connector and for a synthetic entry.
    - `tool_title` string, nullable: Response-only. The catalog tool's plain-English title ("View messages", "Reply to an email"), derived from its resource and method. Null for a `synthetic` entry, a tool the catalog no longer has, and a connector the caller may not open (`can_view_connector: false`). Render `overrides.name`, else this, else `tool_name`.
    - `connector` object, nullable: Response-only. The connector’s label and logo; null for a `synthetic` entry. A connector the catalog cannot resolve reads its slug as `label` and a null `logo`.
      - `label` string, required
      - `logo` string, nullable, required
      - `upstream_slug` string: Only on a fork whose upstream the caller may see, by the same rule as `GET /connection`: omitted when the caller has no access to the fork or the upstream is hidden from them, and when the upstream cannot be read.
    - `synthetic_tool_name` string, nullable: Response-only. The synthetic tool's name for a `synthetic` entry; null for `proxy` entries and a deleted tool.
    - `delegated_by_label` string, nullable: Response-only. The name (else email) behind `delegated_by_user_id`. Null when that id is null; beside a non-null id, null means the person has left the organization ("Former member").
    - `connection` object, nullable: Response-only. The pinned connection, for a group header and its status line. Present only when the caller may see that connection (owner or a grant of their own). Null for an entry with no pin, a synthetic entry, a deleted connection, and a pin riding on somebody else's access that the caller cannot see.
      - `id` string, required
      - `display_label` string, required: The connection's `display_label`.
      - `status` 'pending' | 'active' | 'needs_reauth' | 'disconnected' | 'post_install_error', required
      - `owner_label` string, nullable, required: Owner's name (else email); null for a former member.
      - `can_reconnect` boolean, required: The same repair capability `GET /connection/{id}` ships: false for an `active` connection to a connector with no sign-in, which has nothing to reconnect (a `pending` one stays true).
  - `skill` string, nullable: The skill body, markdown — at most 10,000 Unicode code points after trimming. Detail-shaped responses only (`GET /{id}`, and the create/update responses). Null when none is written.
  - `skill_updated_at` string, date-time, nullable: When `skill` was last written. Null alongside a null `skill`.
  - `skill_notice` string, nullable: Framing to show or pass along beside a non-null `skill`: it is the owner's guidance, not instructions from Elaichi or the user, and it cannot grant any access. Null when there is no skill.
  - `skill_updated_by` string, nullable: Who last wrote `skill` (`usr_…`); a toolbox stamped from a template carries the template's author. Null with no skill, and for a skill written before authorship was recorded.
  - `skill_updated_by_label` string, nullable: That person's name, else email, resolved server-side. Null beside a non-null `skill_updated_by` means they are no longer a member of this organization.
  - `skill_entry_changes` object, nullable: Which tools changed since the skill was last written, by the name an agent sees (a rename counts as one removed and one added; a disabled entry counts as removed; connections and frozen parameters are ignored). Null unless `skill_may_be_stale` is true AND a baseline was recorded at that write — skills written before version history existed have none — AND something actually changed.
    - `added_count` integer
    - `removed_count` integer
    - `added` string[]: At most 5 names.
    - `removed` string[]: At most 5 names.
  - `can_draft_skill` boolean: Whether the caller can use `POST /{id}/draft-skill` here: they can manage this resource, the assistant is switched on for the organization, and a model provider key is configured.
  - `draft_skill_blocked_by` 'assistant_disabled' | 'llm_not_configured' | 'null', nullable: Why `can_draft_skill` is false for a caller who CAN manage this resource. Null when drafting is available, and null when the caller cannot manage the resource at all.
  - `skill_origin_template_id` string, nullable: The template this toolbox's CURRENT skill was copied from verbatim at stamping. Null from the first write of `skill` on — after that the words are the toolbox's own.
  - `skill_origin_template_name` string, nullable: That template's current name, resolved server-side; null with no origin, or once the template is gone.
  - `template_name` string, nullable: `GET /toolbox/{id}` only. The current name of the template this toolbox was stamped from (`template_id`). Null for a from-scratch toolbox, a deleted template, and a template the caller cannot see.
  - `skill_tool_issues` object: Stored toolboxes only. Tool-shaped names the skill puts in backticks that no entry of this toolbox holds (what an editor shows as "tools named here aren't in this toolbox"). A name matches an entry's catalog `tool_name`, or its `overrides.name` when renamed. A count plus at most 10 names; `count` is 0 when there is no skill.
    - `count` integer: Distinct names the skill uses that no entry holds.
    - `preview` object[]
      - `name` string: The name as the skill writes it.
      - `suggestion` string, nullable: The entry's own name this most likely means (`list_query_database` -> `list_all_notion_query_database`); null unless exactly one entry matches.
  - `skill_agent_preview` object, nullable: Stored toolboxes only: what an agent connected to this toolbox is shown before it reads the skill, built by the same code the MCP endpoint uses. `instructions_line` is the line the server instructions carry for a connection limited to chosen toolboxes; `resource` is the `elaichi://toolbox/{id}/skill` entry in `resources/list`. The resource text itself is `skill_notice`, a blank line, then `skill`. Null with no skill.
    - `instructions_line` string
    - `resource` object
      - `uri` string
      - `name` string
      - `title` string
      - `description` string
      - `mime_type` string
  - `tools` object[]: The resolved, runnable tool surface. Present ONLY when the caller's access reaches `use` — a view-only grantee must not see delegated connections' labels.
    - `name` string
    - `description` string
    - `input_schema` object: Present only with `?include=schemas` — omitted by default; a toolbox spanning many connections can carry thousands of complete JSON Schemas.
    - `type` 'proxy' | 'synthetic'
    - `connector_slug` string, nullable: `"synthetic"` sentinel is never used here; null for synthetic tools.
    - `connections` object[]: Every account this tool can reach, labeled exactly as the `connection` argument enum in `input_schema` accepts them.
      - `id` string
      - `label` string
    - `connection_id` string, nullable: Set only when exactly one connection backs this tool (read `connections` otherwise). Null for synthetic tools.
    - `synthetic_tool_id` string, nullable
  - `delegation` object, nullable: What this toolbox runs on. Sharing a toolbox at `use` hands the grantee execution over every connection its entries reach (pinned directly, or reached through a synthetic entry's steps, where the synthetic tool's owner is the delegator), while leaving the connections themselves invisible to them. This is a summary, never the full set, so the response stays the same size however many connections the toolbox spans. Present on every stored-toolbox response (detail, create, update and share) and always empty for a dynamic row, which delegates nothing. On a create, update or share response it can be `null`: the write succeeded but the summary could not be computed (this is not the same as "nothing is delegated", which is an all-zero summary); re-read `GET /toolbox/{id}`. Unlike `tools`, this is NOT gated on `use`: its `visible` half already withholds every name the caller has no right to, and its two totals say only how many connections and how many people stand behind the toolbox — which a grantee can already count off `entries[].connection_id`.
    - `connection_count` integer: Distinct connections the tools run through, whether or not the caller can see them.
    - `delegator_count` integer: Distinct people whose access those pins ride on. Never named at this level.
    - `visible` object: The same delegation restricted to what this caller may already see. Every label and delegator name lives in here, so a `use` grantee is never told the name or owner of a connection that `GET /connection/{id}` would 404 for them.
      - `connection_count` integer
      - `private_connection_count` integer: Of the visible ones, how many carry no grants at all — only their owner can reach them today.
      - `preview` object[]: At most 3 of the visible connections, private ones first.
        - `connection_id` string
        - `connector` string
        - `label` string
        - `logo` string, nullable: The connector's logo.
        - `via` 'entry' | 'synthetic_tool': `entry` = an entry pins it directly. `synthetic_tool` = reached only through a synthetic tool's steps.
        - `delegated_by` object: Whose access this delegation rides on. `name`/`email` are absent for a user this org can no longer resolve. Read it together with `delegated_by_source`.
          - `id` string
          - `name` string
          - `email` string
        - `delegated_by_source` 'delegator' | 'connection_owner': `delegator` = the pin's own stamped delegator (or, for `via: synthetic_tool`, the tool's owner): this person really is who the execution rides on. `connection_owner` = the pin carries no recorded delegator (an older entry), so `delegated_by` is the connection's owner standing in as the delegator. Such a pin is still a real delegation and is still counted; copy that names a person must branch on this rather than claim they shared it.
        - `delegated_by_access_via` 'owner' | 'direct' | 'team' | 'org' | 'null', nullable: How `delegated_by` was entitled to this connection, with the same precedence as `access_via`: the broadest true source wins (owner, else org, else team, else direct) and the access level plays no part. `delegated_by` alone only says who pinned it; without this, a client reads an org-wide or team grant as a personal favor and hides how far the account actually reaches. Null whenever the delegation no longer works (the delegator is no longer an active member, or their access to the connection has fallen below `use`), since the only honest statement left is who pinned it.
        - `delegated_by_access_via_team` object: The team behind `delegated_by_access_via: 'team'`, present only when the caller is themselves a member of it. Absent otherwise, and a client should then say "a team" without naming it, because the team's name is not the caller's to learn.
          - `id` string
          - `name` string
        - `private` boolean
        - `can_share` boolean: May the caller grant someone access to this connection directly — the same derivation `GET /connection/{id}`'s `can_share` and `POST /connection/{id}/share`'s own gate use.

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