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

# Review what a campaign will send

> Read the queue, edit a message before it goes out, and approve or decline what is waiting on you

An active campaign builds a queue of messages and works through it on schedule. Where a campaign is set to require approval, nothing leaves until someone says so — and that is what these endpoints are for.

They need a key with the `campaigns` [scope](/concepts/scopes).

<Warning>
  Approving is the one action in this API that causes mail to be sent. Everything else on this page is reversible; that is not.
</Warning>

## Read the queue

`GET /business/campaigns/{campaignId}/scheduled-sends` lists what is waiting. `status` is required, so you always ask for a specific slice.

```bash theme={null}
curl -G https://api.tryfuse.ai/api/v1/business/campaigns/$CAMPAIGN_ID/scheduled-sends \
  --data-urlencode "status=approval_required" \
  --data-urlencode "limit=50" \
  -u "$FUSE_API_KEY:"
```

```json theme={null}
{
  "sends": [
    {
      "id": "6a8da7adafc401ca94530e14",
      "campaignId": "6a8da7718707dbcfb4448b96",
      "status": "scheduled",
      "channel": "email",
      "type": "manual",
      "subject": "Quick question about BrightPay"
    }
  ]
}
```

| `status`            | What it holds                                               |
| ------------------- | ----------------------------------------------------------- |
| `approval_required` | Waiting on a human. This is the review queue.               |
| `scheduled`         | Approved or auto-approved, waiting for its send time.       |
| `sent`              | Already delivered.                                          |
| `skipped`           | Passed over; the contact moved on to the next step.         |
| `stopped`           | Cancelled, usually because the campaign or contact stopped. |
| `overwritten`       | Replaced by an edit — see below.                            |

## Edit before it goes

`PATCH /business/scheduled-sends/{sendId}` changes the subject, body or send time of a message that has not gone out.

```bash theme={null}
curl -X PATCH https://api.tryfuse.ai/api/v1/business/scheduled-sends/$SEND_ID \
  -u "$FUSE_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{ "subject": "Quick question about BrightPay (edited)" }'
```

```json theme={null}
{
  "send": {
    "id": "6a8dce64a4566f4f2454bd38",
    "replacedSendId": "6a8da7adafc401ca94530e14",
    "status": "scheduled",
    "subject": "Quick question about BrightPay (edited)"
  }
}
```

<Note>
  An edit creates a **new** send and marks the old one `overwritten`. The `id` in the response is the one that will actually go out, and `replacedSendId` is the one you edited — so store the new id if you intend to approve or skip it afterwards.
</Note>

Only a message still waiting can be edited. Anything already sent, skipped, stopped, overwritten, or parked on a task answers `409 SCHEDULED_SEND_NOT_EDITABLE`.

## Approve or decline

Both take a list of ids and report back per id, so a partial batch tells you exactly what happened.

```bash theme={null}
curl -X POST https://api.tryfuse.ai/api/v1/business/scheduled-sends/approve \
  -u "$FUSE_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{ "sendIds": ["6a8dce70a4566f4f2454bd4f", "6a8da7adafc401ca94530e14"] }'
```

```json theme={null}
{
  "approved": ["6a8dce70a4566f4f2454bd4f"],
  "ignored": ["6a8da7adafc401ca94530e14"],
  "notFound": ["000000000000000000000000"]
}
```

| Key                     | Meaning                                                                                            |
| ----------------------- | -------------------------------------------------------------------------------------------------- |
| `approved` / `declined` | Acted on.                                                                                          |
| `ignored`               | Real sends of yours, but in a status the action does not apply to — already sent, already skipped. |
| `notFound`              | No such send, **or** it belongs to another account. The two are reported identically on purpose.   |

`POST /business/scheduled-sends/decline` has the same shape and stops the message instead of sending it, reporting `declined` where approve reports `approved`.

## Skip one

`POST /business/scheduled-sends/{sendId}/skip` passes over a single message and moves that contact to the next step of the sequence.

```json theme={null}
{ "send": { "id": "6a8da7adafc401ca94530e14", "status": "skipped" } }
```

Use skip when the message is wrong for one person but the campaign should carry on for them. Use decline when it should not go at all.

## A review loop

<Steps>
  <Step title="Pull the queue">
    `GET /business/campaigns/{campaignId}/scheduled-sends?status=approval_required`
  </Step>

  <Step title="Fix what needs fixing">
    `PATCH /business/scheduled-sends/{sendId}` — and keep the returned `id`, not the one you sent.
  </Step>

  <Step title="Approve the rest in one call">
    `POST /business/scheduled-sends/approve` with every id you are happy with.
  </Step>

  <Step title="Check the report">
    Anything in `ignored` changed status while you were reviewing; anything in `notFound` is not yours.
  </Step>
</Steps>

## Errors worth handling

| Status | Code                          | Meaning                                                                         |
| ------ | ----------------------------- | ------------------------------------------------------------------------------- |
| `404`  | `SCHEDULED_SEND_NOT_FOUND`    | No such send, or it belongs to another account.                                 |
| `409`  | `SCHEDULED_SEND_NOT_EDITABLE` | Only a send still waiting to go out can be edited.                              |
| `429`  | `RATE_LIMITED`                | Campaign endpoints share one bucket — see [rate limits](/concepts/rate-limits). |
