> ## Documentation Index
> Fetch the complete documentation index at: https://docs.callers.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage agents

> Create, read, replace, update, duplicate, start, stop, and delete agents with the Callers API, plus agent groups, success criteria, and vocabulary.

The `/agents` endpoints let you manage agents as code: provision a standard agent for every new customer, copy a proven agent into a subaccount, rename agents or swap their phone numbers, and start or stop them on your own schedule.

> [!TIP]
>
> For most teams the fastest path is to build and test the agent in the dashboard, then use the API to duplicate, update, and run it. Defining a complete script through the API is possible but verbose.

> [!NOTE]
>
> Agents were previously called *campaigns*. The `/campaigns/...` paths still work and behave the same as `/agents/...`. Responses include both `campaignId`/`campaignGroupId` and `agentId`/`agentGroupId` fields with the same values.

## Endpoints at a glance

| Method and path | What it does |
| - | - |
| `GET /agents?organizationId=…` | List agents in an account. |
| `GET /agents/{agentId}` | Get one agent. |
| `POST /agents` | Create an agent. |
| `PUT /agents/{agentId}` | Replace an agent's whole configuration. |
| `PATCH /agents/{agentId}` | Update name, phone numbers, or webhooks. |
| `DELETE /agents/{agentId}` | Archive (delete) an agent. |
| `POST /agents/{agentId}/duplicate` | Copy an agent, optionally into a subaccount. |
| `POST /agents/{agentId}/start` / `stop` | Start or stop dialing. |
| `POST /agents/{agentId}/update/interestcriteria` | Replace success criteria. |
| `GET /agent-groups`, `GET /agent-groups/{agentGroupId}` | List agent groups. |
| `/agents/{agentId}/vocabulary` | Manage speech recognition vocabulary. |

## List and get agents

`GET /agents` requires `organizationId`. Use your own account ID (from `GET /organization`) or the ID of one of your subaccounts. Filter by group with `agentGroupId`.

```bash cURL theme={"dark"}
curl "https://api.callers.ai/agents?organizationId=$ORG_ID&agentGroupId=$GROUP_ID" \
  -H "Authorization: $CALLERS_API_KEY"
```

```javascript Node.js theme={"dark"}
const res = await fetch(
  `https://api.callers.ai/agents?organizationId=${orgId}`,
  { headers: { Authorization: process.env.CALLERS_API_KEY } }
);
const { data: agents } = await res.json();
```

```python Python theme={"dark"}
agents = requests.get(
    "https://api.callers.ai/agents",
    headers={"Authorization": os.environ["CALLERS_API_KEY"]},
    params={"organizationId": org_id},
).json()["data"]
```

Each agent includes:

**id** `string`

Agent ID.

**name** `string`

Agent name.

**active** `boolean`

Whether the agent is running.

**isIncoming** `boolean`

`true` for inbound agents.

**callParams** `object`

Voice settings: voice, phone numbers (`phonesFrom`), language, time zone, schedule, retries, recording, voicemail, and more.

**emailParams** `object`

Email channel settings (Email agents).

**webhooks** `object[]`

Webhooks configured on the agent.

**variables** `string[]`

Variables the script uses. Provide these in each contact's `data`.

**incomingPhoneNumber** `string`

Inbound number, for inbound agents.

**firstInteractionAt** `string`

When the first call or chat happened (ISO 8601).

**completedAt** `string`

When the agent ran out of contacts (ISO 8601).

**agentGroupId** `string`

Group ID, or `null`.

**agentGroupName** `string`

Group name, or `null`.

## Create an agent

`POST /agents` creates an agent and returns it with status `201`. The schema covers everything the dashboard can configure; most fields are optional and default to the same values the dashboard uses.

Things to know:

* **Minimum fields.** For a basic outbound Voice agent, send `name` (at least 3 characters) and `voiceId`. Get voice IDs from `GET /voices`.
* **Nothing is picked for you.** No voice or phone number is selected automatically. Send `phoneNumbers` (or `callParams.phonesFrom`) with numbers already in your account.
* **Type.** `type` is `CALL` (default), `CHAT`, `EMAIL`, or `TRIGGER`. Set `isIncoming: true` for inbound agents.
* **Time zone.** If omitted, it's `UTC`. Send an IANA time zone (`callParams.timezone`) when calls should follow local hours.
* **Script.** Use `steps` (flat) or `nestedSteps` plus `edges` (graph). If you omit both, the agent gets the standard starter step.
* **Initial state.** Call, chat, and email agents are created stopped. Trigger agents activate immediately.
* **Arrays replace.** Any array you send replaces the default; an empty array clears it.
* **Shortcuts.** `voiceId` and `phoneNumbers` override `callParams.voice` and `callParams.phonesFrom` when both are present.

```bash cURL theme={"dark"}
curl -X POST https://api.callers.ai/agents \
  -H "Authorization: $CALLERS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer follow-up calls",
    "type": "CALL",
    "isIncoming": false,
    "voiceId": "507f1f77bcf86cd799439011",
    "phoneNumbers": ["+14155552671"],
    "callParams": {
      "language": "en-US",
      "timezone": "America/New_York"
    },
    "steps": [
      {
        "id": "greeting",
        "type": "OTHER",
        "template": "Hello {{name}}, this is the support team.",
        "meeting": null,
        "description": null
      }
    ],
    "webhooks": [
      {
        "name": "Call completed",
        "url": "https://example.com/webhooks/calls",
        "events": ["CALL_FINISHED"],
        "isAdvanced": false
      }
    ]
  }'
```

```javascript Node.js theme={"dark"}
const res = await fetch("https://api.callers.ai/agents", {
  method: "POST",
  headers: {
    Authorization: process.env.CALLERS_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Customer follow-up calls",
    voiceId: "507f1f77bcf86cd799439011",
    phoneNumbers: ["+14155552671"],
    callParams: { language: "en-US", timezone: "America/New_York" },
    steps: [
      {
        id: "greeting",
        type: "OTHER",
        template: "Hello {{name}}, this is the support team.",
        meeting: null,
        description: null,
      },
    ],
  }),
});
const { data: agent } = await res.json();
console.log(agent.id);
```

```python Python theme={"dark"}
agent = requests.post(
    "https://api.callers.ai/agents",
    headers={"Authorization": os.environ["CALLERS_API_KEY"]},
    json={
        "name": "Customer follow-up calls",
        "voiceId": "507f1f77bcf86cd799439011",
        "phoneNumbers": ["+14155552671"],
        "callParams": {"language": "en-US", "timezone": "America/New_York"},
        "steps": [
            {
                "id": "greeting",
                "type": "OTHER",
                "template": "Hello {{name}}, this is the support team.",
                "meeting": None,
                "description": None,
            }
        ],
    },
).json()["data"]
```

The Endpoints reference for **Create an agent** has more examples, including a WhatsApp agent, an Email agent, a Trigger agent, and an agent with an in-call HTTP action (`toolFunctions`).

> [!NOTE]
>
> Server-managed fields (owner, audit fields, generated credentials, provider-managed values) are always set by Callers and can't be sent.

## Replace an agent

`PUT /agents/{agentId}` replaces the agent's entire writable configuration using the same schema as create. Fields you omit go back to their defaults, arrays you send replace existing arrays, and `null` clears nullable fields. Voice and phone numbers aren't inferred, so include them.

The agent's running state is kept, except that changing an agent to `TRIGGER` activates it.

> [!WARNING]
>
> `PUT` is a full replacement. To change only the name, phone numbers, or webhooks, use `PATCH`. To change anything else, `GET` the agent first, modify the configuration, and `PUT` the complete result.

## Update name, phone numbers, or webhooks

`PATCH /agents/{agentId}` accepts any combination of `name`, `phoneNumbers`, and `webhooks` (at least one). It returns `{ "success": true }`.

```bash cURL theme={"dark"}
curl -X PATCH "https://api.callers.ai/agents/$AGENT_ID" \
  -H "Authorization: $CALLERS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Renewals Q4", "phoneNumbers": ["+14155552671", "+14155552672"] }'
```

```javascript Node.js theme={"dark"}
await fetch(`https://api.callers.ai/agents/${agentId}`, {
  method: "PATCH",
  headers: {
    Authorization: process.env.CALLERS_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "Renewals Q4", phoneNumbers: ["+14155552671", "+14155552672"] }),
});
```

```python Python theme={"dark"}
requests.patch(
    f"https://api.callers.ai/agents/{agent_id}",
    headers={"Authorization": os.environ["CALLERS_API_KEY"]},
    json={"name": "Renewals Q4", "phoneNumbers": ["+14155552671", "+14155552672"]},
)
```

`phoneNumbers` and `webhooks` replace the current lists. Send `"webhooks": []` to remove all of the agent's webhooks. To add one webhook without touching the others, use `POST /agents/{agentId}/webhook/subscribe` instead.

## Duplicate an agent

`POST /agents/{agentId}/duplicate` copies an agent, including its script and settings, and returns the new agent's `id`.

| Query parameter | Description |
| - | - |
| `name` | Name for the copy. |
| `toOrganizationId` | Copy into one of your subaccounts instead of the same account. |

```bash theme={"dark"}
curl -X POST "https://api.callers.ai/agents/$AGENT_ID/duplicate?name=Acme%20renewals&toOrganizationId=$SUBACCOUNT_ID" \
  -H "Authorization: $CALLERS_API_KEY"
```

This is the recommended way to roll out a template agent to many subaccounts. After duplicating, `PATCH` the copy's phone numbers and webhooks for that subaccount (using `x-sub-organization-id`). The request fails if the target account has reached its agent limit.

## Start and stop

`POST /agents/{agentId}/start` and `POST /agents/{agentId}/stop`. Starting an active agent returns `400 Campaign already activated.`; stopping a stopped agent returns `400 Campaign not activated.` See [Launch outbound calls](https://docs.callers.ai/api-reference/guides/launch-outbound-calls.md).

## Delete an agent

`DELETE /agents/{agentId}` archives the agent: it stops running workflows and releases provider configuration, but keeps the agent's data, contacts, and calls. It returns `{ "success": true }`. Archived agents can be restored from the dashboard.

## Success criteria

`POST /agents/{agentId}/update/interestcriteria` replaces the agent's success criteria. Criteria are grouped into goal-reached (`interested`) and goal-not-reached (`notInterested`) lists.

```bash theme={"dark"}
curl -X POST "https://api.callers.ai/agents/$AGENT_ID/update/interestcriteria" \
  -H "Authorization: $CALLERS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "successCriteria": {
      "interested": [
        { "name": "Demo Scheduled", "description": "The contact agreed to a demo date and time.", "type": "INTERESTED", "order": 0, "default": false, "immutable": false }
      ],
      "notInterested": [
        { "name": "Not a fit", "description": "The contact said the product is not relevant.", "type": "NOT_INTERESTED", "order": 0, "default": false, "immutable": false }
      ]
    }
  }'
```

Criterion names appear in webhook payloads (`successCriteria.name`) and as webhook events (`POST_PROCESSING_FINISHED:Demo Scheduled`). See [Success criteria](https://docs.callers.ai/documentation/results/success-criteria.md).

## Agent groups

Agent groups organize agents in the dashboard. `GET /agent-groups` returns each group's `id`, `name`, and `campaignsCount`; `GET /agent-groups/{agentGroupId}` returns one group. To create an agent inside a group, send `agentGroupId` on create.

## Speech recognition vocabulary

Help the agent recognize product names, brands, and jargon.

| Method and path | Body | Effect |
| - | - | - |
| `GET /agents/{agentId}/vocabulary` | — | List entries. |
| `POST /agents/{agentId}/vocabulary` | `{ "vocabulary": [{ "content", "sounds_like"? }] }` | Add entries (1–1,000 per request, up to 50 `sounds_like` each). |
| `PUT /agents/{agentId}/vocabulary` | Same | Update entries that already exist (matched by `content`); others are ignored. |
| `POST /agents/{agentId}/vocabulary/remove` | `{ "words": ["…"] }` | Remove specific entries (1–1,000 per request). |
| `DELETE /agents/{agentId}/vocabulary` | — | Clear all entries. |

```bash theme={"dark"}
curl -X POST "https://api.callers.ai/agents/$AGENT_ID/vocabulary" \
  -H "Authorization: $CALLERS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"vocabulary": [{"content": "Callers", "sounds_like": ["callers dot ai"]}, {"content": "HubSpot"}]}'
```

See [Speech recognition vocabulary](https://docs.callers.ai/documentation/voice/speech-recognition-vocabulary.md).

## Troubleshooting

> **503 'Campaign management API is currently unavailable'**
>
> Creating, replacing, updating, and deleting agents is temporarily unavailable. Retry later. Reading, starting, and stopping agents are not affected.

> **The agent was created but doesn't call**
>
> New call agents start stopped. Check it has a voice and a phone number, add contacts, and call `start`.

> **PUT reset settings I didn't send**
>
> `PUT` is a full replacement. Read the agent, change what you need, and send the complete configuration, or use `PATCH` for name, phone numbers, and webhooks.

> **404 Campaign not found**
>
> The agent doesn't exist in the account you're acting on. Check the ID and the `x-sub-organization-id` header.

## Related

> **[Create an agent in the dashboard](https://docs.callers.ai/documentation/build-your-agent/starting-a-new-agent.md)**
>
> Build and test agents visually.

> **[Subaccounts and SIP](https://docs.callers.ai/api-reference/guides/subaccounts-and-sip.md)**
>
> Roll agents out across subaccounts.

> **[Voices and cloning](https://docs.callers.ai/api-reference/guides/voices-and-cloning.md)**
>
> Find and create voice IDs.

> **[Webhooks overview](https://docs.callers.ai/documentation/webhook/webhook-overview.md)**
>
> Configure where results are sent.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.