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

# Reactivate campaign

> Resume a PAUSED campaign back to ACTIVE

`POST /api/v2/buyer/campaigns/:id/reactivate`

Brings a `PAUSED` campaign back to `ACTIVE`. This is the **only** way to resume a paused campaign. The resume is sent to every media buy the campaign pause stopped; a media buy you paused on its own stays paused. Media buys return to `ACTIVE` (post-flight if their dates allow).

If any of those media buys does not resume, the call returns an error and lists each buy's outcome. The campaign shows `ACTIVE` as soon as any of its media buys is delivering again, and stays `PAUSED` when none resumed.

<Note>
  `reactivate` and [execute](/v2/buyer/campaigns/tasks/execute-campaign) are distinct endpoints. `execute` launches a `DRAFT` or `COMPLETED` campaign for the first time (or relaunches it). `reactivate` resumes a `PAUSED` campaign.
</Note>

## Request

```bash theme={null}
curl -X POST https://api.apostra.com/api/v2/buyer/campaigns/cmp_987654321/reactivate \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

No request body.

## Parameters

| Field | Type | Required | Notes |
| - | - | - | - |
| `id` | string | Yes | Campaign ID (path parameter). Must be in `PAUSED` status. |

## Response

```json theme={null}
{
  "campaignId": "cmp_987654321",
  "campaignName": "Q2 2026 Tech Launch",
  "previousStatus": "PAUSED",
  "newStatus": "ACTIVE",
  "totalMediaBuys": 2,
  "successCount": 2,
  "failureCount": 0,
  "mediaBuyResults": [
    { "mediaBuyId": "mb_abc123", "name": "Q2 2026 Tech Launch - Example Media", "previousStatus": "PAUSED", "success": true },
    { "mediaBuyId": "mb_def456", "name": "Q2 2026 Tech Launch - Display", "previousStatus": "PAUSED", "success": true }
  ]
}
```

* `previousStatus` / `newStatus` — campaign status before and after the call.
* `successCount` / `failureCount` — how many media buys resumed, and how many did not. A `200` response always has `failureCount: 0`.
* `mediaBuyResults` — per-media-buy outcome. Each entry includes `mediaBuyId`, `name`, `previousStatus`, and `success`.

## When some media buys do not resume

If the seller of any media buy refuses, fails, or does not confirm the resume,
or the storefront queues the resume for seller approval, the call returns
`503 SERVICE_UNAVAILABLE`:

* The media buys that resumed are `ACTIVE` and delivering.
* The media buys that did not resume are still `PAUSED`.
* The campaign shows `ACTIVE` if at least one media buy resumed, because the
  campaign is delivering again, and stays `PAUSED` if none did.
* Apostra's operations team is alerted.

The error's `details` carry the per-buy results and the campaign status:

```json theme={null}
{
  "data": null,
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "Campaign cmp_987654321 was only partly reactivated: 1 of 2 media buys resumed, and 1 did not and are still paused.",
    "details": {
      "reason": "campaign_reactivate_partial",
      "campaignId": "cmp_987654321",
      "campaignStatus": "ACTIVE",
      "totalMediaBuys": 2,
      "successCount": 1,
      "failureCount": 1,
      "mediaBuyResults": [
        { "mediaBuyId": "mb_abc123", "name": "Q2 2026 Tech Launch - Example Media", "previousStatus": "PAUSED", "success": true },
        { "mediaBuyId": "mb_def456", "name": "Q2 2026 Tech Launch - Display", "previousStatus": "PAUSED", "success": false, "error": "The seller's ad server rejected the update." }
      ]
    }
  }
}
```

`reason` is `campaign_reactivate_partial` when some buys resumed and
`campaign_reactivate_failed` when none did. To finish resuming, use
[reactivate media buy](/v2/buyer/campaigns/tasks/reactivate-media-buy) on each
buy that is still `PAUSED`. Calling reactivate on the campaign again works only
while the campaign itself is still `PAUSED`.

### When a seller is still applying the resume

Some sellers accept a resume and apply it later. Those buys stay `PAUSED` for
now, so the call still returns `503`, but they need no retry:

* Their entries in `mediaBuyResults` have `success: false` and a
  `resumeRequestedAt` timestamp, and `details.resumeRequestedCount` counts them.
* When they are the only buys outstanding, `reason` is
  `campaign_reactivate_requested`.
* Each buy, and the campaign, becomes `ACTIVE` on its own once its seller
  reports it delivering.

## Campaign status always follows delivery

A campaign shows `PAUSED` only when every one of its media buys is paused. If a
campaign was stored as `PAUSED` while one of its media buys kept delivering, for
example from a pause made before this rule, Apostra corrects the campaign to
`ACTIVE` and alerts its operations team. This correction changes only what the
campaign shows. It never pauses or resumes a media buy.

## Errors

| Code | When |
| - | - |
| `VALIDATION_ERROR` | Campaign is not in `PAUSED` status. |
| `NOT_FOUND` | Campaign ID does not exist for the authenticated account. |
| `SERVICE_UNAVAILABLE` | One or more media buys did not resume; see [When some media buys do not resume](#when-some-media-buys-do-not-resume). |

See [Errors](/v2/reference/errors) for the full error shape and recovery semantics.

## Related

<CardGroup cols={2}>
  <Card title="Pause campaign" href="/v2/buyer/campaigns/tasks/pause-campaign" icon="pause">
    Halt spend across all media buys
  </Card>

  <Card title="Execute campaign" href="/v2/buyer/campaigns/tasks/execute-campaign" icon="rocket">
    Launch a DRAFT or COMPLETED campaign
  </Card>

  <Card title="Media buy status" href="/v2/buyer/campaigns/tasks/get-media-buy-status" icon="signal-stream">
    Poll live ADCP status
  </Card>

  <Card title="Campaign overview" href="/v2/object-guides/campaign" icon="rocket">
    The campaign object and lifecycle
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.