Replace the store's assistant configuration
Authorizations
A secret API key. Publishable keys cannot reach this API. A key may carry an expiry, and an expired key is refused exactly like an unknown one, with a 401 that names no reason; check the key's expires_at in the dashboard rather than inferring it from a response. When a merchant rolls a key's secret they choose a grace window of up to 3 days, and for its duration BOTH the new secret and the one it replaced authenticate, so an integration moves over on its own deploy schedule instead of at the instant the button is pressed. Move before the window closes: after it, the old secret is refused. Nothing else about this contract moves with a roll. The key keeps its id and its scopes, so the only thing an integration updates is the credential itself.
Headers
A unique key per logical write. Replaying a request with the same key returns the first response byte for byte instead of applying the write twice.
Body
REPLACES the whole config, and every field is required for that reason. An omitted enabled would decode to false and take the assistant off the merchant's storefront; an omitted skill_add_to_cart would take its cart tools away mid-conversation. Both are 200s a client would never notice. Read /api/v1/agent-config and send every field back. A store that has never configured the assistant has no row; this creates it. There is no DELETE, because removing the row restores the defaults, which have the assistant ON, so deleting to disable would do the opposite of what it looks like.
The updated_at you last read. Required, because the config is a singleton written by this route AND by the merchant's dashboard: a write naming no version silently reverts whatever moved under it and answers 200 to both parties. A mismatch is 409 config_modified. null asserts that this store has never saved a config, which is the only way a first write can name a version that does not exist, and it is refused once a row does exist.
The master switch. The storefront widget renders on exactly this, so false means shoppers see nothing whatever else is set.
The assistant's display name, at most 60 characters. "" for the default.
The opening line, at most 280 characters. "" for the default.
The merchant's voice, at most 2000 characters. It shapes TONE only: the server appends its safety rules on top, so a persona can never remove a guardrail.
Switches on a server-authored block that asks clarifying questions.
Switches on a server-authored block that answers hesitation.
What the shopper is told when a conversation goes to a human, at most 280 characters. "" for the built-in text.
Gates search, recommendation and product detail together. GROUPED rather than one toggle per tool, because an assistant that could recommend a product but not detail it is half broken in a way no single switch names.
Gates reading and writing the shopper's cart, together.
Gates order lookup.
The merchant's starter chips. Send [] for none; the key is required either way, because dropping it would clear them. NORMALISED RATHER THAN REFUSED on write: at most six, each truncated to 80 characters, blanks dropped. Read the response back rather than assuming what you sent was stored verbatim.
Response
Success
