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

# Limit what a brain can change in your catalog

> Set the price band within which a brain's or Library intake's price change applies at once. Every other change waits for an administrator to approve it on Apostra.

A brain is the agent that manages your catalog and answers buyers' requests
for proposals: Chef, Prime, or your own model. A brain, and Library intake
reading your Library files, will change your catalog with the same tools you
use, `save_wholesale_product` and `save_playbook`. Your change limits decide
which of those changes apply at once and which wait for you.

No brain or Library intake writes your catalog yet. You can set your band now,
and it applies from the first change one of them makes.

> [!NOTE]
>
> Change limits are part of the modular sales agent beta. Outside the beta,
> `changeLimits`, `sourceMaterialId` and `idempotencyKey` are refused with
> `FEATURE_NOT_ENABLED`, so an approval's outcome cannot be looked up by its key.

## What applies at once, and what waits

One kind of change applies at once: a **price change on an existing product or
pricing fact** that stays within your band of its **list price**.

Every other change from a brain or Library intake waits for an administrator
of your Seller Account to approve it:

* a new product;
* a price outside the band;
* adding or removing a price, or switching a price between fixed and auction;
* a change to a price's minimum spend per package;
* a status change, such as taking a product off the market;
* deleting a product;
* formats, channels, inventory, targeting and the rest of a product;
* house discounts.

A brain does not change your selling guidance through `save_playbook`. It
proposes guidance as a Lesson with `save_lesson`, which you review there.

Your own changes, made through a tool, the web app or a widget, apply as they
always have. The limits apply only to a brain and to Library intake. Your
product and price changes take turns with a brain's change on the same account,
so a brain never writes over a price you set while it was checking. If another
change is still being applied after 15 seconds, yours returns a retryable
`SERVICE_UNAVAILABLE` error; send it again.

### The list price

A price is measured against its list price: the last price a person set or
approved. A brain's change does not move the list price. With a band of 10% and
a list price of $20, a brain can set any price from $18 to $22, but it cannot
reach $24.20 in two steps of 10%: the second step is still measured against
\$20.

When you set a price yourself, or approve a brain's change, that price becomes
the new list price. If Apostra saves your price but cannot record it as the
list price, the call returns a retryable `SERVICE_UNAVAILABLE` error that says
the change was saved. Send the same call again to finish.

## Set your band

Send `changeLimits` to `save_playbook` on its own, without any other playbook
field.

```json theme={null}
{
  "changeLimits": { "priceBandPercent": 10 }
}
```

| Field | What it holds |
| - | - |
| `changeLimits.priceBandPercent` | From 0 to 50. A brain's price change within this percentage of the list price applies at once. |

The band is **0 until you set it**, so every change a brain or Library intake
makes waits for approval. To read your band, call `get` with
`kind: "playbook"`. The result carries `changeLimits.priceBandPercent`.

Only a person can set the band, with the same access house discounts need:
signed in as themselves, or with their own API key. A brain, Library intake or
a machine credential such as an organization or system token that sends
`changeLimits` is refused with `ACCESS_DENIED`.

## Approving a change

A change that waits returns `approval_required` with a link to an approval page
on Apostra, under the same [web approval](https://docs.apostra.com/v2/concepts/web-approvals.md) every
sensitive action uses. If the brain was working in a
[Session](https://docs.apostra.com/v3/sessions.md), the Session also shows a card with the link.

An administrator of your Seller Account opens the link, sees what will change,
and approves or rejects it. Approving applies the change exactly as the brain
sent it. If the product or playbook changed after the brain read it, approving
fails with `catalog_changed` and nothing is written. The brain can propose the
change again against what is there now.

Applying a change is retried if it is interrupted. The retry checks each part
of the change, which is each product field it sets, the pricing facts, or each
discount rule, against how that part stood when the brain read it. A part the
interrupted attempt already applied is not written again, and a part still as
the brain read it is applied. If someone else changed a part in the meantime,
approving fails with `catalog_changed` rather than write over their change.
The parts the interrupted attempt already applied stay applied: read the
product or playbook to see where it stands, and ask the brain to propose the
rest again if you still want it.

The approval result carries an `idempotencyKey`. Calling the same tool again
with that key returns the outcome: still waiting, the applied change once it is
approved, or the reason it was rejected, expired or failed.

## Where a change came from

Both tools take an optional `sourceMaterialId`: the [Library](https://docs.apostra.com/v3/seller-library.md)
file a change was read from. Library intake will always send it. An id that is not
a file in your Library is refused with `VALIDATION_ERROR`.

## Refusals

| Case | Code |
| - | - |
| A brain or Library intake sends `changeLimits` | `ACCESS_DENIED` |
| `changeLimits` is sent with another playbook field | `VALIDATION_ERROR` |
| `priceBandPercent` is below 0 or above 50 | `VALIDATION_ERROR` |
| `sourceMaterialId` is not a file in your Library | `VALIDATION_ERROR` |
| A brain or Library intake sends `materialCandidate` | `VALIDATION_ERROR` |
| A brain or Library intake sends `active` to `save_playbook` | `VALIDATION_ERROR` |
| A brain or Library intake sends `pricing` and `discounts` in one `save_playbook` call | `VALIDATION_ERROR` |
| A brain or Library intake sends `limits` to `save_playbook` | `ACCESS_DENIED` |
| A machine credential, not a person, sends `changeLimits` | `ACCESS_DENIED` |
| Your account is not in the modular sales agent beta | `FEATURE_NOT_ENABLED` |


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