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

# Campaigns: Batch Dialing Jobs in Scalysis Explained

> A campaign is a batch dialing job in Scalysis. Learn how campaigns work, how to upload contacts, control concurrency, and manage campaign state.

A campaign is how you dial a large list of contacts in one coordinated operation. Instead of triggering individual calls one at a time, you upload your contact list, assign a script, and Scalysis handles the scheduling and dialing automatically. Campaigns are the right tool whenever you need to reach more than a handful of people — whether you are confirming cash-on-delivery orders, running a re-engagement list, or handling failed delivery follow-ups.

## Campaign Lifecycle

Campaigns move through a defined set of states from creation to completion. Understanding this lifecycle helps you know when to start, pause, or inspect a campaign.

| State         | Meaning                                            |
| ------------- | -------------------------------------------------- |
| `not_started` | Campaign was created but dialing has not begun.    |
| `running`     | Scalysis is actively dialing contacts.             |
| `paused`      | Dialing is temporarily suspended; can be resumed.  |
| `completed`   | All contacts have been processed.                  |
| `stopped`     | Campaign was manually stopped and will not resume. |

Campaigns are created in the `not_started` state by default. Use the `startImmediately` flag (see below) to move directly to `running` on creation, or start the campaign manually via the API or dashboard later.

```text theme={null}
not_started ──► running ──► paused ──► running
                   │
                   ├──► completed
                   └──► stopped
```

## Campaign Kinds

Scalysis supports three campaign kinds, each optimised for a different merchant workflow:

<CardGroup cols={3}>
  <Card title="cod" icon="money-bill">
    **Cash-on-Delivery** — Confirm COD orders with customers before dispatch to reduce return rates.
  </Card>

  <Card title="list" icon="list">
    **List** — General-purpose outbound dialing for any contact list, such as re-engagement or surveys.
  </Card>

  <Card title="ndr" icon="rotate-left">
    **NDR (Non-Delivery Report)** — A specialised flow for following up on failed delivery attempts.
  </Card>
</CardGroup>

Set the `kind` field when creating a campaign to select the appropriate flow.

## Uploading Contacts

You can supply contacts to a campaign in two ways:

### contacts\[] Array (recommended for API use)

Pass contacts as a JSON array of objects. Each object should include the fields your script expects (at minimum a phone number):

```json theme={null}
{
  "scriptId": 2207,
  "kind": "cod",
  "contacts": [
    { "phone": "+911234567890", "orderNumber": "ORD-001", "brand_name": "Acme Store" },
    { "phone": "+919876543210", "orderNumber": "ORD-002", "brand_name": "Acme Store" }
  ]
}
```

### csvText String

If you have a CSV export from your order management system, pass the raw CSV content as a string in the `csvText` field:

```json theme={null}
{
  "scriptId": 2207,
  "kind": "cod",
  "csvText": "phone,orderNumber,brand_name\n+911234567890,ORD-001,Acme Store\n+919876543210,ORD-002,Acme Store"
}
```

<Tip>
  Prefer the `contacts[]` array for programmatic integrations — it is easier to validate and debug than a raw CSV string. Use `csvText` when you already have a CSV export and want to forward it directly without parsing.
</Tip>

The maximum number of contacts per create request is approximately **2,000**. If your list is larger, split it across multiple campaign creation calls.

## Key Campaign Options

### startImmediately

Controls whether dialing begins as soon as the campaign is created.

* `true` — the campaign moves to `running` immediately after creation.
* `false` *(default)* — the campaign is created in `not_started` state; you start it manually.

```json theme={null}
{
  "startImmediately": true
}
```

### maxConcurrency

Sets the maximum number of simultaneous outbound calls Scalysis will place for this campaign. This is useful for rate-limiting your outreach or staying within carrier thresholds.

```json theme={null}
{
  "maxConcurrency": 5
}
```

<Note>
  The server may enforce an upper cap on `maxConcurrency` regardless of the value you provide. Contact Scalysis support if you need a higher concurrency limit for your account.
</Note>

## Creating a Campaign

Send a `POST` request to `/api/v1/campaigns` with your contact list, script, and options. A successful response returns the `campaign_id` you will use for all subsequent control operations.

```json theme={null}
{
  "scriptId": 2207,
  "kind": "cod",
  "startImmediately": false,
  "maxConcurrency": 5,
  "contacts": [
    { "phone": "+911234567890", "orderNumber": "ORD-001", "brand_name": "Acme Store" },
    { "phone": "+919876543210", "orderNumber": "ORD-002", "brand_name": "Acme Store" }
  ]
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "campaign_id": "abc123xyz"
}
```

<Note>
  Save the `campaign_id` immediately. You will need it to start, pause, resume, or stop the campaign through subsequent API calls.
</Note>

## Controlling a Campaign

Once a campaign is created, use `POST /api/v1/campaigns/{campaign_id}/control` to change its state. Pass an `action` field in the request body:

| Action   | Effect                                                  |
| -------- | ------------------------------------------------------- |
| `start`  | Move the campaign from `not_started` to `running`.      |
| `pause`  | Suspend dialing; the campaign enters `paused` state.    |
| `resume` | Restart dialing after a pause; returns to `running`.    |
| `stop`   | Permanently halt the campaign; sets state to `stopped`. |

```json theme={null}
{
  "action": "pause"
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "campaign_id": "abc123xyz",
  "status": "paused"
}
```

<Tip>
  Use `pause` and `resume` to temporarily hold dialing during peak hours or when you need to update your contact list. Use `stop` only when you want to permanently end the campaign — a stopped campaign cannot be restarted.
</Tip>
