# Create an agent from a template (/docs/api/voice-agents/agent-templates/instantiateAgentTemplate)

> For the complete documentation index, see [llms.txt](https://docs.tandemcx.ai/llms.txt). Any page on this site can be fetched as Markdown by appending `.md` to its URL.

`POST /v1/agent-media/agent-templates/{templateId}/instantiate`

Create an agent from a template

Create a voice agent from a template. Every requirement the template declares must be bound to one of your own resources, unless it is marked optional — an unbound optional requirement drops the tools that needed it. Settings your organization cannot use (a model whose vendor integration is not connected, an ElevenLabs voice without the ElevenLabs integration) are substituted for ones it can, and every substitution is reported in the response. Deciding that needs your organization's integration status, so if that cannot be read the agent is not created at all — retry the call rather than accepting a configuration chosen without it.

The agent is created as a draft, exactly as `POST /v1/agent-media/agents` creates one: the bound configuration is written to version `0.1`, no `publishedVersion` is set, and the agent answers no calls until you publish with `POST /v1/agent-media/agents/{agentId}/versions/{version}/publish`. Edit it first if you want to — a draft is editable in place with `PUT /v1/agent-media/agents/{agentId}/versions/0.1`, which a published version is not. `PUT /v1/agent-media/agents/{agentId}` will not accept a configuration for it in either state.

## Request

**Base URL:** `https://api.tandemcx.ai`

**Authentication:** `Authorization: Bearer <token>` — A Tandem bearer token. Requests are scoped to the organization the token belongs to; no organization header is required.

### Path parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `templateId` | string | Yes | The template's unique ID. |

### Body (`application/json`) — required

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | The new agent's name. |
| `bindings` | object | Yes | One entry per requirement, keyed by the requirement's `id`. |

## Responses

### 201 — The created agent's id, and anything that was substituted.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | No | — |
| `substitutions` | array of object | No | — |
| `substitutions[].field` | string | No | Dotted path into the created agent's config, e.g. `slots.tts`. |
| `substitutions[].from` | string | No | What the template asked for. |
| `substitutions[].to` | string | No | What was used instead. |
| `substitutions[].reason` | string | No | Why the substitution was made, e.g. that the organization has no active integration for the requested provider. |
| `droppedTools` | array of string | No | Everything the template declared that this agent did not get, because an optional requirement was left unbound — each tool by name, and the knowledge base if it had one. |

### 400 — The configuration was rejected. `error` is `invalid_config` and `errors` lists each offending field.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | — |
| `errors` | array of object | No | — |
| `errors[].field` | string | No | Dotted path to the offending field. |
| `errors[].message` | string | No | — |

### 401 — Missing, malformed, or expired bearer token.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 403 — `error` is `curated_partition_read_only`: the request resolved to Tandem's curated templates, which no organization may write. Only a Tandem release publishes a curated template.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 404 — The resource does not exist.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 503 — `error` is `integration_status_unavailable`: your organization's integration status could not be read, so nothing was created. Retry.

No response body.
