# Update campaign

> PATCH /campaigns/:id — edit a draft campaign.

`PATCH /campaigns/:id`

Partially updates a campaign. Only a **draft** can be edited — any other status (`scheduled`, `queued`, `paused`, `recurring`, `canceled`, `sent` or `failed`) returns a `validation_error`. Send only the fields you want to change.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | The ID of the campaign you want to update. |

**Body parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `domain` | string | No | Re-point the campaign at another sending domain’s contacts (draft only). Must be one of your domains. Changing the domain automatically clears `segment_id` and `topic_id` unless new values are provided in the same request. Passing `audience_id` is no longer accepted. |
| `from` | string | No | Sender address on a verified domain. |
| `subject` | string | No | Subject line. |
| `reply_to` | string | string[] | No | Reply-To address. For multiple addresses, send an array of strings. |
| `html` | string | No | HTML body. |
| `text` | string | No | Plain-text body. If omitted, a plain-text version is generated from the HTML; set it to an empty string to opt out. |
| `name` | string | No | The friendly name of the campaign. Only used for internal reference. |
| `preview_text` | string | null | No | Inbox preview text shown after the subject line (max **150 characters**; supports merge tags). Pass `null` to clear. |
| `segment_id` | string | null | No | Re-target a segment. Pass `null` to remove the segment filter. The segment must belong to the same domain. |
| `topic_id` | string | null | No | Re-target a topic gate. Pass `null` to remove it. |
| `schedule_timezone` | string | null | No | IANA timezone name (e.g. `America/New_York`) the campaign’s `scheduled_at` wall-clock time is interpreted in — also the zone daily batches roll over in. A `scheduled_at` that already carries a UTC offset (e.g. a trailing `Z`) is used as-is. Pass `null` to clear (batch rollover then falls back to your account timezone; an offset-less `scheduled_at` is read as UTC). |
| `daily_batch_size` | number | null | No | Send to at most this many recipients per day — an integer between `1` and `100000`. Delivery continues the next day at the same local time until every contact is reached. Pass `null` to send to everyone at once. |

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.campaigns.update('8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90', { "subject": "Updated subject" });
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Campaigns.update("8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90", {
  "subject": "Updated subject"
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->campaigns->update('8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90', [
  'subject' => "Updated subject"
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Campaigns.update("8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90", {
  "subject": "Updated subject"
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

updated, err := client.Campaigns.Update("8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90", &sendping.UpdateCampaignRequest{
    Subject: "Updated subject",
})
```

**Rust**

```rust
use sendping::{SendPing, UpdateCampaignOptions};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = UpdateCampaignOptions::new().with_subject("Updated subject");
let _updated = mb.campaigns.update("8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90", params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.UpdateCampaignRequest;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

SendPingResponse response = sendping.campaigns().update(
        "8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90",
        UpdateCampaignRequest.builder().subject("Updated subject").build());
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.CampaignUpdateAsync(
    "8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90",
    new CampaignUpdateOptions { Subject = "Updated subject" });
```

**cURL**

```bash
curl -X PATCH 'https://www.sendping.co/api/campaigns/8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{ "subject": "Updated subject" }'
```

**CLI**

```bash
sendping campaigns update 8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90 \
  --subject 'Updated subject'
```

### Response

```json
{
  "id": "8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90"
}
```

> **Note:** Errors: `not_found` if the campaign is not yours; `validation_error` if it is not a draft, `domain` does not reference one of your domains, or `audience_id` is passed (no longer accepted).
