get_products is the canonical product door for buyer agents. Send one
AdCP-shaped request to selected storefronts—or all storefronts connected to an
advertiser—and receive one bounded canonical page as products[] plus optional
sibling proposals[]. Every identity remains qualified by its originating
storefront.
Apostra can optionally evaluate valid seller proposals before returning
them. You supply plain-language operating instructions. A managed model chooses
accept, reject, or refine, can attach buyer-owned enrichment, and can rank
the accepted cohort across sellers.
AdCP remains a one-buyer-to-one-seller protocol. Apostra is the
many-to-one buyer layer: it fans out the canonical request, validates each
seller independently, qualifies identities, and returns a bounded aggregate
page. Sellers do not see one another or receive an Apostra-specific
request.
One protocol request, many sellers
The scaling layer does four things without forking the protocol:- Bilateral calls stay canonical. Buying mode, brief, filters, proposals, and refine are ordinary AdCP semantics at each seller edge.
- Identity survives aggregation.
sf1:product IDs andsfp1:proposal IDs prevent cross-storefront collisions and round-trip into purchase. - Slow sellers do not erase fast sellers. Revisioned replacement snapshots expose seller progress while other agents remain pending. Candidates become selectable only after their complete seller/source identity is persisted.
- Responses stay agent-sized.
pagination.max_resultsbounds candidates; proposal graphs remain whole, and the cursor is frozen only when the execution is complete.
Which sellers are searched for an advertiser
Discovery for an advertiser searches only the media partners turned on for that advertiser: partners selected automatically for its markets and channels, partners included for the whole account, and partners turned On for that advertiser. Media partners that are off for the advertiser are not contacted and do not appear instorefront_results[]. They are outside the search, not
failed sellers.
When the request names no storefronts, ext.interchange.storefronts_not_searched
lists the media partners left out for the advertiser: each one’s
storefront_id, storefront_name and reason. NO_AUTOMATIC_MATCH means it
does not match the advertiser’s markets and channels, ADVERTISER_DISABLED
means it is turned off for the advertiser, ACCOUNT_ALWAYS_EXCLUDE means it is
excluded for the whole account, and HARD_INELIGIBILITY means it cannot
transact with you at all. Media partners you can turn on are listed first, then
HARD_INELIGIBILITY ones, each group by name. At most 50 are listed; total
counts every one, so any left unlisted are HARD_INELIGIBILITY unless every
listed partner is one you can turn on. When you can turn any of them on,
suggestion says how, once. The get_products
text summary names them the same way. Each media partner appears once, even
when it is reached through more than one sales agent. The list is reported only
for an advertiser your account itself owns; for any other advertiser, such as
one another organization delegated to yours, it is omitted rather than
guessed.
A media partner that is off also changes the rest of the response in these
cases:
- You named it. When the request names specific storefronts, or refines a
product or proposal from one, a named media partner that is off returns a
storefront_results[]row with statuscompleted, no products, and anoutcomeof kindaction_requiredwithreason_codeadvertiser_activation. Itsmessagesays why it was not searched and itssuggestionsays where to turn it on. A partner turned off for the advertiser is turned on in the advertiser’s view of Media Partners (open the media partner, choose Controls, set Availability to On). A partner excluded for the whole account is changed in the account view, from Always exclude to Default or Always include. - No media partner is on. When none is turned on for the advertiser,
discovery searches nothing and
guidancesays so, with the same path to turn one on. - Otherwise, an empty result’s
guidancealso reports how many media partners were left out because they are not turned on for the advertiser.
skipped when you
named it; turning it on does not change that.
A media partner that is still finishing go-live is different. Some managed ad
servers need the media partner to pass a no-spend certification, such as a
test write to the ad server, before it takes its first booking. Until it
passes, the media partner is searched like any other: its products appear in
results, and you can add them to a buy you are planning. Creating or executing
a media buy with it is refused with ACCESS_DENIED and a message saying the
media partner has not finished going live. There is nothing to turn on; the
media partner finishes the certification on its side, and booking opens once
it passes.
Saved results follow the same rule. When a media partner is turned off for the
advertiser after a search, reading that saved discovery no longer returns its
products; an empty page’s guidance says how many saved products were removed
for that reason. Adding one of its products to a buy, directly or by applying a
proposal, is refused with ACCESS_DENIED and a message saying where to turn
the media partner back on.
Only media partners where the advertiser has an account
A hosted media partner is searched only as the advertiser’s own active account with it. That holds for every search: a brief, a refinement, a proposal request and a wholesale browse. A media partner can offer an advertiser its own products and prices, so a catalog seen without the account would be incomplete and wrongly priced, and could not be bought from. A media partner where the advertiser has no active account yet is not contacted at all. The one exception is a no-spend sandbox scope Apostra has already authorized: a media partner searching its own supply with its own sandbox advertiser, or a sponsored buyer searching the media partner that sponsors it, is answered by that one storefront without an account.- You named it. Its
storefront_results[]row isskippedand itssuggestionpoints to Media Partners. Inget_productsthe row’sreason_codeiseligibilitywith noskip_code: that contract’s reason and skip codes are a closed set, so it cannot say whether the account is still being set up or someone has to act. The V3 Seller read,get({ kind: "seller", id, include: ["products"], advertiserId }), reports the same row withreason_codeaccount_pendingwhen the account is still being set up and nothing needs doing, oraccount_needs_attentionwhen the buyer, an operator or the media partner has to act. - Otherwise it is only counted. An empty result’s
guidancesays how many media partners are still setting up the advertiser’s account and how many need attention, and points to Media Partners.
status
completed, not incomplete), with outcome skipped, reason_code
eligibility and the same suggestion.
Sellers behind a media partner
Some media partners are storefronts that search another seller’s sales agent for you. Such a storefront searches that seller under the account you named, by its brand and operator, only once the seller has reported your account active. While the seller is still setting the account up, holds it for approval, or has refused it, the seller is left out of the search. It is not searched publicly in its place, its saved catalog is not shown instead, and the search does not ask it to set the account up. A seller that takes neither account requests nor accounts you link yourself has no account to wait on, so it is left out too. Sellers that run on Apostra’s embedded sales agent are searched as before. To see a media partner’s products, get the advertiser an account with it on the Media Partners page. A media partner whose accounts could not be read fails for that search, and a buyer that has not finished its setup is told which step to complete (BUYER_SETUP_REQUIRED).
This is how Apostra searches for you. A media partner’s storefront still
answers a wholesale get_products that any agent sends it directly; see
Storefront discovery needs an account.
Who can browse under your company’s seller account
When a seller has approved your company’s account for an advertiser, products for that account are returned to the people and credentials of your company, not only to its administrators. Browsing is open to:- every current member of your company, at any permission level (Basic, Premium or Admin);
- every service token of your company, including a read-only token, limited to the advertiser the token is scoped to when it has one;
- a buyer agent registered for your company, while it holds an active grant for the advertiser you selected; and
- Scope3 support staff switched into your company. Scope3 confirms the person against its staff directory, so a role label alone does not admit anyone, and a session acting as another user is never treated as staff.
- A member, token or buyer agent that is not allowed for this account (a member
of another company, a deactivated or external self-serve member, an expired
or archived token, or a buyer agent without an active grant for the selected
advertiser) gets
ACCOUNT_NOT_FOUND, the same answer as an account that does not exist. A buyer agent acting for a member or token is held to its own grant as well as to that person’s or token’s access. - A credential with no user, service token or registered buyer agent behind it
(for example a machine, organization or agent-registration key) is stopped
before the account is looked up and gets
AUTH_REQUIRED. The error’sdetails.reasoniscomplete_account_authority_requiredwhen the request reaches the storefront’s external AdCP endpoint, andaccount_requires_principalwhen discovery runs inside Apostra.
Read each seller result honestly
ext.interchange.storefront_results[].outcome is present when a seller was
queried through its own agent, or when a seller you named was not searched. It
is one buyer-safe terminal outcome: returned_products (with its count),
no_matching_products, no_inventory_for_request, action_required (a named
seller that is off for the advertiser, with its fix), skipped (with a safe
reason), failed (with a safe reason), or local_refusal (the request was
refused by Apostra’s own validation before it ever reached that seller, with
its code, message, and an optional suggestion for correcting the
request). A seller with no active wholesale inventory is
no_inventory_for_request, not a failed seller and not a retry instruction.
An empty seller result becomes no_matching_products only after that seller
has completed without an error. A seller response with an error and no products
is failed when no cached catalog can serve the request, even when the seller
marks its task completed. local_refusal is never counted toward that
seller’s queried/completed total, because the seller was never actually
contacted. An incomplete result remains incomplete and can carry a safe
seller clarification instead.
A seller result can also carry a buyer-safe message without changing its
outcome. When a seller still needs to finish setting up your account, the
message names that seller and says that you cannot launch a media buy with them
yet. You can still review the returned products and save a draft; Apostra does
not create an account or setup on your behalf from discovery.
A skipped outcome carries one of three reasons:
auth: the media partner could not be reached with your account or credentials. When the outcome also carries asuggestion, your account with that media partner is not connected, is not chosen for this advertiser, or its connection needs reconnecting, andsuggestionsays how to fix it: open Media Partners, open the media partner, connect or reconnect the account and map it to the advertiser, then search again. Theget_productstext summary names these media partners with the same fix, and does not count them as queried.coverage: the media partner does not cover the requested countries or channels.eligibility: the media partner cannot take this request for another reason.
skipped outcome can also carry skip_code, the precise cause that
reason_code is derived from. Treat it as optional: it is omitted when the
cause is not known, such as on a result stored before the field existed.
When one agent covers several sellers,
outcome and filter_result are
omitted because that agent-level result cannot be attributed honestly to an
individual seller. Those rows carry product-derived counts and
property_coverage[] only. Agent-level outcomes for that case are tracked in
AI-10300.
Returned products also produce property_coverage[]: each property domain and
the number of returned products carrying it. Treat this as coverage of the
seller response, not a claim about all supply on Apostra. Each seller row includes
at most 12 property domains, with property_coverage_total and
property_coverage_truncated when the buyer needs to recognise an abbreviated
list. When a seller reports
filter accounting or unfinished work, filter_result says whether no products
matched, filters excluded every candidate, or the result is partial. Seller
diagnostics and operational details are not exposed here.
The advertiser’s property exclusion list is applied after seller products are
returned. ext.interchange.excluded_product_count is the total number removed,
and each storefront row exposes its own
storefront_results[].excluded_product_count. Each seller row also has a
bounded excluded_products[] list with the removed product ID, name, and the
matching domain or domains. These domains are the intersection with the
buyer’s own exclusion list, never the rest of that list. If
excluded_products_truncated is true, use the count as the complete total and
describe the listed products as a bounded sample. If exclusion removes every
completed candidate, read the response guidance and report that N products
from M sellers were removed because they included properties on the
advertiser’s exclusion list. If a legacy candidate has no seller identity,
the total still includes it but no seller row does; report the removed-product
count without inventing a seller count. Do not call either outcome “no matching
inventory”.
get_products does not stop after the first 10 storefronts or choose a final
cohort by response speed. When no storefront selector is supplied (or
storefronts: "all_connected" is explicit), Apostra resolves every
storefront in the buyer’s eligible discovery scope and queries each backing
sales agent once. An ordinary provisional revision contains only sellers that
have answered so far and returns pagination.has_more: false with no
pagination.cursor; poll the same execution_id with since_revision
until results_complete: true. Only then follow pagination.cursor until
has_more: false to consume the complete candidate set. This enforces the
stable-cursor contract: incomplete ordinary results are replacement snapshots,
not pages to append. pagination.max_results limits each completed response
page, not the seller fan-out. The legacy Discover Products groupLimit and
groupOffset fields do not apply to this surface.results_complete: false, and names the remaining sellers as pending.
The requested processing mode is degraded: evaluation requests mark
ext.interchange.evaluation.evaluated: false, while screening requests mark
ext.interchange.screening.evaluated: false; those candidates were passed
through without the requested instructions. The usual max_results and its
server-marked deadline-snapshot pagination cursor still apply to that
replacement page. If no seller snapshot
has landed yet, the same incomplete response is an empty page and says so
without claiming that a seller failed to answer.
A country filter decides which storefronts are included, using each
storefront’s own accepted countries. A source’s sales agent declarations
(primary_channels and primary_countries) never narrow which sources on that
storefront receive the request. Every active source on a pure pass-through
storefront receives it; on any other storefront, an active source receives it
unless the storefront’s own channels or countries rule it out. A source that
has nothing for the requested country answers with no products.
Apostra rejects ambiguous seller-specific controls such as conditional
catalog versions on the aggregate surface. Query that seller’s AdCP endpoint
directly when you need a seller-specific conditional request.
Use canonical filter names
Apostra rejects known cross-operation fields insidefilters before contacting
any seller. Use filters.countries to narrow products by country coverage. Put
delivery targeting such as geo_countries under targeting_overlay, not
filters. excluded_content_categories is not a supported get_products
filter and must be omitted.
Canonical filter fields from the AdCP versions supported by Apostra remain
available. Put seller-specific filter criteria under a vendor namespace in
filters.ext, for example filters.ext.example_seller. These unsupported
fields return a validation error that names the field and how to correct it.
Canonical options from older seller formats
Buyers
When a seller still uses named legacy formats,get_products can return the
seller’s explicit mapping as a URL-free canonical format_options[] entry.
Buyer integrations do not need to change: existing canonical options and
legacy format_ids[] keep their current shapes.
When a buyer selects one of these canonical options, Apostra retains the
seller’s exact publisher-scoped route for later create_media_buy,
update_media_buy, and assigned sync_creatives delivery. The route is never
reconstructed from a similar format kind or ID. If the exact seller mapping is
missing, malformed, or inconsistent with the returned option, delivery fails
closed and the buyer should refresh products before retrying.
Sellers
Sellers opt in one format at a time through the catalog returned bylist_creative_formats. Add a canonical declaration to the legacy row. If
the option needs canonical parameters, include canonical_parameters on the
same row and use the same kind:
projection.diagnostics. Apostra never guesses a canonical kind from a
legacy ID or asset list, and one seller’s mapping cannot apply to another
seller.
Products may publish canonical format_options[] directly or retain exact
legacy references from a shared format catalog. Use the catalog mapping to
replace seller-specific formats that Apostra cannot interpret.
Product-format resolvability
When canonical-format compliance is enabled for a storefront, Apostra surfaces a seller-visible blocker only when a format cannot be mapped to an interpretable declaration. Exact legacy{agent_url, id} references remain
supported without a sunset, for both existing and newly connected sources.
Direct URL-free format_options[] are accepted but are not required yet. A
source with no persisted product-format evidence receives an evidence-pending
blocker until its initial catalog sync records declarations. Catalog age is a
separate freshness concern: an interpretable declaration does not become
noncompliant when its cache entry ages. An unresolved declaration remains
withheld until corrected. For a sales agent on the Agent-supplied path,
each live get_products response is a brief-specific observation,
not a complete catalog snapshot. The newest response for each public or buyer-account context
replaces that context’s previous compliance observation, so products omitted
from a later brief do not keep the source withheld. A buyer that tries to
purchase a previously returned product still has that exact product’s
declaration checked before the buy is forwarded. This
policy audits active external third-party sales-agent sources; managed and
modular inventory sources use their own readiness contracts.
A canonical-format blocker withholds the affected source from discovery and
media-buy admission until the seller replaces the unresolved custom reference
with an exact shared-catalog reference or an interpretable custom canonical
declaration. Other healthy sources in the storefront continue selling. If no
other source can serve, the storefront remains transaction-ineligible.
Choose get_products or Discover Products
Both surfaces share the same seller fan-out implementation. They are different
buyer projections, not different integrations.
Start with
get_products for new agent integrations. Use
Discover Products when you need
its legacy grouped/session presentation or need to continue an existing
discoveryId workflow. Calling both for the same request is normally
unnecessary; Discover Products projects the same raw seller snapshot rather
than running another ranking implementation.
A get_products execution_id is not a Discover Products session. Its
screened results are only readable through get_products: send the same
execution_id, with since_revision for newer results. Browsing it with
Discover Products (GET /api/v2/buyer/discovery/{id}/discover-products, or
browse_discovery) returns 409 CONFLICT with
details.reason: "discovery_read_requires_get_products". It never starts a
second search.
Surfaces
- REST:
POST /api/v2/buyer/products/query - Buyer MCP:
get_products - Buyer
api_call: operationget_products
- REST:
POST /api/v2/buyer/media-buys/batch - Buyer MCP:
create_media_buys - Buyer
api_call: operationcreate_media_buys
Continue the selected product query
When the buyer selects returned proposals or products, reuse the exactext.interchange.execution_id and storefront-qualified IDs from that
get_products result. Do not call get_products or Discover Products again
merely to attach, re-fetch, or reconstruct the selection. A new discovery is a
different snapshot: its candidates may differ or be empty, and it does not
identify the query the buyer selected from. The documented legacy recovery for
an execution that predates its durable accepted-proposal set still requires a
fresh get_products call; treat that response as a new selection and ask the
buyer to select from it again.
If an agent host offers the typed create_media_buys tool, call it directly.
On a reduced or shared tool catalog where that typed tool is absent but
buyer_api_call is available, use buyer_api_call with
operation: "create_media_buys". Both tool routes invoke the same continuation
contract. REST clients call the batch endpoint above. If the conversation no
longer contains the execution ID or a qualified selected ID, report the missing
handle and offer a new discovery as recovery; do not describe that new query as
the original attachment.
Retrieval without evaluation
Omitext.interchange.evaluation to receive valid seller responses without a
managed evaluation:
Include products from verified AdCP 2.x sellers
Some sellers still run a verified AdCP 2.x response contract, which predates the current requiredreporting_capabilities block. Their otherwise valid
products are excluded from the default response because Apostra does not
guess reporting cadence, delay, metrics, or webhook support.
REST and MCP callers can request the separate compatibility response by adding
the following field to get_products:
ext.interchange.response_contract. A projected 2.x product omits
reporting_capabilities and explains the omission explicitly:
response_contract to keep the original response schema, where every
product requires reporting_capabilities. Existing REST and MCP integrations
therefore need no changes. Sellers can remove the compatibility marker from
future discovery by upgrading their declared contract and returning the
current reporting block; no buyer-side account or purchase setting changes.
Request a smaller product projection
Use the canonicalfields array when the next step needs only part of each
product. Apostra validates the complete seller response before applying the
projection, then returns only the requested product fields. The qualified
product_id and ext.interchange provenance remain present so the result can
still be refined or passed to create_media_buys.
format_options and
reporting_capabilities are omitted. Omit fields when you need the complete
canonical product objects.
Evaluate and negotiate proposals
Add evaluation instructions when you want Apostra to remove unsuitable proposals, enrich accepted results, negotiate promising proposals, and optionally rank the accepted cohort before it reaches your agent:- Accept returns the seller’s unchanged proposal and referenced products, with optional buyer-owned enrichment.
- Reject suppresses the proposal from the normal result.
- Refine sends a canonical AdCP refine instruction back to that proposal’s seller, then evaluates the seller’s revised response again.
max_refinement_rounds, repeated-request
detection, the request deadline, and max_evaluation_passes. A proposal still
requesting refinement at the limit is rejected rather than silently accepted.
When ranking is present, a separate comparative pass scores accepted
candidates under its optional instructions. The response is ordered by score
and includes a rank and rationale. Provisional rankings replace earlier
snapshots as sellers settle; the final completed revision is frozen.
The platform selects the managed models. This version does not expose provider
model names, customer executable code, or a model picker.
ext.interchange.screening remains a deprecated compatibility alias for
accept, reject, and refine. It does not enable enrichment or comparative
ranking. Do not send screening and evaluation together.Discover Products compatibility
discover_products is a convenience view over the same seller fan-out and
evaluation engine. Passing its optional evaluation field enables the same
disposition, enrichment, refinement, and ranking behavior, projected into the
Discover response shape. Without evaluation, Discover preserves its existing
enrichment, relevance, ordering, and refinement behavior. Existing Discover
clients do not need to migrate to keep their current behavior.
Proposals and products
Canonical AdCP proposals reference sibling products through allocationproduct_id values; they do not duplicate complete product objects. Evaluation
resolves that graph automatically. A top-level product that is not allocated by
any proposal remains a proposal-less candidate, principally for wholesale
catalogs.
pagination.max_results bounds the combined number of proposals and
proposal-less products. Products referenced by a paged proposal accompany that
proposal and do not consume another candidate slot, so the proposal graph is
never split across pages. Apostra accepts at most 50 allocated products in
one proposal. A response contains at most 100 total proposal and product objects;
when complete proposal graphs reach that limit, the page returns fewer proposal
candidates and the cursor continues from the next whole proposal.
Both IDs are opaque and storefront-qualified:
The targeting a product lets you set
A product can carry AdCP 3.2overlay_support: the targeting dimensions you
may set on a package for that product, such as countries, regions, metro
systems like Nielsen DMA, or a frequency cap, with any per-package limits the
seller declares.
- Wholesale results (
buying_mode: "wholesale") return the seller’s product as the seller declared it, including itsoverlay_support. A storefront that sells only through the seller’s own sales agent, and builds no products of its own, forwards a wholesale request to that agent live and returns the agent’s catalog. When the agent does not listwholesalein its AdCPbuying_modes, that storefront’s result isno_inventory_for_request. - Brief results return products the storefront composes from its
inventory. A composed product carries the
overlay_supportof the inventory product it is built from, so both modes describe the same inventory the same way. A product composed before its inventory declared targeting carries it once the storefront recomposes it. - A product on a seller’s managed sales agent that the seller hasn’t narrowed
carries the targeting the seller’s ad server can apply as its
overlay_support. - Any other product with no declaration, or one that isn’t a valid AdCP 3.2
overlay_support(empty, or containing onlyext), has nooverlay_supportfield.
Stage or buy the result
Theexecution_id in the response is also the durable search/refinement
record used by create_media_buys. Choose whole proposals and/or
proposal-less products from that execution. The operation stages them on a
DRAFT campaign—the campaign is the shopping cart and the parent of every
media buy.
Only proposals in the execution’s durable accepted set can be selected. Run
get_products again before purchasing from an older execution that predates
that set.
Use an existing campaign cart:
campaign.create with the same required fields as a discovery-mode
campaign (advertiserId, name, flightDates, and budget). Apostra
creates the DRAFT campaign and returns its ID. Media buys are never standalone,
even when the caller did not create a campaign first.
mode: "stage"updates the cart and prepares DRAFT media buys without contacting sellers.mode: "execute"performs the same preparation, then sends each resulting buy to its originating storefront through ordinary bilateral AdCPcreate_media_buycalls.replace: truereplaces the cart selection before applying this batch; otherwise selections merge idempotently.
mode: "execute" when the selected result can be submitted immediately.
When you need to inspect or customize per-buy creatives, dates, pacing, or
optimization goals, use mode: "stage", make those changes on the returned
DRAFT media buys, then call execute_campaign or repeat create_media_buys
with the same campaign and selections using mode: "execute". Execution
submits the prepared DRAFT directly; it does not rebuild it from the product
query.
One call may reach several sellers, but the seller calls are not
one atomic transaction. The response reports mediaBuysExecuted, success,
and per-buy errors. Retry the same request after a partial failure; completed
buys are not dispatched again. A completed product query accepts only an
unchanged retry of its recorded batch. To change the selection after execution,
start a new get_products query.
See Create media buys from a product query
for the complete request and response contract.
Progressive responses
Inside Apostra, the runtime retains the original execution and request arguments, reads cumulative results withsince_revision: 0, and follows producer-issued
frozen cursors before attaching a selection. Its bounded wait can end with an
incomplete result; that does not mean the query found no products. See
Apostra continuation and attachment
for the wait limit, confirmed retries, and recovery behavior.
Seller responses arrive independently. Each response is a replacement snapshot:
revisionincreases as sellers settle or a refinement produces a new version;provisional: truemeans replace your previous displayed result;pending_agentsidentifies sellers still working;- fresh provisional revisions may contain seller progress but no candidates while typed product identity is still being persisted;
- proposals being refined are withheld;
- ordinary incomplete responses set
pagination.has_more: falseand issue no cursor; poll theexecution_idwithsince_revisioninstead. No stable cursor is issued untilresults_complete: true; storefront_results[].messagepreserves a seller’s explanation for a successful empty response, including when readiness prevents that storefront from transacting; do not interpret that case as “no matching inventory”;- a failed source request is reported as a failure, not an eligibility skip.
An asynchronous task that is still processing when the wait expires does not
establish that the seller has no matching inventory. Start a new query with a
longer wait to try again. Background source diagnostics may finish that task,
but do not reopen an execution whose
results_completeis alreadytrue; storefront_results[].error: "product_persistence_incomplete"means the storefront answered, but one or more candidates could not be persisted with a complete seller/source identity. Those candidates and any proposals that allocate to them are withheld. Safely persisted candidates from the same execution are still returned; start a new query to retry the withheld inventory. If no safe candidate remains, the request returns a retryable service-unavailable error instead of an authoritative empty catalog;- the final cursor is scoped to the execution, revision, evaluation instructions, and offsets.
evaluation.ranking is present, the accepted cohort is
ordered by that ranking instead.
Poll with the returned execution identity:
Evaluation metadata and cost
The response reports evaluation separately from seller progress:charged_ius remains 0. Retrieval without
evaluation reports billing_status: "included".
If managed evaluation is unavailable, valid candidates pass through and the
evaluation status becomes degraded; an infrastructure failure does not silently
reject seller supply. Every pass-through candidate is explicitly marked
ext.interchange.evaluation.evaluated: false (with confidence: 0), and the
response guidance says so. Check evaluated before treating an accept as a
judgment: evaluated: false means your evaluation instructions were not
applied to that candidate — re-run the request or apply your own screening
before buying on it.