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

# Create Campaign

> Create and configure campaigns using the ColdSend API.

Create and configure cold email campaigns programmatically. Campaign activation follows a component-based approach where you provide the fields you want, then set `launch: true` when ready.

## Create a New Campaign

**POST** `/api/public/v1/campaigns`

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import requests

    api_key = "cs_live_your_api_key_here"
    base_url = "https://api.coldsend.pro"

    response = requests.post(
        f"{base_url}/api/public/v1/campaigns",
        headers={"X-API-Key": api_key},
        json={
            "name": "Q1 Product Launch Outreach",
            "timezone": "America/New_York",
            "sending_days": [1, 2, 3, 4, 5],
            "sending_window_start": 9,
            "sending_window_end": 17,
            "daily_limit_per_inbox": 30,
            "enable_tracking": True,
            "enable_unsubscribe": True
        }
    )

    campaign = response.json()
    campaign_id = campaign["campaign_id"]
    print(f"Campaign created: {campaign_id}")
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const apiKey = "cs_live_your_api_key_here";
    const baseUrl = "https://api.coldsend.pro";

    const response = await fetch(`${baseUrl}/api/public/v1/campaigns`, {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        name: "Q1 Product Launch Outreach",
        timezone: "America/New_York",
        sending_days: [1, 2, 3, 4, 5],
        sending_window_start: 9,
        sending_window_end: 17,
        daily_limit_per_inbox: 30,
        enable_tracking: true,
        enable_unsubscribe: true
      })
    });

    const campaign = await response.json();
    const campaignId = campaign.campaign_id;
    console.log(`Campaign created: ${campaignId}`);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST "https://api.coldsend.pro/api/public/v1/campaigns" \
      -H "X-API-Key: cs_live_your_api_key_here" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Q1 Product Launch Outreach",
        "timezone": "America/New_York",
        "sending_days": [1, 2, 3, 4, 5],
        "sending_window_start": 9,
        "sending_window_end": 17,
        "daily_limit_per_inbox": 30,
        "enable_tracking": true,
        "enable_unsubscribe": true
      }'
    ```
  </Tab>
</Tabs>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "success": true,
    "message": "Campaign created successfully",
    "campaign_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Q1 Product Launch Outreach",
    "status": "DRAFT",
    "created_at": "2024-01-15T10:30:00Z"
  }
  ```
</ResponseExample>

## Request Parameters

### Required Fields

| Parameter | Type   | Description                      |
| --------- | ------ | -------------------------------- |
| `name`    | string | Campaign name (8-255 characters) |

### Optional Fields

| Parameter                     | Type     | Default            | Description                                    |
| ----------------------------- | -------- | ------------------ | ---------------------------------------------- |
| `timezone`                    | string   | `America/New_York` | IANA timezone for scheduling                   |
| `sending_days`                | int\[]   | `[1,2,3,4,5]`      | Days to send (1=Mon, 7=Sun)                    |
| `sending_window_start`        | int      | `9`                | Start hour (0-23)                              |
| `sending_window_start_minute` | int      | `0`                | Start minute (0-59)                            |
| `sending_window_end`          | int      | `17`               | End hour (1-24)                                |
| `sending_window_end_minute`   | int      | `0`                | End minute (0-59)                              |
| `daily_limit_per_inbox`       | int      | null               | Max emails per inbox/day (1-100)               |
| `start_date`                  | datetime | null               | ISO 8601 start date                            |
| `enable_tracking`             | bool     | `false`            | Enable email open tracking                     |
| `enable_unsubscribe`          | bool     | `true`             | Include unsubscribe link                       |
| `ramp_up_enabled`             | bool     | `false`            | Gradually increase sending volume each day     |
| `ramp_up_increment`           | int      | system default     | Emails/inbox/day added per ramp-up day (1-100) |
| `ramp_up_max_limit`           | int      | system default     | Daily cap per inbox once fully ramped (1-1000) |

<Info>
  The sending window supports minute-precision. For example, `sending_window_start: 9` with `sending_window_start_minute: 30` starts at 9:30 AM. When `sending_window_end` is `24`, the minute must be `0`.
</Info>

## Update Campaign

**PUT** `/api/public/v1/campaigns/{campaign_id}`

Update any campaign field or activate it. Only include the fields you want to change.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    response = requests.put(
        f"{base_url}/api/public/v1/campaigns/{campaign_id}",
        headers={"X-API-Key": api_key},
        json={
            "name": "Updated Campaign Name",
            "inbox_ids": ["inbox-uuid"],
            "variants": [
                {
                    "variant_name": "A",
                    "subject_template": "Quick question about {{company}}",
                    "email_content": "Hi {{first_name}},\n\n...",
                    "distribution_percent": 100
                }
            ],
            "sequences": [...],
            "launch": True
        }
    )
    ```
  </Tab>
</Tabs>

### Updatable Fields

**Basic Settings:** name, timezone, sending\_days, sending\_window\_start, sending\_window\_start\_minute, sending\_window\_end, sending\_window\_end\_minute, daily\_limit\_per\_inbox, enable\_tracking, enable\_unsubscribe, start\_date, ramp\_up\_enabled, ramp\_up\_increment, ramp\_up\_max\_limit

<Note>
  Setting `ramp_up_enabled: true` resets the ramp-up counter for all assigned inboxes, so the gradual increase starts fresh.
</Note>

**Inboxes:** inbox\_ids — Array of inbox UUIDs to assign

**Email Content:** variants — Array of email variant objects for A/B testing

**Follow-ups:** sequences — Array of follow-up sequence objects

**Launch Control:** launch — Set to `true` to activate the campaign

### Launch Validation

When `launch: true`, the API checks:

* At least one lead exists
* At least one inbox is assigned
* At least one email variant is configured

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    response = requests.put(
        f"{base_url}/api/public/v1/campaigns/{campaign_id}",
        headers={"X-API-Key": api_key},
        json={"launch": True}
    )

    result = response.json()
    print(f"Launch ready: {result['is_launch_ready']}")
    print(f"Missing: {result['missing_requirements']}")
    ```
  </Tab>
</Tabs>

```json Response theme={null}
{
  "campaign_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "DRAFT",
  "is_launch_ready": false,
  "missing_requirements": ["leads", "variants"],
  ...
}
```

<Warning>
  If requirements are missing, the campaign remains in DRAFT. The `missing_requirements` field tells you exactly what's needed.
</Warning>

## Validation Errors

| Error                                                   | Cause                               |
| ------------------------------------------------------- | ----------------------------------- |
| `ensure this value has at least 8 characters`           | Campaign name too short             |
| `Invalid timezone: America/Invalid`                     | Invalid IANA timezone               |
| `sending_window_end must be after sending_window_start` | Window configuration invalid        |
| `Variant distributions must sum to 100%`                | Variant percentages don't total 100 |

## Best Practices

1. **Use descriptive names** — Include goal, target audience, or time period
2. **Match timezone to audience** — Prevents emails from sending at odd hours
3. **Start conservative with limits** — 20-50 emails/inbox/day for new accounts
4. **Enable tracking** — Essential for measuring campaign performance
5. **Test before launching** — Try with a few test leads first

## Next Steps

<CardGroup cols={3}>
  <Card title="Email Variants" href="/campaigns/variants" icon="files">
    Configure A/B testing and distribution.
  </Card>

  <Card title="Follow-up Sequences" href="/campaigns/sequences" icon="layers">
    Set up automated follow-up emails.
  </Card>

  <Card title="Personalization" href="/campaigns/personalization" icon="sparkles">
    Use variables, spintax, and conditionals.
  </Card>
</CardGroup>
