> ## 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, and declining is final for that contact. Neither can be undone.
</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": "approval_required",
      "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 1 to 100 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 reports `declined` where approve reports `approved`. A declined send moves to `stopped`, and that ends the contact's sequence in this campaign: no later step is scheduled for them. Decline works on sends that are `approval_required` or `scheduled`, so it is also how you call off an upcoming send for one contact.

## 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 the contact should get nothing more from this campaign. Only a send still waiting can be skipped; anything already sent, stopped or overwritten answers `409 SCHEDULED_SEND_NOT_SKIPPABLE`.

## 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. |
| `409` | `SCHEDULED_SEND_NOT_SKIPPABLE` | The send is already settled and cannot be skipped. |
| `429` | `RATE_LIMITED` | Campaign endpoints share one bucket — see [rate limits](/concepts/rate-limits). |


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