---
title: "Agent imports"
description: "Bring agents, tools, and knowledge bases over from Vapi, Retell, ElevenLabs Agents, or Bland with an API key or a pasted JSON export."
---

An **agent import** fetches everything in a competitor account, maps it onto
ThunderPhone agents, API connections, and knowledge documents, and lets you
review before anything is created. The vendor key is used only for the
import and deleted when it finishes. Admin role is required to start, edit,
commit, or discard an import, or to move a number; members can read it.

## Start an import

`POST /v1/agent-imports`

```json
{ "source": "vapi", "auth_mode": "api_key", "api_key": "…" }
```

`source` is `vapi`, `retell`, `elevenlabs`, or `bland`. `auth_mode` is
`api_key` or `paste` (send the exported JSON as `payload`). Returns `201`
with the import in `queued` status, or `409` with `import_id` if one is
already running.

## Get an import

`GET /v1/agent-imports/{id}` — poll until `status` is `ready`. The response
carries `progress`, one `items[]` entry per source agent (`mapped`,
`warnings`, `selected`), and a `report` of phone numbers, webhooks, and
unsupported tools that are not imported.

Each `report.phone_numbers[]` entry has `ownership`: `customer_carrier` (in
your own carrier account, named by `carrier`: `twilio`, `telnyx`, or
`vonage`), `sip_trunk`, `vendor` (sold by the source platform), or `unknown`.
`carrier_account_id` is the Twilio Account SID when the platform exposed it.

## Edit an item

`PATCH /v1/agent-imports/{id}/items/{item_id}` with any of `selected`,
`name`, `voice`, `product`, `prompt_choice` (`deterministic` or `rewritten`).
Only while the import is `ready`. Setting `voice` on an agent whose source
voice had no close match (`voice_confidence` `default`) marks it `picked`.

## Enter a missing header

`POST /v1/agent-imports/{id}/connection-secrets`

```json
{ "connection": "tool_book", "header_id": "0", "value": "Bearer …" }
```

Source platforms never return stored secrets, so a tool plan lists the
headers it could not copy in `mapped.tools[].missing_headers`
(`id`, `name`, `name_known`, `provided`). `connection` is the plan's `key`,
shared by every agent that uses the tool, so one value covers all of them.
Send `header_name` too when `name_known` is `false`. The value is
write-only: it is encrypted until commit, stored on the API connection it
creates, and never returned. An empty `value` clears it. Only while the
import is `ready`.

## Commit an import

`POST /v1/agent-imports/{id}/commit` — creates the selected agents in the
background; poll the import until `status` is `done`. `result` lists the
created agent, API connection, and knowledge base ids and any failed items.
When a source agent used Cal.com booking tools and the organization has a
Cal.com app connection, commit attaches that connection to the new agent.

## Move a number to an imported agent

`POST /v1/agent-imports/{id}/numbers/move`

```json
{ "number": "+15551112222", "agent_id": 42, "connection_id": 7 }
```

For a `customer_carrier` number on Twilio or Telnyx. `agent_id` must be an
agent this import created, and `connection_id` a
[VoIP connection](/guides/bring-your-own-numbers) for the account that holds
the number. ThunderPhone re-points the number at itself in that account, so
**calls stop going to the source platform**, and sets the agent as the
number's inbound agent. The number starts `provisioning`: when
`needs_verification` is `true`, call
`POST /v1/phone-numbers/{phone_number.id}/verify-voip` to switch it on. A
number already on ThunderPhone in your organization is only re-assigned
(`imported: false`) and needs no `connection_id`. Errors carry a `code`:
`number_not_in_connection` (the account does not hold the number),
`connection_account_mismatch`, `number_not_movable`, `number_in_other_org`
(409), and `carrier_unavailable` (502).

## Discard an import

`DELETE /v1/agent-imports/{id}` — abandons the import and wipes the stored key.

## List imports

`GET /v1/agent-imports` — the organization's 20 most recent imports.
