---
title: "Share a toolbox"
method: POST
path: "/toolbox/{id}/share"
tags: ["Toolboxes"]
---

# Share a toolbox

`POST /toolbox/{id}/share`

## Request

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

Grants one user, team, or the whole organization access to a toolbox at a level. Levels are ordered `view` < `use` < `edit`. `use` delegates: the grantee executes tools on this toolbox, running each pinned entry through its delegator's access, never their own. Re-granting the same grantee replaces the level rather than stacking. The response repeats the toolbox's `delegation` summary (the same short summary `GET /toolbox/{id}` carries), so a client that shares without ever having read the detail still learns what it just handed out. Rejects an automatic id with 400, since nothing is shareable there. Requires `edit` access or ownership, and `toolbox:share`.

## Path parameters

- `id` string, required

## Headers

- `X-Organization-Id` string

## Request body

- union
  - ShareRequest: Grants a user, a team, or the whole organization access to the resource at a level. Re-granting the same grantee replaces the level; it never stacks.
    - `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.
  - ShareManyRequest: Share with several grantees at one level. Partial success: each grantee is granted or refused on its own, and only a request where nobody is granted answers 400 `share_grantees_rejected` (every reason in `error.details.rejected`). Duplicates collapse to one grant.
    - `grantees` object[], required
      - `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.

## Response `201`

Created

- union
  - object: One access grant on a connection, toolbox, template, connector or (at `view` only) a stored tool file.
    - `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
    - `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}`.
      - `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.
  - ShareManyResponse: The answer to a `grantees` share: the grants as written, and everyone who was not granted with the code the single form would have answered (`share_target_is_self`, `share_target_is_owner`, `member_not_active`, `bad_request`). A resource's own extra fields (a toolbox's `delegation`) ride alongside.
    - `result` AclEntry[]
      - `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
    - `rejected` object[]
      - `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
      - `code` string
      - `message` string

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