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

# Campaign Stats

> Live granular statistics for a campaign

## Endpoints

| Endpoint                          | Description                               |
| --------------------------------- | ----------------------------------------- |
| **GET** `/campaigns/{id}/stats`   | Aggregated stats across all batches       |
| **GET** `/campaigns/{id}/batches` | Per-batch breakdown with contact counters |

***

## Get Campaign Stats

**GET** `https://api.graine.ai/api/v1/campaigns/{campaign_id}/stats`

Returns live granular stats computed in real-time from the contacts and call\_records collections.

### Path Parameters

| Parameter     | Type   | Required | Description         |
| ------------- | ------ | -------- | ------------------- |
| `campaign_id` | string | Yes      | Campaign to inspect |

### Example Request

```bash theme={null}
curl "https://api.graine.ai/api/v1/campaigns/cmp_abc123/stats" \
  -H "Authorization: Bearer gat_your_token"
```

### Response 200 OK

```json theme={null}
{
  "campaign_id": "cmp_abc123",
  "contact_counts": {
    "pending": 45,
    "dispatched": 3,
    "in_progress": 8,
    "retrying": 12,
    "completed": 142,
    "failed": 8,
    "busy": 12,
    "no_answer": 25,
    "skipped": 2,
    "followup_scheduled": 5,
    "max_retries_reached": 3
  },
  "batch_counts": {
    "pending": 0,
    "in_progress": 2,
    "paused": 0,
    "completed": 1,
    "cancelled": 0
  },
  "call_counters": {
    "completed_calls": 142,
    "failed_calls": 8,
    "busy_calls": 12,
    "no_answer_calls": 25,
    "follow_up_calls": 5
  },
  "retry_breakdown": {
    "retry_1": 8,
    "retry_2": 3,
    "retry_3": 1
  },
  "in_flight_contacts": 28,
  "total_call_attempts": 217,
  "follow_up_attempts": 5
}
```

### Stats Field Reference

| Field                 | Description                                                                         |
| --------------------- | ----------------------------------------------------------------------------------- |
| `contact_counts`      | Per-status count of every contact across all batches                                |
| `batch_counts`        | Per-status count of every batch in this campaign                                    |
| `call_counters`       | Campaign-level call outcome counters (from campaign document)                       |
| `retry_breakdown`     | How many contacts are currently at retry 1, 2, 3, …                                 |
| `in_flight_contacts`  | Sum of contacts in `dispatched` + `in_progress` + `retrying` + `followup_scheduled` |
| `total_call_attempts` | Total dispatch attempts including all retries and follow-ups                        |
| `follow_up_attempts`  | Count of follow-up call records                                                     |

***

## List Campaign Batches

**GET** `https://api.graine.ai/api/v1/campaigns/{campaign_id}/batches`

Lists all batches under a campaign with live per-batch counters computed from contacts (never stale stored counters).

### Query Parameters

| Parameter         | Type    | Required | Description               |
| ----------------- | ------- | -------- | ------------------------- |
| `skip`            | integer | No       | Offset. Default: `0`      |
| `limit`           | integer | No       | Page size. Default: `50`  |
| `status`          | string  | No       | Filter by batch status    |
| `organization_id` | string  | No       | Scoped to org if provided |

### Example Request

```bash theme={null}
curl "https://api.graine.ai/api/v1/campaigns/cmp_abc123/batches?skip=0&limit=50" \
  -H "Authorization: Bearer gat_your_token"
```

### Response 200 OK

```json theme={null}
[
  {
    "batch_id": "btc_xyz001",
    "campaign_id": "cmp_abc123",
    "status": "in_progress",
    "total_contacts": 100,
    "counters": {
      "pending": 22,
      "dispatched": 3,
      "in_flight": 5,
      "retrying": 4,
      "completed": 58,
      "failed": 3,
      "busy": 5,
      "no_answer": 0
    },
    "retry_breakdown": {
      "retry_1": 3,
      "retry_2": 1
    },
    "created_at": "2026-05-08T09:00:00Z"
  }
]
```

<Note>
  `counters` in the batch list response are computed in real-time from two aggregations over the contacts + call\_records collections. They are never stale.
</Note>
