> ## 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.

# Create buyer instructions

> Add a new scoped buyer-instructions row

`POST /api/v2/storefront/buyer-instructions`

Creates a new buyer-instructions row. The `(operatorDomain, brandDomain)` tuple
is unique per storefront — a duplicate scope fails with `409`. To change an
existing row, [update](/v2/storefront/buyer-instructions/tasks/update-buyer-instructions)
it instead.

## Request

```bash curl theme={null}
curl -X POST https://api.interchange.io/api/v2/storefront/buyer-instructions \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "operatorDomain": "acme-media.com",
    "brandDomain": "northwind.example",
    "discountPercent": 15,
    "notes": "Brand requires Acme Media viewability ≥ 70%.",
    "countries": ["US", "CA"]
  }'
```

## Parameters

All five fields are required. Send `null` for any you want to leave unscoped.

| Field             | Type              | Required | Notes                                                                                 |
| ----------------- | ----------------- | -------- | ------------------------------------------------------------------------------------- |
| `operatorDomain`  | string \| null    | Yes      | Operator the row applies to, or `null` for any operator. 1–253 chars                  |
| `brandDomain`     | string \| null    | Yes      | Brand the row applies to, or `null` for any brand. 1–253 chars                        |
| `discountPercent` | number \| null    | Yes      | Discount off base price, `0`–`100`. `null` for no discount                            |
| `notes`           | string \| null    | Yes      | Composition notes, max 2000 chars. `null` for no notes                                |
| `countries`       | string\[] \| null | Yes      | ISO 3166-1 alpha-2 codes (uppercase), at least one when set. `null` for all countries |

## Response

```json theme={null}
{
  "id": "18",
  "storefrontId": "1234",
  "operatorDomain": "acme-media.com",
  "brandDomain": "northwind.example",
  "discountPercent": 15,
  "notes": "Brand requires Acme Media viewability ≥ 70%.",
  "countries": ["US", "CA"],
  "createdAt": "2026-06-06T15:00:00.000Z",
  "updatedAt": "2026-06-06T15:00:00.000Z",
  "createdBy": "operator@touchline.example"
}
```

Returns `201` with the created row. The resolver picks the maximum
`discountPercent` across all rows that match a given buyer.

## Errors

* `400 VALIDATION_ERROR` — missing required field, `discountPercent` out of
  `0`–`100`, or a malformed country code.
* `409 CONFLICT` — a row already exists for this `(operatorDomain, brandDomain)`
  scope. Update that row instead.
* `401 UNAUTHORIZED` — missing or invalid bearer token.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Buyer instruction tasks" href="/v2/storefront/buyer-instructions/tasks" icon="list-check">
    All buyer-instructions operations.
  </Card>

  <Card title="Update buyer instructions" href="/v2/storefront/buyer-instructions/tasks/update-buyer-instructions" icon="pen">
    Change discount, notes, or countries.
  </Card>
</CardGroup>
