> ## 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.

# Batches API

> Group contacts and dispatch outbound calls under a campaign

## Overview

A **Batch** is a group of contacts dispatched together under a [Campaign](/api-reference/campaigns/overview). When you create a batch, Apollo immediately begins dispatching calls to every contact (or waits until `scheduled_start` if set).

Batches inherit the parent campaign's retry policy, working hours, phone number strategy, and concurrency settings — but each of these can be overridden per-batch.

**Base URL:** `https://api.graine.ai/api/v1`

**Authentication:** All batch endpoints require `Authorization: Bearer gat_<token>`.

## Batch Object

```json theme={null}
{
  "batch_id": "btc_xyz001",
  "campaign_id": "cmp_abc123",
  "organization_id": "org_xyz",
  "status": "in_progress",
  "total_contacts": 100,
  "concurrency_limit": 10,
  "scheduled_start": null,
  "counters": {
    "pending": 22,
    "dispatched": 3,
    "in_flight": 5,
    "retrying": 4,
    "completed": 58,
    "failed": 3,
    "busy": 5,
    "no_answer": 0
  },
  "created_at": "2026-05-08T09:00:00Z",
  "updated_at": "2026-05-10T08:30:00Z"
}
```

## Batch Fields

| Field                  | Type     | Description                                                       |
| ---------------------- | -------- | ----------------------------------------------------------------- |
| `batch_id`             | string   | Unique identifier                                                 |
| `campaign_id`          | string   | Parent campaign                                                   |
| `organization_id`      | string   | Owning org                                                        |
| `status`               | string   | Current state (see lifecycle below)                               |
| `total_contacts`       | integer  | Total contacts uploaded to this batch                             |
| `concurrency_limit`    | integer  | Max parallel calls. Inherits from campaign if not set             |
| `scheduled_start`      | datetime | When to start dispatching. `null` = immediately                   |
| `counters`             | object   | Live real-time contact status breakdown                           |
| `max_retries_override` | integer  | Overrides `campaign.retry_policy.max_retries` for this batch only |

## Batch Status Lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending : created with scheduled_start
    [*] --> in_progress : created without scheduled_start
    pending --> in_progress : scheduled_start reached
    in_progress --> paused : /pause
    paused --> in_progress : /resume
    in_progress --> completed : all contacts terminal
    in_progress --> cancelled : /cancel
    paused --> cancelled : /cancel
```

| Status        | Description                           |
| ------------- | ------------------------------------- |
| `pending`     | Waiting for `scheduled_start`         |
| `in_progress` | Actively dispatching calls            |
| `paused`      | Stopped — resumes with `/resume`      |
| `completed`   | All contacts reached a terminal state |
| `cancelled`   | Hard-stopped. Terminal                |
| `expired`     | Passed end window without completing  |

## Contact Status Values

Each contact within a batch can be in one of these states:

| Status                | Description                               |
| --------------------- | ----------------------------------------- |
| `pending`             | Waiting to be dispatched                  |
| `dispatched`          | Published to Kafka — call is being placed |
| `in_progress`         | Call actively ringing or in conversation  |
| `retrying`            | Scheduled for a retry attempt             |
| `followup_scheduled`  | A follow-up call is scheduled             |
| `completed`           | Call was answered and completed           |
| `failed`              | Call failed (network/provider error)      |
| `busy`                | Line was busy                             |
| `no_answer`           | No answer within timeout                  |
| `skipped`             | Manually skipped — no further attempts    |
| `max_retries_reached` | Exhausted all retry attempts              |

## Endpoints

<CardGroup cols={2}>
  <Card title="Create Batch" icon="plus" href="/api-reference/batches/create">
    POST /batches/
  </Card>

  <Card title="List Batches" icon="list" href="/api-reference/batches/list">
    GET /batches/
  </Card>

  <Card title="Get Batch" icon="eye" href="/api-reference/batches/get">
    GET /batches/:id
  </Card>

  <Card title="List Batch Contacts" icon="users" href="/api-reference/batches/contacts">
    GET /batches/:id/contacts
  </Card>

  <Card title="Export CSV" icon="file-csv" href="/api-reference/batches/export">
    GET /batches/:id/export.csv
  </Card>

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

  <Card title="Force Dispatch" icon="bolt" href="/api-reference/batches/dispatch">
    POST /batches/:id/dispatch
  </Card>

  <Card title="Debug Batch" icon="bug" href="/api-reference/batches/debug">
    GET /batches/:id/debug
  </Card>
</CardGroup>
