/mcp/v3; no Interchange page is
required. The authenticated account must be a Seller Account.
An RFP is the seller’s durable commercial opportunity or exercise. An
RFP turn is one immutable request and its response. The response is the
seller proposal artifact inside that turn; clients do not save a second
seller-side Proposal object.
Before creating an RFP
Response composition uses the Seller Account’s own active Storefront products. At least one matching product must have all of these catalog facts:- a name and at least one priced option declaring a
guaranteedornon_guaranteeddelivery type; - at least one channel, including a requested channel when the RFP specifies one;
- an explicit positive fixed or floor price with pricing-option ID, pricing model, ISO currency, and a compatible delivery type; and
- at least one canonical URL-free creative format (
format_kindplusparams).
needs_clarification and identifies the missing catalog facts instead.
Composition scans at most 1,000 products and applies declared field,
collection, and artifact-size limits. A larger catalog or response also ends
in explicit clarification; Interchange never returns a partial proposal as
ready.
request.budget is an exact currency amount, not an arbitrary decimal. Its
currency must match the uppercase ISO 4217 contract published by the
save_rfp input schema and be supported by its runtime refinement; amount
must remain between the schema’s published minimum and maximum. Decimal precision follows that currency’s minor unit: for
example USD accepts two decimal places, BHD accepts three, and JPY accepts none.
An amount that cannot be represented in whole minor units is rejected before
the RFP is saved. Zero is accepted so an incomplete brief can be recorded, but
composition returns actionable needs_clarification; it never consumes worker
retries or emits zero-value allocation lines.
Create and poll a turn
Callsave_rfp with action: "create". clientRequestId is the idempotency
key: retrying the exact request returns the same RFP and turn, while reusing the
key with a changed payload returns an idempotency conflict.
rfpId, turnId, responseState, and a
safe get call. Poll the exact turn:
queued → processing → ready | passed | needs_clarification | failed
readycontains a non-empty semantic response with bound products, prices, allocations, canonical formats, narrative sections, and composition receipts.passedis a deliberate, evaluated decision not to propose, not an absent response. An explicitstrategy.posture: "pass"records the canonical truth gate and decision provenance on the turn.needs_clarificationcontains questions and the facts that could not be resolved. Correct the product catalog or request, then append a new turn.failedcontains a stable reason and safe retry guidance. Do not treat it as a successful response or keep polling it as though it were processing.
Continue the lifecycle
save_rfp uses one closed action union. Fields from another action are
rejected rather than ignored.
HTML, PDF, and PPTX renderers are not certified in this lifecycle slice.
Requests for those formats return
representation_format_not_certified; they do not fabricate a file or mutate
the response artifact.
Search and audit
Usesearch({"kind":"rfp"}) for opportunities and
search({"kind":"rfp_turn"}) for immutable turns. RFP filters include state,
origin, purpose, buyer, advertiser, category, market, channel, posture,
Playbook version, cache mode, and outcome. Turn filters add RFP ID, response and
evaluation state, recipe/model/judge version, and feedback status.
Use get({"kind":"rfp","id":"RFP_ID"}) for the opportunity summary,
latest and released turns, bounded turn history, outcome summary, and links.
Use get({"kind":"rfp_turn","id":"TURN_ID"}) for the exact request,
response, receipts, diagnostics, feedback, outcome, and representation status.
Search results are summaries; they do not repeat the complete request or
response. Feedback bodies and representation statuses remain on the authorized
exact-turn read in bounded pages. Follow feedback.next and
representations.next until they are null. Feedback continuations carry
feedbackOffset; representation pages carry an opaque representationCursor.
Pass the supplied argument back to get rather than synthesizing one. The
representation cursor pins a snapshot, so rows appended while paging do not
produce skips or duplicates.