# Get a template

> Source: https://elaichi.ai/docs/api-reference/templates/template/gettemplate/

`GET /template/{id}`

Resource: **Template** · API: **Templates**

## Path parameters

- **`id`** _(string, required)_
  Template id (`tpl_…`).

## Response body

- **`id`** _(string)_
  Template id (`tpl_…`).
- **`name`** _(string)_
- **`description`** _(string,null)_
- **`owner_user_id`** _(string)_
  Creator (`usr_…`).
- **`access_level`** _(string)_
  The caller's access: `owner`, or a granted `view`/`use`/`edit` level. Templates carry no organization-wide oversight path — an org owner/admin sees a template only when they own it or it has been shared with them, same as any other member.
- **`owner`** _(object,null)_
  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.
- **`entry_count`** _(integer)_
- **`connectors`** _(object)_
  Which integrations this template's tools come from, bounded — the console renders it as a stack of connector logos, exactly as on a toolbox row. Present on every `GET /template` row AND on every command response (`POST /template`, `GET /template/{id}`, `PATCH /template/{id}`, `POST /template/{id}/transfer`), so a client that merges a command response into its list does not lose the stack. `total: 0` means no connector-backed tools (empty, or synthetic-only), never "not computed".
  - **`total`** _(integer)_
    Distinct connector slugs across the template.
  - **`preview`** _(array<object>)_
    At most 5 connectors, ordered by entry count descending then slug ascending — 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, and a page of rows costs no per-row catalog lookup.
    - **`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,null)_
      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)_
- **`updated_at`** _(string)_
- **`access_summary`** _(object)_
  Present on a `GET /template` 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. Same gate and same reasoning as the toolbox row's.
  - **`org_level`** _(string,null)_
    Level of the org-wide grant, or null when there is none.
    Allowed: `view`, `use`, `edit`, `null`
  - **`team_count`** _(integer)_
  - **`user_count`** _(integer)_
  - **`total`** _(integer)_
    Every grant, the org-wide one included.
  - **`preview`** _(array<object>)_
    At most 5 grantees, broadest first (org, then teams, then members), for a hover preview.
    - **`grantee_type`** _(string)_
      Allowed: `user`, `team`, `org`
    - **`grantee_id`** _(string,null)_
    - **`level`** _(string)_
      Allowed: `view`, `use`, `edit`
    - **`name`** _(string,null)_
      Display name; null for org grants and for grantees no longer in the org.
- **`shares`** _(array<object>)_
  Every grant, unabridged. Present only on `GET /template/{id}` when the caller may see the ACL (owner or `edit` access); list rows carry the bounded `access_summary` instead.
  - **`id`** _(string)_
    ACL entry id — the `:aclId` a `DELETE .../share/{aclId}` call takes.
  - **`resource_type`** _(string)_
    Allowed: `connection`, `toolbox`, `template`, `connector`, `file`
  - **`resource_id`** _(string)_
    The shared resource's id (a connector's slug, for that type).
  - **`grantee_type`** _(string)_
    `user` and `team` grants target one `grantee_id`; `org` applies to every member of the organization and takes no id.
    Allowed: `user`, `team`, `org`
  - **`grantee_id`** _(string,null)_
    User id (`usr_…`) or team id (`team_…`). Null for a `grantee_type: "org"` grant.
  - **`level`** _(string)_
    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.
    Allowed: `view`, `use`, `edit`
  - **`created_at`** _(string)_
  - **`updated_at`** _(string)_
- **`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.
- **`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.
- **`can_use`** _(boolean)_
  Whether the caller may stamp a toolbox from this template — the caller's grant-or-ownership level (§10). Present on every list and detail row for both templates and toolboxes — the two ACL-backed resource types with a `use`-gated action of their own.
- **`can_share`** _(boolean)_
  Whether the caller may share this template — owner, `edit` access, or `template:share`. No `template:manage` fallback. Mirrors `POST /template/{id}/share`'s own check.
- **`can_manage`** _(boolean)_
  Whether the caller may edit this template's own settings — owner, or `edit` access. No `template:manage` fallback. Mirrors `PATCH /template/{id}`.
- **`can_transfer`** _(boolean)_
  Whether the caller may transfer or delete this template — ownership, full stop. No `template:manage` fallback. Mirrors `POST /template/{id}/transfer` and `DELETE /template/{id}`.
- **`can_revoke_share`** _(boolean)_
  `can_share`, verbatim — a THIRD formula, distinct from `can_manage`: an `edit` grantee whose role omits `template:share` can edit the template but was never meant to grant or revoke someone else's access to it. Mirrors `DELETE /template/{id}/share/{aclId}`.
- **`access_via`** _(string)_
  How the CALLER reaches this template — not who else can. `owner` — they own it. `direct` — a grant naming them personally. `team` — a grant to a team they belong to (or, per §6.2, one they administer), named in `access_via_team`. `org` — an organization-wide grant. When several sources apply the BROADEST wins and the caller's access level is not consulted: owner, else `org`, else `team`, else `direct`. So a caller granted `edit` personally AND `view` org-wide reads `org` — a narrower grant must never mask org-wide exposure, since this field says how far the template reaches, not what the caller may do with it. Deliberately NOT gated on `can_see_shares`, and deliberately not a widening of it: this is the caller's OWN grant and their OWN team memberships, so a `view`/`use` grantee receives it while the grantee list — information about colleagues — stays closed to them. No other member is ever named. ABSENT when nothing reaches the caller — a transfer answering the ex-owner of a resource that was never shared, or a catalog row browsed with no grant behind it. Absent means "no source to name", never "not permitted", and never an implied `org`.
  Allowed: `owner`, `direct`, `team`, `org`
- **`access_via_team`** _(object)_
  Present exactly when `access_via` is `team`, absent otherwise. The team the caller reaches this template through — one of their own teams, never a disclosure about anybody else.
  - **`id`** _(string)_
    Team id (`team_…`).
  - **`name`** _(string,null)_
    Team display name, or null when the team no longer resolves in the directory — the same null contract every resolved grantee name carries.
- **`entries`** _(array<object>)_
  - **`id`** _(string)_
    Entry id (`tple_…`) — stable across updates only if you send it back unchanged.
  - **`type`** _(string)_
    Allowed: `proxy`, `synthetic`
  - **`synthetic_tool_id`** _(string,null)_
    Set for `synthetic` entries (`syn_…`).
  - **`synthetic_tool_name`** _(string,null)_
    Response-only. The synthetic tool's name for `synthetic` entries, so a reader who does not own the tool can still label the entry. Null for `proxy` entries and when the tool has been deleted.
  - **`connector_slug`** _(string,null)_
    Connector slug for `proxy` entries; null for synthetic.
  - **`tool_name`** _(string,null)_
    Connector tool name for `proxy` entries.
  - **`tool_title`** _(string,null)_
    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,null, required)_
    Response-only. The connector's label and logo, one batch per response; null for a `synthetic` entry. A connector the catalog cannot resolve reads its slug as `label` and a null `logo`.
  - **`can_view_connector`** _(boolean)_
    Response-only, per READER: may the caller open `connector_slug` (`GET /connector/{slug}` and its `/tools`)? False for an organization-owned custom connector nobody shared with the caller (docs/access-model.md §4). Always true for a platform connector and for a synthetic entry.
  - **`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)_
- **`skill`** _(string,null)_
  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,null)_
  When `skill` was last written. Null alongside a null `skill`.
- **`skill_notice`** _(string,null)_
  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,null)_
  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,null)_
  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,null)_
  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.
- **`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`** _(string,null)_
  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.
  Allowed: `assistant_disabled`, `llm_not_configured`, `null`
- **`warnings`** _(array<object>)_
  Only on a create or update response, and only when non-empty: pins accepted although nothing can run them yet (a remote MCP tool the server is not offering right now: it will be once a connection of that server lists it, unless an admin turned it off). Informational, never an error.
  - **`connector_slug`** _(string)_
  - **`tool_name`** _(string)_
  - **`message`** _(string)_

## Code examples

### curl

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

### JavaScript

```javascript
const response = await fetch('https://api.elaichi.ai/template/<id>', {
  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/template/<id>"
headers = {
    "Authorization": f"Bearer {os.environ['ELAICHI_API_TOKEN']}",
    "Content-Type": "application/json",
}

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