# Add up to 500 recipients. Retrying a batch is safe.

Source: https://docs.usetone.ai/reference/campaigns/addRecipients

> Duplicates are counted rather than rejected, so a request that timed out can simply be resent without double-dialling anyone.

`POST /v1/campaigns/{id}/recipients`
Duplicates are counted rather than rejected, so a request that timed out can simply be resent without double-dialling anyone. A campaign holds at most 20,000 recipients. Add them before launching; the list is fixed once dialling starts.

Requires the `write` scope.

## Parameters

| Name | In | | Meaning |
|---|---|---|---|
| `id` | path | required | The campaign's id. |

## Request body

| Field | Type | | Meaning |
|---|---|---|---|
| `recipients` | object[] | required | The recipients to add, 1-500 per request. Retrying an identical batch is safe: duplicates are counted, not errored, so a timed-out request can simply be resent. A campaign holds at most 20,000 recipients. |
| `recipients[].e164` | string | required | The number to dial, in E.164. |
| `recipients[].variables` | object | optional | Per-recipient values for the agent input variables — the mapped CSV columns for this row. Values are strings because that is what a CSV holds; the agent own variable typing does the coercion. |

### Example request

```json
{
  "recipients": [
    {
      "e164": "+919876543210",
      "variables": {
        "name": "Priya",
        "order_id": "AC-4417"
      }
    }
  ]
}
```

## Response

| Field | Type | | Meaning |
|---|---|---|---|
| `added` | integer | required | How many recipients this request added. Duplicates are counted here rather than rejected, so retrying an identical batch is safe. |
| `duplicates` | integer | required | Numbers already on this campaign. Skipped, not an error — which is what makes a retry safe. |
| `total` | integer | required | Recipients on the campaign now. |

### Example response

```json
{
  "data": {
    "added": 0,
    "duplicates": 0,
    "total": 0
  }
}
```
