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

# Get plan suggestion set

> Read one set and the per-media-buy transfer it proposes

`GET /api/v2/buyer/plan-suggestion-sets/:planSuggestionSetId`

Returns one plan suggestion set with the full per-media-buy breakdown — which
media buys give up budget, which receive it, and how much. This is the view to
read before deciding, because the breakdown is what makes the transfer legible.

See [plan suggestion sets](/v2/buyer/campaigns/plan-suggestion-sets) for the
lifecycle and what each status means.

## Request

```bash theme={null}
curl https://api.interchange.io/api/v2/buyer/plan-suggestion-sets/77 \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

No request body.

## Parameters

| Field                 | Type   | Required | Notes                                                                    |
| --------------------- | ------ | -------- | ------------------------------------------------------------------------ |
| `planSuggestionSetId` | string | Yes      | Set id (path parameter) — digits only, no leading zero, up to 18 digits. |

## Response

```json theme={null}
{
  "planSuggestionSetId": "77",
  "optimizerRunId": "8f14e45f-ceea-4c11-8e94-1c1a3c1e2f21",
  "planId": "555000000001",
  "planName": "Nike Q1 Brand Awareness Plan",
  "campaignId": "1042",
  "campaignName": "Nike Q1 Brand Awareness",
  "planRunSequence": "42",
  "planMediaBuyCount": 2,
  "budgetCurrency": "USD",
  "applyMode": "MANUAL",
  "status": "AWAITING_APPROVAL",
  "statusReason": null,
  "netAllocationDelta": "0",
  "notifiedAt": "2026-08-19T06:00:12.400Z",
  "decidedAt": null,
  "appliedAt": null,
  "applyAttemptCount": 0,
  "compensationAttemptCount": 0,
  "firstMessageAt": "2026-08-19T06:00:09.100Z",
  "lastMessageAt": "2026-08-19T06:00:11.800Z",
  "mediaBuys": [
    {
      "suggestionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "adcpMediaBuyId": "MB1",
      "mediaBuyName": "Display - Programmatic",
      "netAllocationDelta": "-400000",
      "appliedAt": null
    },
    {
      "suggestionId": "5c9e1a02-8f3b-4d21-9a77-6b1e2c4d8f90",
      "adcpMediaBuyId": "MB2",
      "mediaBuyName": "Video - CTV",
      "netAllocationDelta": "400000",
      "appliedAt": null
    }
  ]
}
```

## Reading the numbers

Every allocation figure is an exact count of `budgetCurrency`'s minor unit, sent
as a string. `"-400000"` on a USD plan is \$4,000 leaving that media buy.

A member's `netAllocationDelta` is deliberately **not** zero — it is that media
buy's side of the transfer, and it is always present. The set's own
`netAllocationDelta` is what must be zero, and it is the sum of its members; it is
`null` until the set is complete, because there is nothing balanced to report yet.
If you add the members up and get anything other than zero, the set will not be
actionable.

The values are strings because they are int64 counts surfaced as decimal strings,
not because they are large. Do not route them through a float.

`applyMode` tells you who decides: `MANUAL` means this set is waiting on you,
`AUTO` means optimizations apply without review and the set was approved on
arrival. It is read from the campaign, falling back to the advertiser's default,
and fixed when the run is first seen.

`applyAttemptCount` and `compensationAttemptCount` relate to automatic
application of an approved set, which is not yet enabled — both are `0`.

## Errors

| Status | When                                           |
| ------ | ---------------------------------------------- |
| `404`  | No such set, or it belongs to another account. |
| `400`  | Malformed set id.                              |
