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

# Create Batch

> Upload contacts and begin dispatching outbound calls

## Endpoint

**POST** `https://api.graine.ai/api/v1/batches/`

Also available as **POST** `/batches/upload` (Merlin alias — identical behaviour).

Creating a batch immediately begins dispatching calls to all contacts (unless `scheduled_start` is set).

## Headers

| Header          | Required | Description          |
| --------------- | -------- | -------------------- |
| `Authorization` | Yes      | `Bearer gat_<token>` |
| `Content-Type`  | Yes      | `application/json`   |

## Request Body

| Field                  | Type       | Required | Description                                                  |
| ---------------------- | ---------- | -------- | ------------------------------------------------------------ |
| `campaign_id`          | string     | Yes      | The campaign this batch belongs to                           |
| `contacts`             | Contact\[] | Yes      | List of contacts to call (see schema below)                  |
| `organization_id`      | string     | No       | Defaults to token's org                                      |
| `scheduled_start`      | datetime   | No       | When to begin dispatching. `null` = immediately              |
| `concurrency_limit`    | integer    | No       | Max concurrent calls. Overrides campaign setting             |
| `max_retries_override` | integer    | No       | Overrides `campaign.retry_policy.max_retries` for this batch |
| `call_context`         | object     | No       | Additional context passed to the telephony layer             |
| `metadata`             | object     | No       | Arbitrary metadata stored with the batch                     |

### Contact schema

| Field            | Type   | Required | Description                                      |
| ---------------- | ------ | -------- | ------------------------------------------------ |
| `phone_number`   | string | Yes      | E.164 format (e.g. `+919876543210`)              |
| `call_variables` | object | No       | Per-contact substitution variables for the agent |

<Warning>
  `callee_name` **must** be in `call_variables` for each contact (not in campaign `default_call_variables`). The AI agent uses this in its greeting — without it, the agent cannot address the person by name.
</Warning>

### scheduled\_start timezone handling

| Value                            | Behaviour                                                                             |
| -------------------------------- | ------------------------------------------------------------------------------------- |
| `null` (default)                 | Dispatch begins immediately                                                           |
| Naive datetime (no `Z` / offset) | Interpreted in the **campaign's timezone** (e.g. `"2026-05-10T11:00:00"` → 11 AM IST) |
| UTC datetime (with `Z`)          | Used as-is                                                                            |

## Example Request

```json theme={null}
{
  "campaign_id": "cmp_abc123",
  "organization_id": "org_xyz",
  "contacts": [
    {
      "phone_number": "+919876543210",
      "call_variables": {
        "callee_name": "Rajesh Sharma",
        "current_plan": "Basic Health",
        "renewal_date": "2026-07-01",
        "premium": "12000"
      }
    },
    {
      "phone_number": "+919876543211",
      "call_variables": {
        "callee_name": "Priya Mehta",
        "current_plan": "Family Floater",
        "renewal_date": "2026-06-15",
        "premium": "28000"
      }
    }
  ],
  "concurrency_limit": 10,
  "scheduled_start": null
}
```

### Schedule for a specific time

```json theme={null}
{
  "campaign_id": "cmp_abc123",
  "contacts": [...],
  "scheduled_start": "2026-05-12T09:00:00"
}
```

This starts at 9:00 AM in the campaign's timezone (e.g. Asia/Kolkata).

## Responses

### 200 OK

```json theme={null}
{
  "batch_id": "btc_xyz001",
  "campaign_id": "cmp_abc123",
  "organization_id": "org_xyz",
  "status": "in_progress",
  "total_contacts": 2,
  "created_at": "2026-05-10T09:00:00Z"
}
```

<Tip>
  Save the returned `batch_id` — use it to track progress, export results, or pause/cancel this batch independently.
</Tip>

### 400 Bad Request

```json theme={null}
{ "detail": "campaign_id is required" }
```

### 404 Not Found

```json theme={null}
{ "detail": "Campaign not found or does not belong to this org" }
```

## Code Examples

```python theme={null}
import requests

url = "https://api.graine.ai/api/v1/batches/"
headers = {
    "Authorization": "Bearer gat_your_token",
    "Content-Type": "application/json"
}
payload = {
    "campaign_id": "cmp_abc123",
    "contacts": [
        {
            "phone_number": "+919876543210",
            "call_variables": {
                "callee_name": "Rajesh Sharma",
                "current_plan": "Basic Health",
                "renewal_date": "2026-07-01",
                "premium": "12000"
            }
        }
    ],
    "concurrency_limit": 10
}

response = requests.post(url, json=payload, headers=headers)
batch = response.json()
print(batch["batch_id"])
```

```javascript theme={null}
const response = await fetch("https://api.graine.ai/api/v1/batches/", {
  method: "POST",
  headers: {
    "Authorization": "Bearer gat_your_token",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    campaign_id: "cmp_abc123",
    contacts: [
      {
        phone_number: "+919876543210",
        call_variables: {
          callee_name: "Rajesh Sharma",
          current_plan: "Basic Health",
          renewal_date: "2026-07-01",
          premium: "12000"
        }
      }
    ],
    concurrency_limit: 10
  })
});

const batch = await response.json();
console.log(batch.batch_id);
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Monitor Contacts" icon="users" href="/api-reference/batches/contacts">
    Track per-contact call status
  </Card>

  <Card title="Export Results" icon="file-csv" href="/api-reference/batches/export">
    Download call outcomes as CSV
  </Card>

  <Card title="Pause or Cancel" icon="circle-pause" href="/api-reference/batches/lifecycle">
    Control batch execution mid-flight
  </Card>

  <Card title="Troubleshoot Stuck Batch" icon="bug" href="/api-reference/batches/debug">
    Debug why calls aren't going out
  </Card>
</CardGroup>
