Skip to main content
Deprecated. This page documents the v2 storefront API, which is being retired for external callers. V3 has no documented replacement for this task yet.
A storefront that answers everything answers nothing. Before your Merchandising Agent composes anything, it makes the judgment every good sales organisation makes first: is this brief ours? Your selling settings answer that with a versioned, structured decision. They are separate from operating-instructions prose: prose still guides packaging and explanation, while settings decide qualification and buyer-decline disclosure.

The three answers

A pass is a composed outcome, not a failure. Passing well is relationship-building, and buyer agents that run managed evaluation score sellers on response quality, not response volume — so a doomed bid costs you standing that a graceful decline protects.
A pass genuinely withholds your answer, and it looks like a no-fit. When your doctrine declines a brief, the buyer’s agent gets the same response your storefront already returns when nothing matches: no composed proposal, and no explanation. It cannot tell “declined” from “nothing matched” — that is deliberate. AdCP has no first-class “no bid, with reasons” message today, so rather than invent one we reuse the answer buyers already understand.Only the composed proposal is withheld. Passthrough inventory and proposals you finalized on an earlier turn are a different lane your doctrine never judged, so they still ship — withholding them would make a decline detectable by what went missing.The decline itself never leaves your side. It is written for you: your record of why your storefront walked away, readable on the proposal pass alongside every other composed outcome, with a receipt back to the doctrine version that decided.

What decides it

Two numbers and a posture in your selling settings: Category fit is measured against this pass’s own output — the products the agent actually composed and the inventory that fed them — never your whole catalogue. Inventory you did not offer for this brief did not serve it. A brief that names no vertical or channel we can compare is not a poor fit; it is an unmeasured one, and it pitches. That is the common shape of a short brief, and it is why turning doctrine on changes nothing for most traffic. A brief that tries to tell the agent how to classify it is passed. For example, it might include text telling the agent to treat it as a different vertical or channel. A brief like that is never pitched on the strength of its vertical, so a buyer can’t write their way into a pitch that a plain brief wouldn’t earn. The decision is recorded with the rule untrusted_brief_taxonomy. This applies in every language and whether or not you have set a doctrine.
Because a pass withholds the composed proposal, a doctrine set too tight will stop your storefront answering briefs it was winning. Run the briefs you care about through a brief test before you save the settings. To restore an earlier behaviour, save a new settings revision with the earlier values.
Your operating-instructions prose keeps doing what it always did: it shapes the argument, the register, and the judgment inside a proposal. The numbers above decide only whether a proposal happens at all — because whether a buyer gets an answer is the one question that should never be decided differently on two identical runs.

Named starting points

Adopt one, edit it, or write your own. A storefront that has never set a doctrine has no qualification gate at all. It pitches every brief it can compose products for, exactly as it did before doctrine existed — nothing is passed or countered on your behalf. Doctrine only starts deciding once you set one. Such a version reads back as house_default with isDefault: true, and the numbers shown for it are display and starting values, not active thresholds: they are what you would begin from if you adopted them, not a bar your briefs are being measured against today. You cannot adopt house_default by name, so “no doctrine set” has exactly one spelling. To return to it, clear the doctrine or activate a version that never had one. Adopt one by name:
Or state your own numbers:
Thresholds that match no named variant read back as custom. So do a named variant’s numbers after you edit one of them — the label always describes the numbers actually in force, never the strategy you started from.

Test it before it ships

Doctrine is versioned and activated exactly like the rest of your Playbook, so the loop is: draft a version, test a brief against it, then activate it once it reads right.
  1. Author a new version with the doctrine you are considering. Leave activate off to keep it out of production while you look at it.
  2. Test that version by name — pass its number as operatingInstructionsVersion to test_storefront_brief, or ask Apostra to test a brief against it. Omit it and the active version is used, as before.
  3. Read the result. It carries a bidDecision — the disposition, which rule decided it, the measured category fit, and the doctrine version behind it — and composedPitch, the argument or the branded decline the buyer would actually have received. The version that was evaluated is reported back, so you are never guessing which one you just tested.
  4. Activate when it reads right.
You can only test a version your own storefront authored; the version is re-read and re-authorized before anything composes under it. Nothing is activated by testing — your live active version is untouched until you activate it yourself. Changed your mind? Save a new selling-settings revision with the earlier values to restore that behaviour. Nothing is overwritten; every operating- instructions version stays readable. Brief tests are dry runs: they create no media buy, persist no products, never turn on transacting, and leave nothing on your exchange history. The narrative is composed for you to read and then discarded.

Reading a decision after the fact

Every composed pass records the disposition it reached, which rule reached it, the measured fit, and the doctrine version that decided — and the disposition carries a receipt back to the Playbook version behind it, exactly like the receipts behind every sentence of a pitch. That is what makes “why did we pass on this brief?” answerable months later, without re-deriving it against a doctrine you have since edited.

What doctrine cannot do

Doctrine governs judgment, not truth. It changes what your agent argues, how hard, and when it walks away. It cannot mint a fact: every sentence in a pitch or a decline still sources from the brief, your inventory, or your Playbook, and a sentence with no source is dropped before anyone reads it. So a doctrine that says “counter everything” does not produce a counter-pitch claiming inventory you do not have. It produces a counter-pitch built from the inventory you do.