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

# Make Campaign Call

> Initiate a call as part of a specific campaign

# Make a campaign call

Queues a call under a specific campaign. The call inherits the campaign's agent, schedule, retry policy, and DNC rules.

For one-off calls (not subject to campaign scheduling), use [Make a call](/en/api-reference/endpoints/make-call) instead.

## Endpoint

```
POST /api/v1/campaigns/{campaign_id}/call
```

## Path parameters

<ParamField path="campaign" type="string" required>
  The unique identifier of the campaign.
</ParamField>

## Request headers

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication. Format: `Bearer talq_your_environment_token_here`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Application JSON. Format: `application/json`
</ParamField>

## Request body

<ParamField body="to" type="string" required>
  Phone number to call in E.164 format (e.g., "+1234567890").
</ParamField>

<ParamField body="payload" type="object" required={false}>
  Replacement variables for the campaign agent prompt. Use this to personalize the conversation with dynamic data. Keys should match placeholders in your agent's prompt.
</ParamField>

<ParamField body="context" type="object" required={false}>
  Custom data to be sent back to your client via webhooks. This data is not used in the conversation but will be included in all webhook events related to this call, allowing you to track and associate calls with your internal records.
</ParamField>

<ParamField body="is_testing" type="boolean" required={false}>
  Whether this is a test call. Test calls do not consume billing credits and are excluded from analytics aggregates. Default: `false`.
</ParamField>

<ParamField body="allow_duplicates" type="boolean" required={false}>
  Whether to allow placing this call even if the same `to` number already has an active or queued call within the campaign. When `false` (default), the request returns `409 Conflict` with the existing call's details so you can avoid duplicate outreach. Default: `false`.
</ParamField>

## Example requests

<RequestExample>
  ```bash theme={null}
  # Request 1: Make a regular campaign call
  curl -X POST "https://app.talkover.ai/api/v1/campaigns/campaign-uuid-1/call" \
    -H "Authorization: Bearer talq_your_environment_token_here" \
    -H "Content-Type: application/json" \
    -d '{
      "to": "+1234567890"
    }'
  ```

  ```javascript theme={null}
  // Request 1: Make a regular campaign call
  const response = await fetch('https://app.talkover.ai/api/v1/campaigns/campaign-uuid-1/call', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer talq_your_environment_token_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      to: '+1234567890'
    })
  });

  const result = await response.json();
  console.log(result);
  ```
</RequestExample>

<RequestExample>
  ```bash theme={null}
  # Request 2: Make a test campaign call
  curl -X POST "https://app.talkover.ai/api/v1/campaigns/campaign-uuid-1/call" \
    -H "Authorization: Bearer talq_your_environment_token_here" \
    -H "Content-Type: application/json" \
    -d '{
      "to": "+1234567890",
      "is_testing": true
    }'
  ```

  ```javascript theme={null}
  // Request 2: Make a test campaign call
  const response = await fetch('https://app.talkover.ai/api/v1/campaigns/campaign-uuid-1/call', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer talq_your_environment_token_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      to: '+1234567890',
      is_testing: true
    })
  });

  const result = await response.json();
  console.log(result);
  ```
</RequestExample>

<RequestExample>
  ```bash theme={null}
  # Request 3: Make campaign call with payload and context
  curl -X POST "https://app.talkover.ai/api/v1/campaigns/campaign-uuid-1/call" \
    -H "Authorization: Bearer talq_your_environment_token_here" \
    -H "Content-Type: application/json" \
    -d '{
      "to": "+1987654321",
      "payload": {
        "customer_name": "John Doe",
        "order_id": "12345",
        "product_name": "Premium Plan"
      },
      "context": {
        "user_id": "user_123",
        "source": "web_app",
        "campaign_batch": "2024_Q1"
      }
    }'
  ```

  ```javascript theme={null}
  // Request 3: Make campaign call with payload and context
  const response = await fetch('https://app.talkover.ai/api/v1/campaigns/campaign-uuid-1/call', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer talq_your_environment_token_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      to: '+1987654321',
      payload: {
        customer_name: 'John Doe',
        order_id: '12345',
        product_name: 'Premium Plan'
      },
      context: {
        user_id: 'user_123',
        source: 'web_app',
        campaign_batch: '2024_Q1'
      }
    })
  });

  const result = await response.json();
  console.log(result);
  ```
</RequestExample>

## Response

### Success Response (201 Created)

<ResponseExample>
  ```json theme={null}
  {
    "campaign_call": {
      "id": "call-uuid-1",
      "campaign_id": "campaign-uuid-1",
      "to": "+1234567890",
      "status": "queued",
      "scheduled_at": "2024-01-15T10:30:00Z",
      "created_at": "2024-01-15T10:30:00Z"
    },
    "campaign": {
      "id": "campaign-uuid-1",
      "name": "Q1 Outreach",
      "status": "active"
    }
  }
  ```
</ResponseExample>

### Response fields

<ResponseField name="campaign_call" type="object" required>
  Details of the queued campaign call.

  <Expandable title="Campaign Call Object">
    <ResponseField name="id" type="string" required>
      Unique identifier for the campaign call. Use this to track status and correlate with webhook events.
    </ResponseField>

    <ResponseField name="campaign_id" type="string" required>
      The campaign this call belongs to.
    </ResponseField>

    <ResponseField name="to" type="string" required>
      The phone number that will be called.
    </ResponseField>

    <ResponseField name="status" type="string" required>
      Initial status of the campaign call. Possible values:

      * `queued` — call accepted and waiting for dispatch
      * `scheduled` — call scheduled to be placed at a future time within campaign hours
    </ResponseField>

    <ResponseField name="scheduled_at" type="string">
      ISO 8601 timestamp when the call is expected to be placed.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      ISO 8601 timestamp when the campaign call was created.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="campaign" type="object" required>
  Summary of the parent campaign at the time the call was queued.
</ResponseField>

## Error responses

### 409 Conflict — Duplicate Call

Returned when a call to the same `to` number is already active or queued in this campaign and `allow_duplicates` is `false`.

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "A call to this number already exists in this campaign",
    "existing_call": {
      "id": "call-uuid-existing",
      "campaign_id": "campaign-uuid-1",
      "to": "+1234567890",
      "status": "queued",
      "created_at": "2024-01-15T09:50:00Z"
    }
  }
  ```
</ResponseExample>

To override this behavior intentionally (e.g., a follow-up call), pass `"allow_duplicates": true` in the request body.

### 404 Not Found

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Campaign not found"
  }
  ```
</ResponseExample>

### 422 Validation Error

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "The given data was invalid.",
    "errors": {
      "to": [
        "The to field is required."
      ],
      "to": [
        "The to must be a valid phone number."
      ]
    }
  }
  ```
</ResponseExample>

### 400 Bad Request

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Campaign is not active"
  }
  ```
</ResponseExample>

### 401 Unauthorized

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Unauthorized"
  }
  ```
</ResponseExample>

### 403 Forbidden

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Cannot make calls for this campaign"
  }
  ```
</ResponseExample>

### 429 Too Many Requests

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Rate limit exceeded"
  }
  ```
</ResponseExample>

### 500 Server Error

<ResponseExample>
  ```json theme={null}
  {
    "success": false,
    "message": "Internal server error."
  }
  ```
</ResponseExample>

## Error codes

| Code                  | Description                                             | HTTP Status |
| --------------------- | ------------------------------------------------------- | ----------- |
| `CAMPAIGN_NOT_FOUND`  | Specified campaign does not exist                       | 404         |
| `VALIDATION_ERROR`    | Request validation failed                               | 422         |
| `CAMPAIGN_NOT_ACTIVE` | Campaign is not in active status                        | 400         |
| `DUPLICATE_CALL`      | An existing call to the same number is queued or active | 409         |
| `INVALID_TOKEN`       | Authentication token is invalid or missing              | 401         |
| `FORBIDDEN`           | Cannot make calls for this campaign                     | 403         |
| `RATE_LIMIT_EXCEEDED` | Rate limit exceeded                                     | 429         |
| `SERVER_ERROR`        | Internal server error occurred                          | 500         |

## Campaign Status Requirements

| Campaign Status | Can Make Calls | Notes                   |
| --------------- | -------------- | ----------------------- |
| `draft`         | No             | Campaign must be active |
| `active`        | Yes            | Calls can be made       |
| `paused`        | No             | Campaign is paused      |
| `completed`     | No             | Campaign has finished   |
| `cancelled`     | No             | Campaign was cancelled  |

## Important notes

<Info>
  **Campaign context.** Calls made through this endpoint are associated with the specific campaign.
</Info>

<Info>
  **Campaign settings.** The call will follow the campaign's configuration (agent, retry logic, etc.).
</Info>

<Info>
  **Test calls.** Use `is_testing: true` for test calls that don't count toward billing.
</Info>

<Warning>
  **Active campaigns only.** Calls can only be made for campaigns in "active" status.
</Warning>

<Warning>
  **Rate limits.** Be aware of rate limits when making multiple calls.
</Warning>

## Related endpoints

* **Get Campaign**: `GET /api/v1/campaigns/{campaign_id}`
* **Update Campaign Status**: `PATCH /api/v1/campaigns/{campaign_id}/status`
* **Make a Call**: `POST /api/v1/calls`
* **List Calls**: `GET /api/v1/calls`
* **Get Agent Calls**: `GET /api/v1/agents/{agent_id}/calls`
