> ## Documentation Index
> Fetch the complete documentation index at: https://docs.interchange.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release notes and changes to API v2

# API v2 Changelog

All notable changes to the Interchange API v2 are documented here.

## 5.148.0 — August 13, 2026 at 6:53 PM UTC

* Prospective buyers can now say whether they need a campaign management system or plan to use an AI agent, identify that agent when applicable, and describe their markets, channels, and timing. The commercial team uses those details to route the request. Submitting the form does not create an account, connect an agent, or grant access; access follows only after review and approval. Existing buyers do not need to take action.
* Universal Ads connection capabilities now show CRM audience sync as unsupported, and sync attempts stop before changing provider data. Existing connections need no reconfiguration; if you need CRM audience activation, choose a connected ad platform that reports audience sync support.
* Sellers with the modular sources capability can now send inventory feeds through authenticated Storefront API endpoints. You can preview pasted or uploaded static avails before committing them, commit a signed preview when it looks correct, or use the push endpoint for a single authenticated submit. Static avails and wholesale pricing feeds use the same source, contract, and tenant checks as the existing modular source setup.
* Action: no action is required for existing sellers. Existing sources, existing feed defaults, buyer-facing fulfillment, and runtime buyer behavior are unchanged. Nothing is converted automatically, and a seller must still have the existing `modular-sources` entitlement before creating or extending modular source feed workflows. Buyer impact is not applicable: this changes seller-side feed ingestion only and does not change buyer APIs, discovery, pricing, or media-buy behavior.
* Monetization: this does not introduce a new fee, buyer charge, billing meter, or UI package. Access follows the existing Enterprise `modular-sources` entitlement; any commercial value is through that existing entitlement and agreement path, not a new per-feed or per-request charge.
* Rollout and controls: rollout is gated by the existing `modular-sources` entitlement, not a new PostHog flag. Expansion means granting that entitlement through the existing admin entitlement ledger for approved seller cohorts. The kill switch is to stop granting or revoke the `modular-sources` entitlement for affected customers, which blocks new modular source composition and module attachment while leaving existing buyer fulfillment and runtime operations unchanged. Operational adoption is measured before expansion: at least one entitled pilot seller must complete preview, upload, commit, and push on a real modular source; stale baseline and invalid-token rejects must return the documented validation codes; and support must be able to diagnose any rejected row from the returned feed diagnostics without manual log inspection.
* Media buys across every storefront now reject an ISO subdivision before dispatch when a seller's value-aware capability explicitly marks that inclusion or exclusion value unsupported. Buyers do not need to change valid targeting requests; an unsupported value now returns a validation error before spend begins. Existing seller boolean region declarations require no change. Sellers who want value-level preflight enforcement can publish structured inclusion and exclusion evidence under `ext.scope3.storefront.geo_region_evidence`; the standard AdCP `media_buy.execution.targeting.geo_regions` field remains boolean. Storefronts without namespaced evidence keep their current behavior. The deprecated `supportedRoutingTypes` v2 field now returns the same behavior-free compatibility values for every storefront; `ROUTED` and `DECISIONED` do not classify storefronts or control targeting.

## 5.147.0 — August 13, 2026 at 5:49 PM UTC

* Sellers can now price display and video inventory independently, even when both formats share the same ad-server selector. Add a format reference to each row in your wholesale pricing feed and the platform applies the matching rate; buyers then see the price intended for the specific format they requested. Existing selector-only pricing feeds continue to work unchanged — format references are optional and only needed when you want format-specific rates.
* Reporting no longer converts delivered spend on a media buy that was never booked cross-currency. When a source reports delivery in a currency it is not paid in, that is a labelling defect, not an exchange: applying a rate to it multiplied correct spend by a real exchange rate and returned a plausible, wrong number. Delivery spend is now converted only where the buy's own booking evidence says the source is paid in the currency it reported. Where it isn't, the daily view keeps the row in the reported currency and the summary view returns `FX_RATE_UNAVAILABLE` instead of a converted figure.

## 5.146.0 — August 13, 2026 at 4:54 PM UTC

* Fixed a crash that caused WAV and other large audio file uploads to fail with "No creatives could be saved from the upload." The failure was a Node.js call stack overflow in the base64 validator when processing files larger than \~7.5 MB. Files are now accepted correctly.
* Fixed two defects in managed ESA media buy forwarding. HTML5 creatives now include their display dimensions when forwarded, resolving invalid creative rejections. Brand-safety signal exclusions now route to the correct targeting fields instead of being dropped by the GAM adapter.
* Merchandising Simulator proofs can now stay bound to one modular inventory
* source, with matching source evidence in API responses and the portable Page.
* Existing storefront-wide scenarios remain readable.
* When a buyer requests an account with your storefront, you can now approve
* them into an existing record in your ad server — the GAM Company, FreeWheel
* advertiser, or equivalent you already use for other advertisers you traffic.
* Their campaigns land against that record from their next media buy on. When
* you approve this way, you also state whose legal entity should be invoiced
* (the operator or the advertiser), so the invoice recipient matches the party
* you agreed to bill. Approving through Interchange billing and rejecting still
* work as before; this adds a third option for sellers who prefer to keep
* buyers inside their own account tree.
* Direct-billing is dark-by-absence until each seller opts in per the
* settlement-election spec, so ungated day-one behavior is unchanged for every
* buyer whose sellers do not use this decision. Buyers whose linked account
* flips from Interchange to direct billing will see the new invoice recipient
* when their sellers opt in and use this decision.

## 5.144.0 — August 13, 2026 at 9:52 AM UTC

* Buyer and seller reports now retain real delivery regardless of a media buy's lifecycle status. Control-state buys without delivery remain absent from summaries, preventing unapproved or pre-seeded budgets from affecting pacing while ensuring contradictory delivery is never hidden.
* Sales agent webhooks now return 410 Gone when the sending agent is disabled, instead of being silently accepted. If your integration receives a 410, verify that your webhook sender is using your current active agent ID. You can look up your active agents via the AdCP API or contact support.

## 5.143.5 — August 13, 2026 at 8:41 AM UTC

* `GET /api/v2/buyer/creative-dashboard-url` now accepts an optional `manifestId` query parameter. When `advertiserId`, `campaignId`, and `manifestId` are all provided, the returned URL navigates directly to that specific creative manifest in the Interchange UI rather than landing at the campaign level.
* Power buyers and agency teams using the buyer REST API can now update `packages[].targetingOverlay.audience_include` and `audience_exclude` on an existing media buy. Only the named package's audience lists change; its other targeting and sibling packages stay unchanged. Existing requests need no changes.

## 5.143.2 — August 13, 2026 at 6:12 AM UTC

* Fixed seller-adjusted demand revisions failing when an automatic approval tried to send the revised proposal.

## 5.141.12 — August 13, 2026 at 2:54 AM UTC

* Release the exact pre-fix Spotify rejection lease after verifying its reviewed zero-mutation evidence and immutable source.

## 5.141.11 — August 13, 2026 at 2:12 AM UTC

* Fixed Meta Engagement campaigns failing with "Upstream request failed" after setting `pageId` via `update_media_buy` on a multi-page account. The explicit page ID stored in the media buy is now correctly resolved and forwarded as `promoted_object.page_id` on the ad set. Meta API rejection details are now also surfaced in error responses to aid diagnosis.

## 5.141.10 — August 13, 2026 at 1:48 AM UTC

* Preserve Spotify's safe audience-upload rejection code through the adapter boundary.

## 5.141.9 — August 13, 2026 at 1:00 AM UTC

* Pin the legacy Spotify canary's text flight timestamp by digest before confirming paused containment.

## 5.141.8 — August 13, 2026 at 12:36 AM UTC

* Recover the exact interrupted staging Spotify canary only after fresh paused, zero-delivery containment is verified.

## 5.141.5 — August 12, 2026 at 10:46 PM UTC

* Sales agent registration and disabling now write an audit log entry, including for storefront-hosted agent rows that previously left no record. These entries appear in the storefront activity feed and record `adcp_agent.updated_by` so the row itself shows who last touched it.

## 5.141.3 — August 12, 2026 at 9:54 PM UTC

* Fixed two pacing period bugs that artificially constrained spend on replacement draft media buys (AI-6096).
* First, clearing per-buy pacing periods on a DRAFT or PENDING\_APPROVAL media buy was incorrectly blocked when any period had already started. Since pre-execution buys have no deployed packages, clearing is always safe and is now allowed.
* Second, when a draft buy with per-buy pacing periods is executed mid-campaign, elapsed periods' budgets are now redistributed into the remaining active periods rather than being silently dropped. This matches the behavior of the campaign-level pacing fallback path and ensures the buy's full product budget reaches the seller.
* Meta governed CRM staging canaries now recognize the protocol's explicit idempotent-replay marker while still requiring the replayed audience payload to match exactly.

## 5.141.1 — August 12, 2026 at 8:56 PM UTC

* Your one-time 100-IU credit now expires exactly 60 elapsed days after acceptance, regardless of billing-cycle dates. Settings → Plan & Billing and MCP Apps show the same stored expiry, and existing credits keep their original dates.

## 5.139.0 — August 12, 2026 at 7:48 PM UTC

* Your storefront can now decide whether a brief is worth answering, before your Merchandising Agent composes anything. Set a **selling doctrine** on your Playbook: a minimum category fit to respond, how readily you counter-pitch instead of walking away, and what to do when a stated budget meets an unpriceable catalogue. Your Merchandising Agent then pitches the brief in full, counter-pitches with a credible reframe, or passes with a short, branded decline. Adopt a named starting point (`premium_scarcity_house`, `volume_partner`, `consultative`) or set your own numbers. Doctrine rides the same Playbook versions you already author, so reverting means activating the previous version, and every decision is recorded on the proposal pass with the doctrine version and the rule that reached it. On a pass your storefront withholds the composed proposal and returns its existing no-fit response shape, so a buyer can't tell a decline from nothing having matched; passthrough inventory and already-finalized proposals still ship. The decline is recorded for you, not sent to them.
* Signing out now fails safely: if the sign-out request doesn't reach the server, you stay signed in and see an error instead of a false "signed out" screen. This matters most on a shared or public computer, where the previous behavior could leave your session active even though the screen showed you as logged out.
* A brief that a storefront's Merchandising Agent genuinely has nothing for now returns a normal empty product set instead of an `INVALID_REQUEST` error. AdCP has one shape for "no bid" — an empty catalog — and this aligns the composer's silent no-fit with it, so your agent can treat every empty discovery the same way. A seller who deliberately authors a decline note in their rulebook still sends it; only the default silent no-fit changed. An empty catalog is also, by design, all your agent sees when a seller's own selling rules chose not to answer a brief — the two are deliberately indistinguishable, so treat any empty discovery as "nothing here for this ask" and move on or re-brief.

## 5.138.0 — August 12, 2026 at 6:42 PM UTC

* If your operator domain was saved with an `https://` prefix, that prefix is now stripped automatically. Nothing to change on your side.
* **Agencies and consultants verifying a client domain:** you can now self-serve verification from account settings instead of filing a support request. Two paths are available:
* **Verify via AAO:** If your agency's work-email domain matches the operator domain you're claiming, sign in through your AdCP Alliance Organization account. Verification completes automatically.
* **Request manual review:** If the operator domain belongs to a client whose email domain differs from your agency's, submit a review request from account settings. Scope3 reviews within one business day and follows up on the outcome. This path resolves email-domain mismatches only. If the stored operator domain itself is wrong for your account (for example, it points to the wrong client), contact Scope3 support to have it corrected — manual review will not resolve that case.
* **Already verified and transacting?** No action needed. Verification status and transacting access are unchanged for existing accounts.
* A verified operator domain is a transacting prerequisite. There is no separate charge for verification.

## 5.137.0 — August 12, 2026 at 5:47 PM UTC

* Seller Setup and modular source diagnostics now show the same setup progress and next action for each modular source. If a feed row's publisher properties or creative formats cannot be verified against that source's current Property Roster, the row is rejected; resolve the shown issue before committing the feed. Existing valid feeds need no changes.
* Your organization now receives its one-time 100-IU setup credit when it accepts its first IU plan through Plan & Billing or Murph, including for an existing account. Retries and later plan revisions do not create another credit.

## 5.136.0 — August 12, 2026 at 4:31 PM UTC

* The inventory source input guide now provides copyable files through a public example-pack page, distinguishes complete external-agent pass-through from sources that need inputs supplied separately, names the built-in provider paths, and organizes setup around five customer questions plus explicit operating tracks.

## 5.135.0 — August 12, 2026 at 3:38 PM UTC

* Account analysis now presents campaign health, format performance, and metric labels in consistent sentence case — status values like "Needs attention", "Behind", and "Above benchmark" read cleanly instead of raw lowercase, while metric acronyms (CTR, CPM, ROAS…) keep their standard casing. No action is required.
* Agent collection rows now open their canonical Agent Page in the web app.
* Buyer discovery no longer withholds a third-party pass-through sales agent
* because a product from an older, brief-specific response remains in its local
* history. Interchange now evaluates the source's newest live response alongside
* its seller-authored catalog. Unresolved products in that current evidence are
* still withheld.
* Previously returned product IDs remain protected: if a buyer later tries to
* purchase one, Interchange checks that exact product's format declaration before
* forwarding the media buy.
* Enrolled sellers can open the legacy Source mapping workspace reliably again. Access remains limited to enrolled customers, with nothing to change on your side.
* v3 search for `creative` and `creative_collection` now supports cursor-based pagination. Previously the result was capped at 100 rows with `hasMore: true` and no `nextCursor`, leaving items past the first page unreachable. Pass `limit` (up to 200) and the returned `nextCursor` to page through large sets.

## 5.134.0 — August 12, 2026 at 2:41 PM UTC

* Approved storefront media buys with no creatives attached now reach the sales agent instead of being rejected. Forwarding added an empty `creative_assignments` list to each package, which AdCP does not allow — the field must name at least one creative or be omitted entirely. Buys that are booked before their creatives are ready now forward with the field omitted, and the seller reports them as awaiting creatives. Assignments the buyer has since cleared are no longer forwarded from the frozen request, and a package carrying inline creatives forwards untouched while its creatives still match the buy.
* Creative syncs to a storefront no longer fail when the seller has accepted a creative but has not yet placed it on an ad server. A seller's platform creative ID is now recorded as evidence whenever it arrives — on the sync acknowledgement or on a later creative webhook — rather than being required up front. A seller that echoes the buyer's own creative ID back as its platform ID is still reported as unconfirmed.
* For buyers: a creative you sync to a storefront before assigning it to a package now reports as synced instead of failed, and its platform ID fills in once the seller's ad server issues one. Nothing changes in how you call `sync_creatives`, and no action is needed on your side.
* For sellers: a creative you have accepted but not yet trafficked now registers as synced on the buyer's side instead of showing as a failed sync against your storefront. Nothing changes in what you send — report your platform creative ID once your ad server issues one, and keep sending it on the acknowledgement when you have it there.
* Campaign delivery now loads correctly after a single-storefront media buy is created through Interchange. No action is required.

## 5.133.1 — August 12, 2026 at 12:54 PM UTC

* Provider-backed campaigns now return delivery and accept updates using the correct platform campaign while keeping the same buyer-facing media-buy ID. Nothing changes in buyer requests or responses.
* Third-party storefront catalogs no longer go stale indefinitely on the buyer
* discovery path. Cache-only product reads now revalidate a stale catalog in the
* background instead of serving the same cached products forever. Previously, a
* third-party source whose live discovery calls chronically timed out could
* serve month-old products, which newer creative-format validation then filtered
* out entirely - surfacing as empty discovery results and failed media buy
* submissions for otherwise healthy sellers.

## 5.133.0 — August 12, 2026 at 11:38 AM UTC

* Audience syncs now fail safely unless a connected platform can prove it can create, update, use, and remove the exact customer list. Meta, Snap, and TikTok receive continuous lifecycle verification; Spotify refuses unverified uploads; and Google, LinkedIn, Pinterest, and Reddit remain unavailable for governed sync until their safety checks are complete. Buyers do not need to take action. Seller storefront display and readiness are unchanged.
* Meta Sales media buys now accept a `pixelId` field on product selections so buyers can specify which Meta Pixel / Dataset to use for conversion tracking. Pass `pixelId` in `create_media_buys` selections, `add_discovery_products` selections, or `update_media_buy` product entries. Unlike `pageId`, there is no auto-select: every Meta Sales (OUTCOME\_SALES) buy must explicitly specify a pixel.
* Partner organizations can now use one accepted Offer to operate a certified sales agent for explicitly authorized client organizations. In the Partner page and Partner access API, accepting the Offer grants the paid operating right after payment, ownership, registration, and certification are current. An existing Partner needs an Offer that expressly includes this right before operating for an unrelated client; free Partner registration, testing, and certification are not converted or removed.
* This pilot does not add a buyer-visible badge, directory placement, promotion, or ranking change. Certified Partner listing remains a separately verified manual program, and any Featured Partner placement is labeled and cannot affect organic ranking or Murph recommendations. Existing Partner API integrations do not need to change immediately: `featureKey` keeps its legacy value during the v2 rollout, while the additive `entitlementFeatureKey` identifies the paid right. New and existing Partners can review the operating boundary in [Partner Program and agent operations](/v2/storefront/inventory-sources/partner-account).

## 5.132.0 — August 12, 2026 at 10:50 AM UTC

* Use the **Prepare your inventory onboarding materials** guide to separate
* operational source truth from merchandising decisions. Sellers can download
* CSV and JSON compatibility templates validated against
* `static-avails-feed:v1`, complete a source-authority worksheet, and rehearse a
* fictional campaign while seeing
* exactly which files are production-importable, supporting evidence, manual
* pilot steps, or gaps. Existing inventory-source behavior is unchanged.
* The compatibility templates retain the parser's exact legacy `collectionId`,
* `collectionName`, and `collectionDescription` fields; those values do not
* establish AdCP Collection identity, and the templates are not the target
* Inventory Feed schema.
* Activating, archiving, or renaming a product in Inventory Components works again. The widget sent the change as a full product replacement while carrying only the field you touched, so the sales agent rejected it for the name and inventory such a body leaves out — the product stayed in Draft behind a `REST call failed (400)`. Edits now send only what this surface edits — Activate and Archive send the status alone, the edit form sends name, description, and status — so the pricing, coverage, and formats it never shows you keep their stored values. The edit form also opens with the product's current name, description, and status filled in instead of blank.
* For anyone changing a product through the API: the partial-update endpoint is now reachable over REST as `PATCH /api/v2/storefront/esa/{esaId}/products/{productId}`, and both it and the `patch_esa_product` operation take the partial-update body the sales agent documents — a field sent as `null` keeps its stored value instead of being rejected. The Storefront API reference now shows that body.
* Meta CRM audiences now keep their buyer identity when provider metadata is
* temporarily omitted, and governed test fixtures are deleted and verified by
* their exact provider identities.
* Creatives you submit to Meta now appear in list and get responses exactly as
* submitted, with nothing to change on your side.

## 5.131.0 — August 12, 2026 at 8:43 AM UTC

* Storefront health now reports **Available, needs attention** when one external
* sales-agent source is withheld for unresolved product formats while another
* source continues serving buyers. The affected source keeps its independent
* connectivity result, so a successful Agent response is not mislabeled as an
* outage.

## 5.130.1 — August 12, 2026 at 6:17 AM UTC

* Meta media buys now accept a `pageId` field on product selections so buyers can specify which Facebook Page to use when the connected Meta ad account has more than one authorized Page. Pass `pageId` in `create_media_buys` selections, `add_discovery_products` selections, or `update_media_buy` product entries. When the account has exactly one authorized Page the field remains optional and the server selects it automatically.

## 5.129.1 — August 12, 2026 at 5:03 AM UTC

* Buyer discovery no longer withholds a third-party sales-agent source merely
* because its last interpretable product-format declaration crossed the catalog
* cache freshness window. Catalog refresh continues independently. Unresolved
* formats and sources with no persisted declarations remain withheld. Other
* healthy sources in the same storefront continue selling.
* Sellers do not need to republish an otherwise valid canonical declaration or
* exact shared-catalog legacy reference just because its cached snapshot aged. A
* corrected declaration takes effect on the next readiness evaluation after the
* refreshed product is recorded.
* New Rate Cards now omit human expert support, audio/video understanding, and modular source management as separate Intelligence Unit activities. Human support and modular-source access remain Enterprise contract terms, while audio transcription used with Murph stays included in the Murph session. Sellers do not need to update existing accepted Rate Cards or Offers: their immutable activity schedules remain unchanged.

## 5.128.0 — August 12, 2026 at 3:16 AM UTC

* When a buyer or seller/storefront organization has an IU plan offer, its organization admins can review the exact terms of the selected Rate Card plan in **Settings → Plan & Billing** and in the portable IU-plan authorization task. Each offer shows whether it uses the plan’s standard terms or explicit customer-specific customizations.
* No action is required. Existing accepted offers, including accepted 250-IU terms, remain unchanged, and existing V2 API requests continue to behave as before. This release does not republish or change the staging Rate Card.

## 5.120.0 — August 11, 2026 at 8:49 PM UTC

* TikTok creative inventory drift errors now include a precise, identifier-free `reason`, helping buyer integrations distinguish stale inventory, format provenance, and provider digest conflicts without changing requests.
* Set a fixed CPM when you create a product
* You can now give a product a fixed rate as you author it. Asking for one in Murph chat used to fail with `unsupported product fields: pricing_options`, and the only way to create the product was to drop the price — which shipped it as an auction with no floor, so buyers never saw it.
* This matters most when one ad-server selector needs more than one price. An uploaded pricing feed keys each row on the selector, so a single ad unit serving both display and video gets the same price for both. A rate set on the product is per-product: create one product per format and price each one on its own.
* The rate must be in your storefront's settlement currency — there is no FX. If it isn't, the product is still created but stays hidden from buyers, and the response now tells you which currency was wrong instead of leaving you to find an invisible product.
* TikTok carousel creatives remain available when the provider's broader image search takes longer to publish their readiness details. Nothing changes in buyer requests.
* When a buyer's OAuth connection to an adapter storefront (such as Meta Ads) becomes invalid, `discover_products` previously returned 0 results with no explanation — indistinguishable from a genuine empty inventory response. Buyers now receive a `connectionIssues` signal in the response indicating that the connection needs re-authentication, so the problem is visible rather than silent.
* No action is required beyond reconnecting the affected account via **Settings > Connections**. Once re-authenticated, product discovery resumes automatically.
* TikTok creative inventory now ignores non-reusable external-identity assignments regardless of the material fields TikTok reports for them, preventing those account-owned ads from blocking buyer media-buy creation. No request changes are required.
* When TikTok rejects creative image evidence, buyer integrations now receive a precise `validation_reason` for invalid single-image counts, carousel counts, or image formats. No request changes are required.
* The Murph agent debug-calls lookup (`GET /api/v2/murph/agent-debug-calls`) now honors and echoes the lookback window it applied. Every response includes a `window` object reporting the hours covered, the hours you requested, and the exact start/end timestamps — so a short lookback can never be mistaken for a longer one. `windowHours` is now documented and bounded to 1–720 (30 days); values above 720 return `400`, and omitting it defaults to a 7-day window instead of an unbounded most-recent scan.
* AdsWizz-connected storefronts now keep order status and booked-flight checks
* working when their agency credential has limited order-read permissions.
* Existing buy dates are unchanged, and no action is required.
* Make storefront discovery previews and source tests distinguish a completed empty seller catalog response from discovery that stopped before a seller `get_products` round-trip.
* A storefront no longer hides its entire product catalog when one inventory source cannot be format-audited. A single source with stale or uninterpretable product-format evidence used to block everything: `get_products` returned no products and every media buy was refused, including for healthy sources whose formats were perfectly valid. That source is now withheld on its own, so the rest of the catalog stays discoverable and buyable. A buy that does route to a withheld source is refused with a distinct reason rather than an unknown-product error, so a buyer agent can tell "try again later" from "wrong product id".
* For sellers, this changes what one troubled source costs you: the rest of your storefront keeps selling instead of going dark, and only the affected source is held back until its formats can be read again. Product-format evidence for third-party sales agents now refreshes on its own as well, so it no longer expires while your storefront waits for the buyer request it was being blocked from serving. Nothing to change on your side.

## 5.119.1 — August 11, 2026 at 1:08 PM UTC

* Ignore externally managed TikTok Spark assignment formats that are not reusable advertiser creative inventory.

## 5.119.0 — August 11, 2026 at 12:58 PM UTC

* Buyers can now ask Murph to open Notifications and review campaign and account events. Sellers can open the same Page to review storefront events and manage Product Updates and source-health alerts in their primary Slack channel. No setup is required. Read and acknowledged states remain separate for each recipient. Slack, email, and webhook delivery never changes either state. Release history remains in the separate Release notes Page.
* Keep TikTok reusable creative inventory available when an advertiser also contains ads backed by provider identity types that cannot be reassigned through authorization-code inventory.
* Reconnect your existing Reddit Ads connection once in **Settings → Connections** so it can keep working after the initial one-hour token expires. New and reconnected Reddit Ads connections refresh automatically.
* Murph can now look up your storefront's published brand identity without asking you to approve a read-only action or losing the action between turns. Direct storefront API behavior is unchanged.

## 5.118.0 — August 11, 2026 at 11:49 AM UTC

* Enrolled sellers can use `get_delivery` on `/mcp/v3` to query up to 90 days of seller-reported delivery or cumulative storefront margin in pages of up to 100 rows; the response makes unavailable values and pagination explicit, and neither buyer measurement nor `/mcp/v2` behavior changes.
* Keep TikTok reusable creative inventory available when an advertiser also contains linked-account Spark ads that cannot be reassigned through authorization-code inventory.

## 5.117.0 — August 11, 2026 at 10:58 AM UTC

* Meta Engagement campaigns can now be created successfully. Previously, any attempt to launch an Engagement campaign failed with a generic "Upstream request failed" error. No storefront configuration changes are needed — previously failed campaign creation requests should be retried.
* If your storefront uses AdsWizz and you want to open new buys, confirm the
* currency in your ad-server setup with your Scope3 contact. Interchange applies
* that currency to every AdsWizz campaign and checks any optional CPM ceiling
* before sending it. New buys remain closed until Scope3 independently verifies
* that AdsWizz accepts the currency; existing live buys keep running and need no
* action.

## 5.116.0 — August 11, 2026 at 10:34 AM UTC

* Accept TikTok's empty non-applicable ad material fields without weakening validation of reusable creative evidence.
* The v3 agent surface now supports the `creative_collection` noun for non-executable grouping and joint review of creatives. Buyers can search, read, create, update, and manage collection membership through `search`, `get`, and `save_creative_collection`.

## 5.115.2 — August 11, 2026 at 10:16 AM UTC

* Keep TikTok reusable creative inventory available when an advertiser also contains provider-managed catalog carousel or live-content ads.

## 5.115.1 — August 11, 2026 at 9:16 AM UTC

* Keep TikTok creative inventory usable when an advertiser contains externally authored carousel ads, while preserving strict ownership checks for adapter-managed carousel assets.

## 5.114.5 — August 11, 2026 at 6:57 AM UTC

* Murph now shows storefront product results as they arrive in one live discovery view, labels provisional totals as “so far,” and waits for completion or the buyer's explicit choice to continue before showing recommendations. Wait explanations stay specific to an individual storefront's observed outcome instead of generalizing latency across countries, regions, or groups of sellers. For sellers, buyer-facing status now uses neutral storefront-specific outcomes without characterizing the seller, its geography, or its peers as slow.
* `discover_products` and `browse_discovery` now surface a `connectionIssues` field when an adapter OAuth credential (e.g. Meta, Snap) has expired. Previously, products from that storefront were silently omitted with no indication that re-authentication was needed. The new field names the provider and affected storefront so the buyer can navigate to Settings > Connections to reconnect.

## 5.114.4 — August 11, 2026 at 6:30 AM UTC

* Background meeting reconciliation now leaves exhausted, unchanged Zoom transcripts terminal instead of retrying them indefinitely. Source-health notifications can also recover when Murph can join a public customer channel but the provisioning bot cannot invite it. No action is required.

## 5.112.0 — August 10, 2026 at 11:57 PM UTC

* `create_media_buys` and `update_media_buy` now warn as soon as a media buy is staged or updated if the owning campaign's pacing schedule has no period covering today or later — instead of only failing later when you try to execute. The warning tells you to call `update_campaign` with `pacingPeriods` covering the new dates before executing.

## 5.110.0 — August 10, 2026 at 9:55 PM UTC

* Sellers now get notified about a few more storefront issues they can actually fix, like rejected delivery reports or a sales agent responding with errors, instead of only finding out by checking the storefront dashboard.

## 5.108.0 — August 10, 2026 at 6:48 PM UTC

* Organization account admins enrolled in Organization Agents can open the Agents collection and choose Create Agent to register a private Agent. Choose a claimed operator or name a new one, then continue in Agent Overview. This does not connect a Source, publish the Agent, or change existing Agents.
* Spotify connected account sync now reuses media buys created through its legacy direct adapter flow instead of failing on a duplicate. No action is required.
* Preserve authenticated Spotify account identity when reading media buys so account sync can safely reconcile legacy direct-adapter campaigns.
* Delivery reporting no longer records a zero-impression day when a publisher's sales agent reports that it has no delivery data for that day yet. Previously the day was stored as zero, and because a past day is never re-read, that zero was permanent — a campaign that was delivering could report zeros indefinitely. The day is now left absent until real figures arrive, and the source's reporting is no longer counted as healthy on the strength of a response that reported nothing.
* Publishers need take no action, and nothing changes in what they are asked for or shown: their own reporting is unaffected, and a day their ad server could not report yet is now recorded as pending rather than as zero delivery. The one indirect effect is that a sales agent whose reporting is genuinely not returning data will no longer be counted as healthy on those responses, so a real reporting outage becomes visible instead of looking like a campaign that simply did not deliver.
* Creative sync now reports the state your seller actually sent, instead of a
* state we filled in. A seller may acknowledge a creative without stating a review
* status — the ad protocol allows it, and it means "accepted, nothing further to
* report". We substituted "processing" and then read our own guess back as a
* seller-side stall, so a creative the seller had accepted showed as failed with
* "is processing and is not live". That invented status is gone.
* Several related misreports go with it, all in the same direction: a creative
* that was not ready being shown as ready. A creative is still only reported live
* once the seller names it on their delivery platform.

## 5.107.0 — August 10, 2026 at 5:17 PM UTC

* Buyers now see clearer storefront language that distinguishes a seller's wholesale price from your price and explains advertiser routing, with no workflow change. Sellers now see plain mapping and coverage labels across setup, exports, and guidance, making it easier to confirm which catalog details are ready for buyers; no setup or API behavior changed.
* Organizations enrolled in the Agents preview can now review the software
* Agents they operate, including their certification and implementation-health
* summaries. A storefront can also see the Agent that powers its own Source
* without exposing other organizations' connections or credentials.
* Connected account sync no longer fails or creates a duplicate when it finds a media buy placed through an older adapter route. No action is required.
* Expanded buyer and seller chat widgets now scroll through their full content without requiring per-widget host configuration.
* Fixed `get_storefront_reporting_metrics` returning zero impressions and spend for media buys delivered through managed ad-server sources. Reporting now correctly includes delivery data for all source types on a storefront.
* Storefront logos now come only from identity asserted through `brand.json` or the AAO registry. If no authoritative identity exists, the storefront shows no resolved logo instead of substituting one inferred from a website or enrichment service. Murph also keeps unsupported flat-rate, time-based, click, and engagement pricing in their original commercial units rather than translating them into invented CPM or impression figures, and explains that a storefront run by experts uses the canonical `https://interchange.io` publisher-authorization identity rather than its buyer-facing MCP endpoint.
* The v3 agent surface now supports the `creative` noun. Buyers can search, read, create, update, and archive creatives through the standard v3 verbs (`search`, `get`, `save_creative`). Campaign creatives are also available via `get(kind: 'campaign', include: ['creatives'])`. This is the BYO-first slice: generation sessions and collections are separate follow-up nouns.
* Storefront media buys now reject stale or invalid creative-format selections before entering manual approval, instead of failing only after seller review.

## 5.106.0 — August 10, 2026 at 3:38 PM UTC

* Connected account sync now reuses the buyer's existing campaign when the provider returns the same media buy, instead of failing while attempting to create a duplicate.

## 5.105.0 — August 10, 2026 at 2:56 PM UTC

* When you upload a zip containing files that Murph doesn't recognize (for example, an HTML5 ad bundle packaged as a nested zip), those files now appear in a notice telling you which ones weren't added and why. Previously they were silently dropped with no feedback.

## 5.104.0 — August 10, 2026 at 1:01 PM UTC

* Add an advertiser right in chat. Click **+ Add advertiser** or just ask Murph
* ("add an advertiser called Acme at acme.com") and a guided form opens,
* pre-filled with whatever you said — fill in the rest, and it creates the
* advertiser and links its brand. When it's done, Murph confirms and can switch
* you straight into the new advertiser, with **Switch into it** and \*\*Add
* another\*\* actions right on the form.

## 5.102.0 — August 10, 2026 at 10:21 AM UTC

* Creative sync status now includes the publisher's public AdCP agent or inventory
* source identifier in `sourceId`. The existing `agentId` remains unchanged for
* compatibility. Approvals, history, and seller workflows are unchanged, and no
* action is required.
* Discovery Card and Business Rules now use the full available Page width, keep long content reachable through one dependable scrollbar, link brand management to the identity's real owner, and make worldwide country coverage explicit when editing legacy cards.

## 5.100.0 — August 10, 2026 at 8:55 AM UTC

* Managed ad-server sources now prove their execution currency before they can be connected or accept a new buy. The storefront checks that currency against the seller's settlement currencies, rechecks it after credential changes, and no longer assumes USD when an adapter has not supplied a currency. Existing buys keep their original currency while a mismatch is repaired.

## 5.99.0 — August 10, 2026 at 7:16 AM UTC

* Canonical product discovery and forwarding now use the SDK's supported additive projection and durable legacy-route sidecars while keeping advertised format options URL-free.

## 5.98.0 — August 10, 2026 at 6:36 AM UTC

* Reddit campaigns without an update timestamp now sync correctly; no buyer action is required.

## 5.97.0 — August 10, 2026 at 6:01 AM UTC

* LinkedIn connections now ignore legacy personal ad accounts during discovery, so setup completes when supported business accounts are available. Nothing needs to change on your side.
* Reddit media-buy sync now remains compatible when Reddit adds a new raw campaign status, using the campaign's configured lifecycle status for buyer-facing state and actions.
* When buyers create a media buy through a provider-policy-owned social storefront (LinkedIn, Meta, Pinterest, Reddit, Snap, or TikTok), the storefront no longer reports itself unavailable solely because it has no Interchange acceptance policy. The social platform continues to apply its own review rules, while adapter and managed storefronts configured for Interchange approval still require an active policy and approver routing. Nothing to change on your side.

## 5.96.1 — August 10, 2026 at 5:42 AM UTC

* Snap storefront account sync and media-buy reads now complete when Snap omits redundant account ownership or returns empty demographic targeting. No action is required.
* Fixed `execute_campaign` failing with "This storefront is blocked and cannot accept media buys" for adapter storefronts on accounts that own multiple storefronts. The eligibility check now evaluates the specific target storefront rather than an arbitrary storefront belonging to the seller.

## 5.96.0 — August 10, 2026 at 5:25 AM UTC

* Before connecting a new ad server, confirm the default and payment currencies in Storefront setup. The connection then verifies its execution currency instead of assuming USD:
* For AdsWizz, enter the agency billing currency in the ad-server connection form.
* Google Ad Manager discovers its supported currencies automatically.
* FreeWheel and SpringServe use the confirmed storefront default.
* Already live? Existing buys keep their original currency. If the ad-server connection reports a missing or mismatched currency, update the Storefront currency settings or reconnect the ad server before accepting a new buy.

## 5.95.2 — August 10, 2026 at 4:42 AM UTC

* Buyers can update creatives while a media buy awaits storefront approval without losing those changes when the buy is forwarded. Storefront operators receive the forwarded media buy with the buyer's latest creative assignments intact. Neither audience needs to take action. Background reconciliation and source-health checks now retry transient provider failures without repeated alerts.
* When you buy through a connected Reddit account, product discovery now returns the full wholesale catalog without a brief, and campaign syncs use the credential attached to the selected account. Nothing to change on your side.

## 5.95.1 — August 10, 2026 at 4:21 AM UTC

* Forced publisher-agent discovery refreshes now return the latest authorization directly from the publisher's live `adagents.json`, including newly added or removed agents, while the registry mirror catches up. The response keeps the registry's last-validation timestamp and identifies the live origin as its freshness source, so a stale crawl timestamp no longer means the refreshed authorization was ignored.

## 5.95.0 — August 10, 2026 at 4:13 AM UTC

* Discovery Card logos with transparent backgrounds now receive a contrast tile in both seller setup and Marketplace, so light or dark artwork remains visible instead of disappearing into the card.

## 5.94.0 — August 10, 2026 at 3:16 AM UTC

* Murph now presents updates to an existing ask with the correct ask reference and requester state instead of describing them as a new, unrecognized ask.
* Pass-through media buys now preserve source-authored canonical creative format selections when forwarding, preventing valid buys from failing before they reach the source sales agent.

## 5.93.11 — August 9, 2026 at 4:32 PM UTC

* Preview accounts can now use the **Inventory sources** selector at the top of the seller rail to switch between the overall Storefront and an exact source, or add another source. Each source opens its established detail page. The mapping-workspace preview is no longer shown in the UI, while existing API compatibility reads continue to work. No setup or integration change is required, and product delivery, pricing, and packaging are unchanged.

## 5.93.10 — August 9, 2026 at 4:12 PM UTC

* Storefront composition now preserves selectable creative formats and their exact delivery routes when a wholesale source publishes legacy formats only.

## 5.93.9 — August 9, 2026 at 3:17 PM UTC

* Media buys against pass-through inventory now reach their source when the buyer picks a creative format from a source that publishes its formats in the legacy form. Product discovery already offered those formats as canonical options, but the forwarding step did not recognise the option ids it had just advertised, so an approved buy failed with `invalid_format_selection` and could not be retried. Discovery and forwarding now read a source's legacy formats identically, so this holds however the source declares them. A package that selects several of a source's legacy formats now forwards all of them.

## 5.93.3 — August 9, 2026 at 12:41 PM UTC

* Buyers now see reliable Discovery Card logos, a consistent description label, and the seller’s complete description instead of a trapped scrolling field.
* Sellers editing a managed Discovery Card in Seller Setup must now choose at least one accepted country or select every country before saving. Existing cards remain visible until they are edited, and sellers who already listed countries do not need to do anything.
* Buyers filtering Marketplace by country will still see a storefront when that seller has not yet finished listing where it sells, so existing sellers do not disappear during this update. A storefront that names supported countries appears only in those countries, and one that explicitly supports none stays hidden. Buyers do not need to take action.

## 5.92.2 — August 9, 2026 at 10:37 AM UTC

* Reddit audience signals and campaign syncing now complete reliably instead of failing on valid Reddit responses. No action is needed.

## 5.92.0 — August 9, 2026 at 6:48 AM UTC

* Meta creative retries after a rate limit or rejected sync are now safer: they avoid duplicate ads and reuse existing uploads when possible. No action is needed on your side.

## 5.91.0 — August 9, 2026 at 5:18 AM UTC

* Your storefront now writes the argument behind a proposal, not just the plan. When a brief arrives, your Merchandising Agent composes a pitch that leads your proposal pass in the demand inbox: a thesis for why this plan fits this buyer, each product's role and its fit, what will and won't be measured, the case for the price, and an honest note on anything the brief asked for that your catalogue doesn't cover. The product table moves below it, unchanged, as the plan appendix. Every sentence in the pitch cites the brief, your inventory and product data, your Playbook pricing, or your Playbook instructions — an unsourced sentence is dropped before you see it. That's why a thin setup reads plainer: audience-size claims and superlatives have no source in the platform today, so they never compose, while a maintained rate card and a written Playbook give the pitch more to argue from. The pitch is included in your existing storefront plan — no new billable surface. Buyers still receive products and prices exactly as before; the argument is on your side of the exchange for now.

## 5.90.0 — August 8, 2026 at 9:05 PM UTC

* When you assign creative to a Meta media buy, temporary provider failures are now retried automatically without risking duplicate ads. Terminal failures no longer expose raw provider details. Nothing to change on your side.

## 5.89.1 — August 8, 2026 at 8:10 PM UTC

* Signing in to Interchange now remains available when an OAuth integration repeatedly retries an expired session. No action is needed on your side.

## 5.89.0 — August 8, 2026 at 7:39 PM UTC

* For completed v3 requests, Activity call records now list each buyer or storefront API operation routed through the compatibility layer, in order. This makes retries and downstream failures easier to diagnose; cancelled requests report the evidence as unavailable instead of showing a partial history. Nothing to change on your side.
* On each Source page, you can now review coverage separately for Storefront-built products and products supplied by a connected Agent. Existing Sources need no action. A **Needs attention** section names the owner and next step: Storefront catalog or routing gaps identify what to provide to Scope3 support, while Agent-owned product gaps must be corrected in the connected Agent and resynced. A catalog that has not synced successfully is shown as unavailable instead of empty. Direct mapping edits are not yet available in these workspaces, and Agent-supplied products remain read-only in Interchange. Switching product modes keeps inactive mappings for later without applying them to current products. Product paths are not separately priced, and buyer API fields, product labels, ranking, and delivery behavior do not change.
* On the Connections page, you can now unlink an ad platform connection from its card or detail view. Unlinking stops future syncs and campaign subscriptions for every advertiser using the organization-level grant. Historical reporting and advertiser mappings remain.

## 5.88.0 — August 8, 2026 at 6:02 PM UTC

* Buyer and seller REST integrations can now pass `clientRunId` to
* `GET /api/v2/activity/calls`; list and detail responses also expose nullable
* `clientRunId` and server-observed `apiVersion`. `clientRunId` is caller-supplied
* correlation, not independent provenance: cross-check `workloadUid`, `runUid`,
* `apiVersion`, and the time window. Results remain account-authorized, and
* service tokens remain restricted to their workload. Existing integrations
* require no changes unless they adopt the optional filter or fields.

## 5.87.2 — August 8, 2026 at 5:20 PM UTC

* Buyer supply requests now save against the authenticated Interchange account even when it has no Linear customer association. Repeating a withdrawal safely reports that there is nothing left to remove. No customer action is required.

## 5.87.0 — August 8, 2026 at 4:15 PM UTC

* Pausing Meta media buys now succeeds when Meta omits disabled manual-placement controls from its response. Nothing needs to change on your side.
* Product authoring now presents every publisher coverage option declared by the inventory source, including property tags, without implying that publisher verification is required. This seller-authoring change does not affect buyer-facing storefront rendering.

## 5.86.2 — August 8, 2026 at 3:44 PM UTC

* Pausing Meta media buys now succeeds when Meta omits an optional placement setting from its response. Nothing needs to change on your side.

## 5.85.0 — August 8, 2026 at 1:57 PM UTC

* Enrolled sellers can now open an Inventory Source page to see whether Scope3 builds products from that Source's inventory or the connected Sales Agent supplies finished products. This is operational context only: it does not change how buyers discover, rank, name, or buy the seller's products, and neither option is priced separately. Existing active Sources keep their current behavior and need no action. If an inactive Source says its product setup is unresolved, ask the Sales Agent provider to confirm what it supports; Scope3 support owns the follow-up selection when both approaches are supported. The Source remains inactive until that setup is resolved. Buyer API fields, product labels, and delivery behavior do not change.
* You can now see delivery reporting problems as a diagnosis on your source, alongside the inventory problems that were already there. If a source returns a delivery report we can't accept, the diagnosis names the exact field that failed validation, so you can fix the cause instead of guessing from a generic failure. Selling is unaffected while one of these is open: inventory, pricing, and orders keep working, and only the reporting for that source is incomplete.
* Two new troubleshooting sections cover what to do: [Delivery reports rejected](https://docs.interchange.io/v2/storefront/inventory-sources/troubleshooting#delivery-reports-rejected) and [Delivery reports not returned](https://docs.interchange.io/v2/storefront/inventory-sources/troubleshooting#delivery-reports-not-returned).

## 5.84.2 — August 8, 2026 at 9:24 AM UTC

* Large third-party sales-agent catalog responses no longer stall while diagnostic logging captures a preview of the response.
* Buyer Setup now recognizes active media pricing inherited from your billing
* organization. Missing Organization IU pilot terms no longer appear as a missing
* media rate card, and a confirmed buyer operator no longer needs domain
* verification to go live. Nothing to change on your side. Seller availability,
* authorization, and setup are unchanged.

## 5.84.0 — August 8, 2026 at 8:15 AM UTC

* Seller navigation now keeps the binding Discovery Card alongside Business Rules and inventory setup under Connect. Business Rules also renders policy, disclosure, and approval controls on one consistent card surface.
* Storefront operators using an agent with the gated v3 preview can now get more reliable answers from Interchange documentation. The agent can follow a cited page to the relevant guidance and stop once it has enough evidence, helping it preserve field names and safety steps. Nothing changes in buyer-facing storefront responses, and sellers do not need to update their setup.

## 5.83.2 — August 8, 2026 at 7:01 AM UTC

* The Discovery Card editor now presents its identity and buyer-facing fields together on one clear card surface.

## 5.83.0 — August 8, 2026 at 5:53 AM UTC

* Buyer teams can now use the Calls view in Activity to see whether connected workflows succeeded, how long they took, and what happened when one failed. They can share the details with a technical teammate when they need help. Seller teams get the same view for requests handled by their storefronts. Existing history remains available, and no setup or integration changes are required.
* Anyone using Murph can now choose Google Drive files without enrollment. Buyer teams can also choose Drive files in campaign creative uploads. Each import requests access only to the files selected in Google's window; it does not create persistent Drive access.

## 5.82.2 — August 8, 2026 at 5:27 AM UTC

* Connections now show the full integration grid on page and Settings surfaces instead of clipping the bottom of the list. Sellers can also save Discovery Card descriptions, channels, and accepted countries from the current storefront surface.

## 5.82.0 — August 8, 2026 at 4:06 AM UTC

* Buyers can now compare storefronts by the countries and channels they accept, with Advertising Policies when disclosed by the seller or connected sales agent. For pass-through sellers, each connected source's standard AdCP `primary_channels` and `primary_countries` form one binding, correlated declaration; separate sources are never combined. Sellers manage how they appear in Marketplace from one Discovery Card in Setup. Managed sellers keep Brief Acceptance, Creative Policy, and human approval settings separate; external pass-through sellers continue to use coverage and policies from their own sales agent. Existing V3 `media_kit` integrations remain available as deprecated compatibility surfaces.
* Your generated `adagents.json` files are now ready to copy or download: Murph
* uses valid property IDs and current timestamps, reports exactly what it checked,
* and attaches each file to its Slack reply. No setup change is required. If you
* copied a file from an earlier Murph response, generate it again before publishing.
* Parent organization admins now manage payout destinations for child storefronts. In Plan & Billing → Payouts, select a direct child storefront to create or replace its destination, or use the REST billing API with `targetCustomerId`; child-account admins can no longer change payout routing. Standalone storefront payout management is unchanged, and inventory, reporting, and other storefront operations remain child-scoped. Generic MCP payout operations do not support direct-child targeting.

## 5.81.1 — August 7, 2026 at 10:38 PM UTC

* The "+ Add advertiser" button on the Advertisers overview is temporarily
* unavailable while we finish improving the in-chat add-advertiser flow. To add
* an advertiser in the meantime, use "+ Add advertiser" in the advertiser menu at
* the top of the left sidebar, or just ask Murph to add one.

## 5.80.0 — August 7, 2026 at 9:19 PM UTC

* You can now create an advertiser without leaving the chat. Use the \*\*+ Add
* advertiser\*\* button on your Advertisers view, or ask to add one — then name it,
* look up its brand by domain, and set its primary currency. When you're done, you
* land in the new advertiser's campaigns. Nothing changes for advertisers you've
* already set up.

## 5.79.1 — August 7, 2026 at 7:55 PM UTC

* Opening **Billing** in an advertiser's settings no longer yanks you to the organization billing page and silently switches your active account. Advertisers now see an inline note that billing is handled at the organization level, with an explicit button to open it — the account context only changes when you choose to.

## 5.78.0 — August 7, 2026 at 3:44 PM UTC

* Your agent can now request fresh offers from named sellers against a campaign with `request_proposals`. Each seller's answer is stored as a Proposal: list a campaign's Proposals with `search`, and read one with `get`, including the resolved detail of every product the seller allocated. Accepting one by passing `fromProposalId` to `save_media_buy` stages a draft media buy built exactly from that offer, and records which version of the Proposal was accepted even if the seller later revises it. Evaluation instructions on `request_proposals` are accepted but not yet applied to results, and the staged media buy follows the normal draft flow: nothing is sent to the seller when you accept.
* Property exclusion lists are now enforced when buying: products on excluded properties are filtered out of discovery results, and executing a campaign fails with a clear error if a selected product conflicts with the advertiser's exclusion list.
* Brand logos now stay fresh when a brand replaces the bytes at a stable logo URL. Previously, once a logo was cached, it was served indefinitely. The cache now uses ETag/Last-Modified conditional revalidation: a `304 Not Modified` response keeps the cached copy; a `200` re-downloads and replaces it.

## 5.77.0 — August 7, 2026 at 1:11 PM UTC

* The buyer agent skill now teaches the multi-storefront `get_products` progressive-response contract: poll until `results_complete: true`, replace provisional snapshots instead of appending them, paginate with the cursor only after completion, and read `storefront_results[].message` on successful empty results. Agents built on the skill no longer risk presenting an early partial snapshot as the whole marketplace.

## 5.76.0 — August 7, 2026 at 10:32 AM UTC

* `capabilityHealth.inventory.status` and `capabilityHealth.reporting.status` on `GET /api/v2/storefront/readiness` and `GET /api/v2/storefront/inventory-sources/{sourceId}/diagnostics` keep the same field name and position, but `status` is now nullable: it is `null` when nothing has ever reported on that capability, where it previously read the string `unknown`. The other five fields on each axis change entirely. `lastError`, `lastErrorCode`, `lastErrorAt`, `lastSuccessAt` and `lastCheckedAt` have been removed, because a single set of them could only ever describe one check. The equivalent detail now sits on each entry in `observations`, described below: `lastError` becomes `detail`, `lastErrorCode` becomes `cause`, `lastCheckedAt` becomes `observedAt`, and `lastSuccessAt` becomes `lastOkAt`. There is no direct replacement for `lastErrorAt`; for a check that is not healthy, `observedAt` is when it recorded that result.
* Each axis now also carries `observations`: one entry per health check that reported on that capability, each with its own `status`, plus `observer`, `cause`, and `observedAt`. Several checks can watch the same capability and disagree, for example one confirming the connection is fine while another reports the reporting feed failing. Before, you could only see whichever check happened to run most recently; now you can see all of them.
* `status` itself is more trustworthy for it: it is computed across every check that reported, discounting one that has gone stale, instead of reflecting only the last write. An axis nothing has ever reported on now reads `null`, not healthy.
* If you want one verdict, keep reading `status`: do not build your own collapse from `observations`. If you want to see checks disagree, read `observations`.
* For a managed ad-server source, a failure reported by any check now shows up in that source's health, the same as for every other source type: for example, a creative-sync failure now flips the badge even while the pipeline check itself reports healthy.
* If you look at your storefront's health from the seller-setup widget or the account switcher, nothing changes: the health badge and its wording are the same as before. Only someone reading the raw API response sees these new fields.
* This is a data-model and API-contract correctness change, not a change to pricing, packaging, or your plan.

## 5.75.3 — August 7, 2026 at 5:18 AM UTC

* Sellers approved for the modular inventory source pilot now receive its setup
* and management surfaces directly from their `modular-sources` entitlement. A
* separate rollout flag is no longer required, preventing pilot access from
* drifting between two customer lists.

## 5.75.0 — August 7, 2026 at 12:29 AM UTC

* No action is required unless your organization is invited to the controlled Enterprise Contract pilot. Existing integrations also need no changes: `get_iu_rate_card_offer` and `get_storefront_rate_card_offer` continue to return the same contract details and response structure.
* If invited, an organization administrator can open Settings → Plan & Billing to see purchased product rights, premium support, package history, and current status. Enterprise brand administrators can confirm their organization’s governance, product, and support rights in one place. Agency teams use the same organization record to verify exactly what is included. Power buyers and builders can use `open_iu_plan_task` to open the authenticated view through MCP with standard labels and safe links. Small-business buyers do not need to act; the page remains hidden unless their organization joins the pilot.
* Invited seller administrators see the same purchased rights, premium support, package history, and status for their organization. This gives sellers one authenticated record for confirming what they purchased and whether it is active. It does not change how buyers discover or rank seller storefronts.
* Packages awaiting payment appear as “Payment required” and remain inactive. A billing hold marks a purchased package as “Paused.” Once a prepaid package’s payment is confirmed, using the package will not return it to “Payment required.” A refund or payment reversal changes the package to “Payment required” until funding is restored.
* We will expand the pilot only after Plan & Billing and MCP show the same contract state, private terms remain limited to authorized organization administrators, and failed next actions and support requests stay within the approved pilot limits. Turning off `iu-rate-card-pilot` hides the new views without changing accepted contracts.

## 5.74.2 — August 6, 2026 at 3:02 PM UTC

* The Modular source workspace now opens reliably instead of failing when a redundant access check on its static app shell is temporarily unavailable. Source data and actions remain protected by authenticated customer and tenant authorization checks.

## 5.74.1 — August 6, 2026 at 2:41 PM UTC

* Advertiser property lists now attach to new media buys only when the seller declares property-list targeting support in its capabilities. Sellers that do not support the dimension no longer receive it, which prevents them from rejecting the buy outright.

## 5.74.0 — August 6, 2026 at 1:35 PM UTC

* Accept exact legacy `{agent_url, id}` product-format references indefinitely
* when the shared AdCP catalog can interpret them. Product-format enforcement now
* blocks only unresolved custom references and missing catalog evidence; it no
* longer requires direct canonical `format_options[]` based on source age or a
* September 1 deadline.
* Sellers using shared-catalog references do not need to duplicate canonical
* options on their products. Sellers with custom references must move them into a
* shared interpretable catalog entry or publish an interpretable custom canonical
* declaration before their storefront can transact under the flag.
* Buyers need no setup change. They continue to discover products whose formats
* are interpretable. A storefront with unresolved custom formats returns no
* products to buyers until the seller repairs those formats, preventing buyers
* from selecting inventory that cannot be trafficked.
* Fixed a failure where a live storefront's products could be discovered but not bought. Storefronts that were created before going live carried a stale internal status that two execution steps still checked, so `execute_campaign` rejected the storefront's own products with "Sales agent not found", and creative attachment reported the agent as inactive. Nothing was ever sent to the seller, so no orphaned orders were created. A storefront's availability is now read only from its live pause and readiness state, everywhere in the buying path.
* If your Reddit connection is already marked expired, reconnect it once in Settings → Connections. Active Reddit connections now refresh OAuth credentials automatically before they expire.

## 5.73.0 — August 6, 2026 at 11:39 AM UTC

* The Murph Storefront rail now lets enrolled sellers open every inventory source on its own Source Page, including Scope3-managed adapters and sources still being connected. No migration or buyer-side action is required, and buyer discovery, ranking, labels, and delivery do not change. Switching sources clears the prior source's work, while shared links restore the exact source instead of falling back to another connection. Add and manage sources from Seller Setup, which now presents one collection with Scope3-managed, certified-partner, operator-managed, and advanced modular paths.
* Connections now explains when Scope3 must configure a provider app and disables the unavailable connection action instead of sending buyers into a broken authorization flow. Nothing is wrong with the buyer's provider account, and no buyer action is needed until the provider app is available.

## 5.72.0 — August 6, 2026 at 11:04 AM UTC

* Storefront administrators can now list pending buyer account requests in Buyer Account Mapping through the storefront REST API or MCP, then approve Interchange-cleared billing or reject a request with a reason. Requests stay pending until an administrator decides them; existing grants, source bindings, and billing defaults do not change automatically.

## 5.71.5 — August 6, 2026 at 7:44 AM UTC

* Buyer-facing adapter errors now retain bounded, host-authored diagnostics for malformed audience inventory and TikTok response envelopes. Provider messages, numeric response codes, request identifiers, and account data remain suppressed.
* Connected Pinterest, Spotify, and LinkedIn storefronts now distinguish audiences that exist but are not ready from accounts with no audiences. Non-ready audiences remain visible with a non-live deployment and cannot be mistaken for targetable inventory. Failed adapter reads also retain bounded, allowlisted diagnostics for readiness probes without exposing provider messages or identifiers.

## 5.71.0 — August 5, 2026 at 10:09 PM UTC

* Media buys now carry the advertiser's property list from the moment they are sent to the seller. Previously, a property list only reached media buys that were already active when the list was created - a buy executed after the list existed shipped without it until it was manually attached.
* Creatives produced by generation sessions are now stamped with `creative_source: "generated"` instead of the default `"uploaded"`. All other creation paths are unchanged. The `"connected"` value remains reserved for a future inbound-import path.
* Geo targeting specified as `countries` (instead of the canonical `geo_countries`) now flows through to media buy packages correctly. Previously, campaigns stored with the legacy field name had their geo constraints silently dropped at execute time.
* Products created from ad-server inventory now declare the publisher inventory they cover, so buyers can see whose inventory a product sells. The Inventory Selector task asks for coverage alongside the delivery formats, offering your ad server's own authorized options — typically all properties on a publisher domain, or the specific properties it has verified. One option is prefilled; with several you choose. Previously coverage could only be set when the draft started from a publisher format, so drafting from ad units or placements produced a product the ad server rejected with no way to fix it from the task.
* Because the options come from your ad server, the domain shown is the publisher that authorized you — for a representation network that is the network, not each represented site — and the product declares the properties underneath it. If the task offers nothing, that source has no authorized publisher properties yet, which is a publisher-side step to resolve.
* Validation findings are also grouped now by whether they stop you. Advisory warnings appear under their own heading instead of below "Fix these items before creating", so a recommendation no longer reads as a blocker.
* Normalize TikTok's documented human-readable custom-audience detail types into canonical adapter signal types while continuing to reject unknown provider values.
* Media buys discovered from a linked account now stop background status checks as soon as the source reports them completed or canceled. No action is required.
* Treat TikTok custom-audience list types as advisory and validate the authoritative detail type before projecting signal inventory.

## 5.70.0 — August 5, 2026 at 6:26 PM UTC

* TikTok storefronts now discover custom audiences when the provider returns the `audience_type` list-field variant. Conflicting, malformed, or unsupported audience types still fail closed.
* Open Partner to activate paid operations for unrelated clients. If the **Partner activation pending** banner appears, follow its Plan & Billing action to add a verified card, fund prepay, or resolve a billing hold. In Partner, claim your provider and complete production certification for its current revision. Operations open when your accepted Partner Program contract is in force and every requirement is current.
* Provider registration and production certification remain free while paid operations are pending. Buyers do not get an automatic connection: Partner-only operations and attribution activate only for eligible Partners, while buyer consent and client authorization remain separate requirements.
* Fixed inventory-source test-campaign diagnostics so the run record's seller calls now match the storefront activity log. When a test campaign reached a seller during discovery but then failed at product selection or media-buy dispatch, the run record previously showed no seller calls — making it look like the seller was never contacted. The completed discovery round-trip now appears in the run's diagnostics, so an empty seller-call list reliably means discovery never reached a seller.

## 5.69.0 — August 5, 2026 at 4:15 PM UTC

* Campaigns that have been archived now correctly block new creative operations. Attaching or creating a creative against an archived campaign returns 404 (the campaign is treated as no longer present). Sales-agent sync no longer fires on behalf of archived campaigns. The advertiser creative library no longer counts archived-campaign attachments in each creative's campaign usage count.
* Buyer-facing adapter errors now retain bounded, host-authored diagnostics for malformed audience inventory and TikTok response envelopes. Provider messages, numeric response codes, request identifiers, and account data remain suppressed.
* `customer_get_users` now includes administrators from parent accounts in your organization. Previously those users had access to your account but were not returned in the response.
* No permissions have changed. If your account is part of an organization, you will see additional users in the response. Nothing to update on your end. Sellers are not affected.
* Connected social storefronts now expose real audience lists reliably instead of failing only after an account has inventory. Large lists are paginated, and invalid or cross-account inventory fails visibly. Sellers do not need to take action; buyer agents targeting these audiences should use each result's `signal_agent_segment_id`.
* Creative sync now reports failure when a sales agent accepts a creative but refuses the package assignment that puts it on your media buy, rejects it through its review status, or returns no result for it at all. Previously those synced as succeeded while the creative stayed pending, so a creative that never reached the buy looked live. The reason now travels with the failure, quoted from the sales agent in their own words — including any package they name — instead of a bare sales-agent name.
* Storefront source test campaigns now attach the buyer-facing pricing option returned by their own discovery run, preventing valid account-scoped products from being rejected during selection.
* Buyer Account Mapping imports can now bind uniquely matched sandbox relationships to authenticated inventory-source accounts. If sandbox and live relationships share the same operator and brand domains, the import quarantines the row instead of choosing one.
* Pacing plans now enforce budget limits on live buys. When you write a `pacingPeriods` schedule on a campaign, each active buy's package budget cap is updated to match where you are in the current period - and a background worker advances those caps at each period boundary going forward.
* **What this means in practice:** Budget cap updates go through each seller's standard approval flow. Sellers with auto-approval apply the change near-immediately; sellers with manual review apply it after their team acts. Check your approval queue if you expect delivery to change quickly.
* Previously, pacing schedules were accepted and stored but never applied to buys already running. Existing stored schedules on active campaigns will begin enforcing when the next period boundary is crossed.
* Connected Pinterest, Spotify, and LinkedIn storefronts now distinguish audiences that exist but are not ready from accounts with no audiences. Non-ready audiences remain visible with a non-live deployment and cannot be mistaken for targetable inventory. Failed adapter reads also retain bounded, allowlisted diagnostics for readiness probes without exposing provider messages or identifiers.

## 5.67.0 — August 5, 2026 at 10:37 AM UTC

* Organizations can now review and accept a private Enterprise Offer in Plan &
* Billing. The Offer clearly shows what is included, the contract term and
* renewal rules, and monthly or discounted prepayment choices. Customers can
* download the same proposal as a PDF for internal approval, accept one payment
* choice online, and continue to payment setup.
* Offer administrators start from the standard activity pricing and change or
* waive only the exceptions agreed with the customer. Existing plans, prices,
* and billing terms do not change unless an administrator issues a private Offer
* and the customer accepts it.
* **Persona pass**
* **Enterprise brand buyer:** gets one approval-ready record of scope, term,
* renewal, entitlements, support, and payment choices.
* **Agency / hold-co buyer:** can take the same proposal through approval
* across client stakeholders without reconciling separate documents.
* **Power buyer:** can inspect the exact accepted pricing and product rights in
* Plan & Billing after acceptance.
* **SMB novice:** sees a plain-language proposal and does not need to configure
* anything unless their organization receives one.
* **Seller:** a seller organization can receive the same private Offer for its
* own plan; this does not change how a storefront or its inventory appears to
* buyers.
* **Rollout and measurement**
* This is an atomic GA launch with `gate: none`. Exposure is inherently limited
* to organizations for which an administrator issues a private Offer, and no
* commercial terms change until an organization administrator explicitly
* accepts it. Rolling back the authoring and acceptance surfaces stops new Offers
* without changing immutable terms that customers already accepted; an unaccepted
* Offer can also be revoked.
* We will review Offers issued, proposal PDF downloads, acceptance events,
* monthly-versus-prepayment selection, and payment-setup starts each week. For
* the first ten issued Offers, success means every accepted binding preserves the
* selected payment choice and requires no manual document or billing correction.
* Those first ten Offers establish the conversion and time-to-acceptance baseline
* for the next adoption target.
* Creative delivery to legacy sales agents now translates both canonical format
* identity and package assignments into the seller's supported wire shape. This
* prevents a seller from accepting the media buy but rejecting every creative
* because its required legacy format ID or assignment container was missing.

## 5.66.1 — August 5, 2026 at 8:42 AM UTC

* Meta connections now use Page authorization for Page-native event-source discovery and send schema-valid audience discovery requests, allowing targeting and Instant Form checks to complete reliably.

## 5.66.0 — August 5, 2026 at 8:14 AM UTC

* A proposal pass now shows what fed each product. Expand a product row and you see which of your own ingredients your agent consulted when it built that line — the inventory it selected, the audience it layered on, and the rate-card entries it priced against — plus, under the table, what fed the whole response: the Playbook version it composed under and the terms resolved for that buyer. Tap an inventory, audience, rate-card, or Playbook chip to open the thing that owns it and change it there; a chip with no place to go — buyer terms, or inventory from another seller's storefront — says so instead. Nothing to set up: your agent records this while it composes, so it appears on responses from here on. Passes composed before this simply do not expand, and a chip for something you have since deleted says so rather than sending you to a stand-in. This is included in your existing storefront plan — no new billable surface and no packaging change.

## 5.65.4 — August 5, 2026 at 6:14 AM UTC

* Storefronts that are still completing launch requirements now open Get ready to sell as one focused page, even when the legacy transaction switch was enabled early. Pre-chat widget navigation also removes stale tucked pages instead of restoring them over the active setup task.
* Seller Setup source cards now show a consistent status and explanation across connection, products, and health. No action is needed; pass-through cache gaps and health that has not yet been observed stay out of required setup work.

## 5.65.2 — August 5, 2026 at 5:06 AM UTC

* Third-party sales-agent storefronts now use the inventory source's status as the single lifecycle signal, preventing a stale internal agent copy from blocking readiness, discovery, or seller-owned test campaigns.

## 5.65.1 — August 5, 2026 at 3:47 AM UTC

* OAuth-protected sales agents now use the AdCP client's standard web OAuth flow, including protected-resource discovery for identity providers hosted separately from the agent. When authorization cannot start, the secure credential form shows the actionable reason instead of a generic retry message.

## 5.65.0 — August 5, 2026 at 3:22 AM UTC

* Opening Plan & Billing from Settings now starts parent and standalone organizations on Overview, so buyers and sellers see their plan, next action, usage, and account standing before choosing a billing task. Child storefront payout setup and other task-specific links still open the relevant tab directly.
* For each active third-party sales-agent source created on or after August 4, 2026 at 05:17 UTC, publish a URL-free canonical `format_options[]` declaration on every product. Enrolled storefronts now see source-level legacy and unresolved format details in **Seller Setup > Inventory sources**; sources awaiting current cached evidence remain blocked while a non-serving buyer brief refreshes them. Before September 1, exact legacy mappings from older sources remain temporarily grandmothered while observed non-canonical products from newer sources and unmappable declarations block storefront transactions. On September 1, the grandmothering period ends and every active external sales-agent source must publish direct canonical declarations.
* Buyer impact: buyers do not need to change their requests. While a seller is blocked by this check, buyer discovery returns no products and media-buy admission rejects the storefront; service resumes after the seller publishes canonical declarations and readiness passes.
* Monetization: none. This changes neither pricing, packaging, billable units, nor marketplace economics.
* Measurement: use the named readiness check `source_product_format_compliance` to track the percentage of enrolled active sources that pass, the count of storefronts blocked, and median time from first warning to compliance. Launch acceptance is 100% enforcement for newly created sources with no non-serving refresh failures left unresolved; September 1 acceptance is 100% of enrolled active sources passing direct canonical declarations, with the flag-off kill switch retained for incident response.
* Approving a creative now records your decision instantly and delivers it to your sources in the background. Previously, a slow sales-agent response during an approval could hold the request open long enough to time out — making a saved approval look like it failed, and a retry then surfaced a misleading "no valid routing policy" error. Approvals are now acknowledged the moment they're saved, delivery finishes on its own within seconds, and retrying an already-decided creative reports its real status.
* In the Interchange web app, buttons that open a related tool from inside a panel — for example Import seller feed, or opening campaigns and diagnostics from a widget — were failing with "Couldn't open that workspace. Try again." Those actions work again. Nothing to change on your side.
* Attaching a CSV to set wholesale pricing in Murph now works even when your browser sends the file as plain text — a common case that previously failed with "the attached pricing feed could not be read." And when a referenced file can't be found, Murph now names the attachments it can see instead of a generic error. Nothing to change on your side.

## 5.64.0 — August 5, 2026 at 1:19 AM UTC

* Check your storefront status in Murph for next actions instead of waiting for a storefront nudge. When you ask Murph for status, it lists each setup or source-health step as required or recommended and links to the relevant tool or page when one is available. Complete required steps to make your storefront available, and use recommended steps to improve readiness; if no action appears, nothing needs attention. The separate always-on storefront nudge ladder has been retired, so these next actions are no longer pushed to the in-app feed, email, or Slack. Existing source-health alerts remain separate and continue to follow your notification preferences. This does not change the storefront information buyers see.

## 5.62.0 — August 4, 2026 at 10:58 PM UTC

* If you are an organization administrator and see **Scope3 mapped · unclaimed**
* in Partner, review the provider name and sales agent, then select \*\*Claim this
* operator\*\*. Claiming confirms the mapped identity belongs to your organization
* and preserves its existing agent identity and history. It does not grant Partner
* Program access, certification, client authorization, or commercial activation.

## 5.61.0 — August 4, 2026 at 6:38 PM UTC

* Reporting responses now carry conversion value, CPA, and ROAS alongside the
* existing metrics, at every level — totals, campaign, media buy, package, and
* timeseries — and in the CSV export. CPA is spend divided by conversions; ROAS is
* conversion value divided by spend. Both follow the surface's own spend
* denomination, so buyer figures are computed against gross fee-inclusive spend and
* storefront figures against net spend. These fields populate only for buys whose
* seller reports conversion data; where a seller reports none, conversion value is
* zero and CPA and ROAS are null.
* `reference` creatives stored in the advertiser library can no longer be accidentally assigned to campaigns or synced to sellers. To use a reference creative in a campaign, promote it to `evergreen` via save-to-library first.

## 5.59.0 — August 4, 2026 at 3:00 PM UTC

* The advertiser filter on the Activity page now correctly scopes the Changes feed and the Calls feed. Previously the picker was visible but not forwarded to either data fetch.
* **Behavior change:** `DELETE /campaigns/{campaignId}/creatives/{creativeId}` now detaches the creative from that campaign only — it no longer permanently archives the creative. Existing integrations calling this endpoint will receive the same `204` response, but the creative and its assets remain live in the advertiser library and any other campaigns it belongs to. Active or paused media buys still block the operation. To permanently archive a creative across all campaigns, use the new `DELETE /advertisers/{advertiserId}/creatives/{creativeId}` endpoint.
* If you manage creatives through Murph or the Interchange UI, removing a creative from a campaign keeps it intact in your library and available for reuse.
* For enterprise buyers and agencies: campaign-level removal no longer risks destroying a creative shared across campaigns. Global archive is now a separate, explicit advertiser-scoped action.
* Daily delivery reporting now reports each day separately when a seller returns a reporting window covering more than one day. Previously, if the seller split the days only within each package and reported the media buy as a single whole-window total, all of that delivery was recorded against the window's first day: that day read roughly double its real delivery, and the remaining days of the window read as blank. Each day now carries its own spend, impressions, and other counts, taken from the per-package figures the seller reported for that day. Realized spend on the storefront margin ledger is attributed by day the same way, so the two agree on which day earned what. Re-running a report for a past date repairs any days already affected.

## 5.58.0 — August 4, 2026 at 2:08 PM UTC

* Advertiser brand logos now show in the All Advertisers view instead of falling back to initials.

## 5.57.0 — August 4, 2026 at 1:07 PM UTC

* Organizations that operate a sales agent can now register the provider and agent from Partner before commercial approval. Registration begins the free technical certification path for an exact implementation revision; it does not grant Partner operations access, connect clients, or award certification.

## 5.56.0 — August 4, 2026 at 11:58 AM UTC

* Storefront readiness now checks that live buys have an advertiser to book against. A storefront could previously report itself ready to transact with no advertiser configured — inventory synced, credentials passing, sandbox tests green — while every buy outside the sandbox failed. Sandbox buys skip advertiser routing entirely, so a clean smoke test was never evidence that live buys would work.
* If you sell through several ad servers, this blocks going live only when none of them can route a live buy. When one ad server is missing an advertiser and the others can still transact, readiness names that ad server as a warning and your storefront stays live.
* What the check asks of you depends on your ad server, and it says which on the check itself:
* **Google Ad Manager and AdsWizz** — choose the advertiser yourself. The check reads it back from your ad server rather than a stored copy, so it clears on your next readiness read with nothing else to do.
* **FreeWheel** — the advertiser is real but cannot be set from the storefront yet, so the check asks you to contact us and we map it for you. There is no self-service step to wait for.
* **SpringServe** — no advertiser exists to map, so the check never applies to your storefront.
* Your sandbox test still runs while this check is open: a no-spend test books against your sandbox advertiser, which is a different advertiser that never touches live routing. The separate sandbox advertiser check stays advisory as before.

## 5.55.0 — August 4, 2026 at 11:26 AM UTC

* The Partner page now shows the Scope3 Embedded Sales Agent as a registry-backed reference agent, including its currently deployed production version and current certification status. The reference never exposes deployment digests, evidence, clients, or health data, and Scope3 is not shown as certified until the exact production revision has current evidence for every requirement, including the zero-spend creative canary. No action is required from buyers or storefronts; companies offering an agent to others can use the example to understand the Partner certification path.
* This has the same awareness-only posture for enterprise brand, large-agency, builder, and novice buyers. Seller check: not applicable—the reference does not change storefront ranking, catalog facts, inventory presentation, or anything buyers see about a seller.
* Rollout uses the existing Partner entitlement for private operations and ships the customer-safe reference atomically without a new flag; a registry read failure falls back to the existing explanatory copy, and third-party expansion still requires the current provider registration and certification boundaries. Measure reference-card reads, Partner applications following a read, release-registration freshness, certification currentness, and any private-data exposure (target: zero).
* This adds no billable surface and changes no packaging, price, or entitlement tier. Partner approval remains an enterprise application, while technical certification remains evidence-based and cannot be purchased.

## 5.54.0 — August 4, 2026 at 10:45 AM UTC

* From the organization account selector or Add account, companies that offer a sales agent to other businesses can now open Partner, learn the certification path, and apply to the Partner Program. Buyers and storefront operators that only use another company's agent do not need to act. Opening the page does not grant operational access: buyer identities, source health, incidents, and debugging stay hidden until Scope3 approves the organization's Partner entitlement, while existing entitled operators keep their agent cockpit. No self-service purchase or pricing is added; approval remains an enterprise commercial decision.
* Fix invitation acceptance broken for all customers. Accepting an invitation was failing with a PostgreSQL type mismatch caused by parameter inference in the grant\_lock CTE.
* Fix creative tracking URLs keeping the previous campaign's ID when a creative is assigned to a new campaign. Impression and click tracker URLs are now regenerated against the campaign being assigned, so click and impression attribution reports against the correct campaign instead of the one the creative was originally created under.

## 5.53.0 — August 4, 2026 at 8:43 AM UTC

* Organization admins can now choose **Partner** from **Add account**, and new
* organizations can choose it during signup. If your organization already has
* Partner Program access, Partner opens normally and there is nothing to change.
* If it does not, **Apply** opens a Contact Us path so your organization can
* request approval; it does not create an account before approval. Buyer and
* Storefront accounts, provider health, and pricing are unchanged.

## 5.52.1 — August 4, 2026 at 7:53 AM UTC

* Fixed two copy issues on the demand inbox and proposal pass: the ledger's scoreboard caption led with internal roadmap caveats instead of what the win-rate figure means, and the proposal pass could show two contradicting sentences about whether a brief's condensed facts were captured. Both now lead with the fact the seller needs, with any caveat moved into a Technical details disclosure.

## 5.52.0 — August 4, 2026 at 7:29 AM UTC

* External-agent pass-through storefronts now show the connected sales agent and its endpoint in a billing-first overview instead of presenting an empty seller analytics dashboard. Sellers can open Plan & Billing or confirm a switch to Interchange merchandising from the same surface.
* Organization admins now open their Partner account from the account switcher,
* alongside Buyer and Storefront accounts. Partner operations no longer appear as
* an organization setting, and customer-facing pages use Partner terminology
* instead of “Fleet.”
* Sellers who haven't yet turned on merchandising can now see what it unlocks.
* The Demand, Test runs, Components, Signals, and Merchandising rules rows in
* the storefront navigation show as locked — with a short explanation — instead
* of disappearing entirely. Clicking a locked row opens the same "Get ready to
* sell" setup step used today to turn merchandising on. Storefronts that have
* explicitly chosen to route through their own third-party sales agent are
* unaffected: those rows stay hidden, as they do today.
* The proposal pass now offers the right verb for the exchange it's actually looking at, instead of one "Send" button everywhere. On an exchange your agent already answered, Adjust composes a correction you save as training guidance for your agent — it's labeled honestly, since there's no buyer to notify. On a sandbox or simulator run, there's no send affordance at all: run it again or compare it in the Merchandising Simulator instead.

## 5.51.0 — August 4, 2026 at 5:22 AM UTC

* Before account setup, buyers can check whether requested ISO countries and
* channels are open for a pilot, with domestic and global supply reported
* separately. Failed supply reads are shown as unknown rather than empty, and
* this preview does not change alpha access or enroll an account.
* Interchange now preserves the countries and channels your sales agent advertises
* in `get_adcp_capabilities.media_buy.portfolio`. These primary values are positive
* evidence, while your storefront's separate accepted-country setting is the
* exhaustive brief-routing policy. When connecting a new sales agent, confirm
* either the complete country list you accept or that you accept briefs globally;
* you can clear that choice later to return to an unconfigured scope. Existing
* unconfigured storefronts continue to receive briefs while setup reports the
* missing confirmation. Interchange never infers acceptance from your Media Kit
* or treats an AdCP primary-country list as an exhaustive deny list.

## 5.50.0 — August 4, 2026 at 4:49 AM UTC

* You can now revise a proposal your storefront has already sent, from the demand inbox. Open the proposal, choose Adjust, and set any of three overrides: negotiation posture, price, or a cap on how many products the revision carries. The Merchandising Agent composes a draft revision from what you declared, and you review it before anything leaves your storefront. There is no new setting to turn on.
* A draft is yours alone until you send it. Your buyer sees nothing while it is a draft, and discarding it leaves the proposal they already have untouched. Sending obeys the same media-buy approval setting your storefront uses today. If that setting requires manual review, someone other than the person who drafted the revision approves the send — you can reject or withdraw your own draft, but not approve it.
* Sending does not reach your buyer's agent. There is no delivery channel for a follow-up proposal yet, so a sent revision reads as sent, not delivered. Your buyer is not notified, and their agent sees nothing new — this is a seller-side change only. If your buyer needs to see it, reach them the way you do today.
* This is included in your existing storefront plan behind the `demand-inbox-ledger` pilot flag — no new billable surface, no packaging change.
* Asking Murph to list, show, or browse your advertisers now opens the visual All Advertisers view instead of a plain text list, so you can see campaign and draft counts, brand identity, and pick one to work in right from the same reply.

## 5.48.0 — August 4, 2026 at 1:55 AM UTC

* Registered Partner organization admins can now use the **Partner** account to see
* an overall production certification status for each sales capability, the seven
* checks behind it, and when its evidence expires. The status follows the
* capability's current implementation revision and appears next to the existing
* creative canary. Partner terms, client connection approvals, deployment health,
* marketplace listing, and pricing are unchanged. No action is required unless a
* check is missing, expired, or revoked. Availability remains limited to
* organizations already configured and entitled for agent certification; this
* does not widen Partner access.

## 5.47.0 — August 4, 2026 at 12:11 AM UTC

* Partner sales-agent connections now stay available only while the seller's setup
* is approved, healthy, and ready to serve. If approval is withdrawn, the setup
* stops responding, or the Partner account is paused, the Partner account shows the
* connection as inactive and keeps its previous activation time for audit history.
* **For buyers:** In the Interchange signup form, select every country where you plan to run a pilot. If buyer pilots are not yet available in a selected country, we keep the application for follow-up and use that country-level demand to guide market expansion. This demand signal does not change which Storefronts are shown or how they are ranked.
* **For Storefront prospects:** If you were waiting to open a Storefront, you can complete signup now under Scope3’s standard Terms of Service. Accepting those Terms creates the account’s standard agreement. Organization IU plan selection, signup codes, and pricing previews remain unavailable until the Organization IU Rate Card rollout opens. This release does not publish a Rate Card, enroll your organization in a paid IU plan, enable IU charging, or change current prices.
* Registered Partner organization admins can now retrieve a bounded statement of
* AI usage produced by assisted testing and Partner-authored debugging for their
* explicitly bound client sources. Every line retains the exact capability,
* implementation revision, client, Storefront source, and Partner-safe session
* reference; full-period totals stay complete when detail rows are truncated.
* This first stage is tracked operating evidence, not a charging path. All
* Partner-attributed rows remain platform-bearer and settle zero IUs until a
* separately accepted Effective Rate Card term and entitlement authorize a debit.
* Normal client workloads remain with the client, deterministic checks emit no AI
* usage, and confirmed Scope3 defects carry incident-backed zero-rating provenance.
* Persona check: this is for third-party Partner admins, not the standard seller
* persona. It does not change what a buyer sees about a seller or what a
* Storefront-owning client sees about its provider. Commercial screen: the
* statement exposes no price, accepted term, invoice line, or client charge, and it
* cannot debit either organization's wallet.
* Adoption acceptance starts with at least one registered Partner retrieving a
* statement containing attributed assisted-testing or debugging usage. Measure
* statement request count, distinct Partner organizations, attributed event count,
* zero-rated event count, and truncation rate; the launch target remains zero
* client-bearer Partner events and zero non-zero IU settlements.
* Roll back by disabling the Partner AI usage statement and producer seam, then
* reversing the attribution migration. Monitor attribution conflicts, unexpected
* non-platform bearers, zero-rating guard rejections, statement truncation/latency,
* and cross-tenant privacy-test failures.

## 5.46.0 — August 3, 2026 at 10:35 PM UTC

* Registered Partner organization admins can now retrieve a bounded support-effort
* statement attributed to the exact capabilities and client inventory sources they
* operate. The statement separates included support, overage candidates, and
* incident-response effort zero-rated because of a confirmed Scope3 platform
* defect. Full-period totals remain complete when detailed lines are truncated.
* The ledger is append-only and derives every Partner, client, capability,
* Storefront, and source identity from the explicit provider binding. Zero-rating
* requires an authoritative Scope3-owned provider incident affecting that binding.
* Only Partner-safe descriptions and references are returned; credentials, raw
* incident details, internal notes, and unrelated clients remain private.
* Persona check: this is an operating statement for third-party Partner admins and
* the Scope3 staff who record support evidence, not the standard seller persona.
* It does not change what a buyer sees about a seller or what a Storefront-owning
* client sees about its provider. Buyer campaign users do not see it. Commercial
* screen: `OVERAGE_CANDIDATE` is reconciliation evidence only—not a price, invoice
* line, accepted term, or client charge—and deterministic reads spend zero IUs.
* Roll back by disabling the statement and recording routes, then reversing the
* support-effort migration. Monitor recording conflicts, zero-rating guard
* rejections, statement latency/truncation, and cross-tenant privacy-test failures.

## 5.45.0 — August 3, 2026 at 9:54 PM UTC

* Seller administrators with a future-dated Enterprise package can keep operating
* their existing inventory sources, while adding a new modular inventory source stays
* unavailable until the accepted contract term begins. The setup unlocks from that
* same contract automatically when its effective date arrives.
* Existing sources, readiness, diagnostics, and bookings are unchanged. Buyer
* administrators and customers without a negotiated Enterprise package have no
* workflow change, and no action is required.
* In the Storefront API, a seller account admin can now invite the certified
* Partner already connected to one inventory source to inspect that source's safe
* diagnostics. The admin selects the exact provider binding UID, chooses an expiry
* of up to seven days, and can revoke the invitation immediately. A Partner admin
* uses the Partner API routes to list live invitations and open the permitted
* source diagnostics.
* Access covers read-only, redacted source health. It never exposes credentials or
* other clients, and it does not grant source changes, test execution, client
* account membership, or shared-room access. Every read rechecks the live source
* connection, Partner status, production certification, expiry, and revocation.
* Persona check: the seller admin grants access and the third-party Partner admin
* uses it. Buyer campaign users do not see this surface, and this seller-side
* change does not alter anything a buyer sees about a seller. Commercial screen:
* delegated diagnostics is an operating benefit of the existing paid Partner
* relationship, not a new SKU or paid add-on; deterministic reads spend zero IUs
* and never charge the client.
* Roll back by disabling the four provider debug-grant routes, then reversing the
* new migration. Monitor grant creation/revocation counts, denied or expired reads,
* diagnostics latency, and any cross-tenant privacy-test failure.

## 5.44.0 — August 3, 2026 at 9:06 PM UTC

* Your advertisers now open on a single landing view — every advertiser you work with in one place, each showing its brand, how many campaigns it has, and a one-tap way to jump back into an advertiser you left mid-setup. It's the starting point for choosing which advertiser to work in, and it loads in one step instead of stitching the list together as you go. Per-advertiser spend totals aren't shown on this view yet — that's coming.
* Enterprise customers with a negotiated package can now see exactly what their
* subscription includes in Plan & Billing and the IU-plan task. Packages can include
* Partner Program participation, agent certification, SSO setup, publisher
* self-serve, modular inventory sources, and either unlimited named support or a
* monthly support allowance with an IU rate for additional hours.
* Included features become available when the Enterprise offer is accepted and
* remain tied to its contract term. Existing Enterprise access continues through
* this upgrade. No customer action is required, and customers without a negotiated
* Enterprise package are unaffected. This does not change seller storefronts or
* seller workflows.
* Unassigning a creative from a campaign now safely reconciles downstream state. Media buys in DRAFT or PENDING\_APPROVAL are updated to remove the creative. Attempting to unassign while the creative is on an ACTIVE or PAUSED buy returns a validation error. The join row is now soft-deleted (status: INACTIVE) rather than hard-deleted, preserving audit history.
* `PUT /api/v2/buyer/campaigns/:id` now returns a fully hydrated `mediaBuyRefs` array in the response, matching what `GET` returns. Previously the field was always empty, causing AI callers to incorrectly infer that media buys had been removed.
* Three fixes to the flighted pacing contract:
* Setting `pacingPeriods` where every period has already ended now returns a validation error instead of silently accepting an inert schedule.
* The `update_campaign` response now includes a `pacingApplicationNote` field when you write `pacingPeriods`, telling you how many DRAFT buys will use the schedule on the next `execute_campaign` call and that live buys are unaffected.
* DRAFT media buys with `start_time: "asap"` that have never been dispatched to a seller can now have their `start_time` updated to a specific future date. Previously this was blocked by a validation error even on never-forwarded buys, which made per-buy `pacingPeriods` (which requires a concrete window) impossible to configure on the normal `asap` default.
* Provider-organization operators now receive always-on open and recovery
* notifications for provider-attributed incidents. Each notification links
* to the Partner account and includes the capability, safe classification, confidence,
* detection time, and aggregate affected-client count without exposing client
* identities, connection IDs, credentials, or raw errors.
* This extends the existing Partner workspace and adds no billable surface or paid
* tier gate. Buyer interfaces and buyer notifications are unchanged; each affected
* publisher continues to receive only its own tenant-scoped source-health status.
* Seller-persona check: new provider-wide status is not applicable to an affected
* publisher because it could reveal other clients; that publisher sees only its
* own source state and next action.
* The routing ships with the existing provider-organization admin cohort because
* it closes an operational alerting gap without changing serving, quarantine,
* support, or billing decisions. Rollback disables the worker delivery call while
* the append-only incident evidence remains inert. Measure delivered open/recovery
* edges, delivery errors, acknowledgement time, and incident recovery time before
* adding delegated diagnostics or support metering.

## 5.43.0 — August 3, 2026 at 7:08 PM UTC

* Fixed a case where sellers who declared "the Scope3 Prebid module is active on this product" on an ESA-hosted product were not seeing that declaration take effect at ad-serve time — the package-ID key-value that gates the resulting ad-server line item on Prebid-enriched traffic was silently being skipped for these products. New forwards on affected products now correctly carry that targeting. Existing forwarded buys are not backfilled by this change.
* The Partner account now shows a connection as inactive when client approval has
* been withdrawn, or renewed but validation has not finished. The previous
* activation time remains available as history. No action is needed: the status
* returns to active after the client approves the connection and validation
* completes. This corrects status display only; it does not change billing,
* packaging, access, or what buyers see.
* Provider operators can now see grouped active incidents in the Partner account,
* including safe attribution, confidence, detection time, and affected client and
* connection counts. Persistent source failures are grouped by client, endpoint,
* implementation revision, or provider capability and recover without exposing
* client credentials or unrelated inventory.
* This is included in the existing Partner workspace and does not add a billable
* surface or paid tier gate. Deterministic provider health remains zero-rated. Buyer
* interfaces are not changed and buyers do not receive incident-derived signals
* about a provider or another client.
* The read-only projection ships to the existing provider-organization admin
* cohort without a feature flag because it does not change serving, quarantine,
* support routing, or billing decisions; rollback is an application rollback and
* the append-only evidence remains inert. Adoption is measured through Partner →
* Partner-account route usage. Incident events measure detection and recovery time, affected
* clients, and classification mix before notification or delegated-debugging
* behavior expands in a later release.
* A buyer requesting preview access with a work email from an organization Scope3 already knows will now see its company name pre-filled. This saves re-entry without granting account access or changing who can join.
* Seller impact: not applicable. This changes buyer signup and the internal TARS admission workflow only; sellers do not see a new or changed surface.
* Buyer persona: first-time and SMB preview requesters benefit from the plain-language company prefill; no opt-in mechanics are exposed to them.
* Monetization: none. This does not change pricing, packaging, billable surfaces, or commercial differentiation.
* Rollout: the advisory signup prefill is intentionally ungated because it has a one-second database deadline and falls back to the existing signup flow without changing access. Its kill switch is reverting the signup resolver. Account admission remains Scope3-SuperAdmin-only, and only the admitted customer is enrolled in `alpha-opt-in`; the global flag stays off. Expansion requires reviewed admission receipts without unresolved delivery/errors and a separate market/channel governance decision.
* Measurement: `auth:signup_flow_start` records `canonical_org_ref`; adoption is the share of eligible preview requests with that property populated. Operational acceptance is an `applied` or explicitly warned admission receipt with verified customer-scoped enrollment, one confirmed Account edge, and an active administrator or ADMIN invitation.

## 5.42.0 — August 3, 2026 at 3:41 PM UTC

* Fix execute\_inventory\_source\_test\_campaign returning 0 products when the storefront is in a pre-launch (paused) state. Sellers can now run end-to-end inventory tests against their storefront before it goes live on the marketplace.
* Provider organizations can now open the Partner account to see their capabilities,
* explicitly connected client sources, connection status, and safe health
* diagnostics. Partner registration and paid commercial status remain separate
* from private provider ownership.
* Optimization suggestions no longer ask for your approval when there is nothing to approve. A suggestion that carries no budget or bid change — most often for a media buy with no optimization goal, where the suggestion is pacing information only — is now recorded and closed out instead of landing in your queue, as is a suggestion whose campaign or media buy is no longer active by the time it reaches you. Suggestions that propose a budget or bid change on an active campaign and media buy are unaffected, and nothing changes on your side.

## 5.41.0 — August 3, 2026 at 1:44 PM UTC

* A handful of small honesty and clarity fixes across your Ask Murph workspace.
* The "Per-buyer auto-approve" rail item and its widget now say the same thing —
* the rail used to read "Buyer trust" while the page it opened read "Per-buyer
* auto-approve." The "Sales agent" rail item and its page now match too, and the
* page's "Evidence" tab is now labeled "Calls." Connecting a sales agent now
* speaks your language instead of ours: "Connect a sales agent your partner
* runs — paste the address they gave you" replaces "Register an external ADCP
* sales agent by its endpoint," the address field is now called "Agent address"
* with a plain-language hint, and the technical MCP/A2A protocol choice now has
* a note telling you to just ask your partner if you're not sure. Pending
* operations no longer shows a false "nothing is waiting on anyone" when we
* can't read the underlying data — it now shows the honest retry state instead.
* Its "Review escalation" button, which never actually escalated anything, now
* reads "Open timeline" — exactly what it opens. The demand inbox's buyer filter
* now says "Buyer (loaded 100)" directly on the control, so it's honest about
* its own scope no matter which buyer you have selected, instead of a footnote
* you could miss.
* On the v3 preview surface — flagged off today, with no accounts enrolled — every task waiting on you reads through one `work_item` search. Alongside creative reviews and media-buy approvals, `search({ "kind": "work_item" })` and `get` now cover **modular source follow-ups**: the source-side tasks a modular inventory source raises for itself, such as confirming avails or resolving a trafficking error. Each one tells you the `requiredResultFields` it needs, and `save_work_item` completes it with them. Complete the same follow-up twice and you get `"action": "unchanged"` with nothing written; a conflicting correction is refused with the original record and its evidence intact.
* Approved is still not the same as delivered, and the response now tells you which one you have. Completing a follow-up applies its side effects as part of completing it, so `COMPLETED` is proof the effect landed. An approved media buy with a `forwardedAt` timestamp was sent — not a guarantee every downstream leg accepted it. One with no timestamp was never forwarded at all; that is reconciliation work, and the response points you to the approvals page to retry the forward.
* The two status vocabularies stay separate on purpose: a follow-up has no `approved` state and a creative review has no `COMPLETED` one. Ask for a status one queue cannot have and the response names the queue it did not search, rather than returning nothing and letting that read as "nothing is waiting". Follow-ups are held per inventory source, so a storefront-wide read fans out across your modular sources and reports how many of them it reached. Two limits are reported separately: sources the scan did not reach, and sources whose own read window filled up. A single queue reads up to 100 follow-ups at a time, and one that comes back full is named in the coverage as an exhausted window — a floor, not a total, which `filter.status` can narrow. Neither limit is ever reported as an empty queue. To read one queue on its own, pass a `sourceId` together with `filter.workItemKind: "modular_source"` — a `sourceId` alone is refused, because the approval queues are storefront-wide and would silently ignore it.
* Getting an advisory AI evaluation, reassigning an approval to someone else, and retrying a forward stay on the approvals page rather than becoming fields on `save_work_item`. The first two cost money per call or move who is accountable for a decision, and a retry re-sends the buy to your ad server — none of them is a state you can declare, and re-recording a decision will never trigger one.
* This is a flag-only preview rollout. Monetization: none. It adds no package, differentiation, price, billing, entitlement, usage meter, or metering change. Disabling `v3-agent-surface` removes this v3 reachability but does not undo durable decisions, completed follow-ups, or their module side effects; corrections remain separate follow-up or reconciliation records. The v2 completion response's additive `changed` field is backward-compatible, and no data repair is required.
* Preview measurement uses the existing redacted MCP action ledger. At each cohort review, count modular-source `work_item` searches and gets plus `save_work_item` completions, split by success, unchanged retry, conflicting correction, unreachable source, and exhausted source window. Expand only after every enabled modular-source test storefront has completed one follow-up successfully, repeated that completion with an unchanged result, and read the completed result back. Pause expansion if any completion is recorded without its module side effect, a conflicting correction overwrites the authoritative record, or an incomplete source scan is presented as an empty queue.
* Nothing else on `/mcp/v2` changes.

## 5.40.0 — August 3, 2026 at 12:01 PM UTC

* Business Rules can now tell a storefront admin which human reviews each approval kind. On the `/mcp/v3` agent surface, `get` with `include: ["approvalRouting"]` returns the primary and fallback approvers by name, their roles, the channels they're notified on, and the reminder and escalation clock for media buys and creative review, alongside the acceptance policy and approval gates you could already read. Approver email addresses are deliberately not returned to the agent. Reading routing requires an admin; a non-admin session gets an explanation of why, never an empty table. Changing routing stays on the Approvals Page, where a human picks who can act, and no approval gate changed behavior. Separately, the seller documentation was wrong about rolling an acceptance policy back and now describes both routes: saving the earlier content again mints a new version, while the Business Rules Page reactivates an existing version and mints nothing.
* Monetization: none. This read remains part of the existing `v3-agent-surface` preview and adds no package, entitlement, differentiation, price, usage meter, or billing change.
* Preview measurement uses the existing redacted MCP action ledger. During each cohort review, count `get` calls with `kind: "business_rules"` and `include: ["approvalRouting"]`, split into successful reads, admin denials, and unavailable upstream reads, without retaining approver details. Expand only after every enabled test storefront has completed at least one successful read and no unavailable read has been presented as an empty routing table. Pause expansion immediately on any email-address exposure or any routing mutation outside the Approvals Page.
* Creatives with publisher-scoped format assignments (`format_option_ref: { scope: "publisher", publisher_domain: "facebook.com", format_option_id: "..." }`) now sync to Meta, Snap, and Pinterest storefronts correctly. No change to your integration is required if you were already setting this field — it was accepted but silently dropped before; it now flows through. If you were not setting it, nothing changes. Sellers will see these creatives flowing to their publisher placements where they previously did not.
* This ships ungated. No kill-switch is needed: the previous behavior was a silent drop (not a deliberate gate), and this restores the intended end-to-end flow. Adoption will be measured by `sync_creatives` success rates on publisher-scoped storefronts (Meta/Snap/Pinterest). Full AAO registry validation (confirming the format\_option\_id exists on the publisher's catalog) is a follow-up tracked in AI-5171.
* Testing your storefront now tells you the truth in your own language. A test
* buy that was still waiting on a few details from you — a budget, flight dates,
* an advertiser, a test brief — showed up with a red "Failed" chip and a raw run
* ID for a title, even though nothing had actually run yet. It now shows a
* distinct "Needs details" status and names exactly what's missing (Budget,
* Flight dates, Advertiser, Test brief), and the title reads as "Test buy against
* your storefront" instead of an internal ID. Each step in a test now reads as
* what it proved ("Storefront reachable", "Sandbox advertiser ready") instead of
* an internal tool name; the exact endpoint and HTTP status behind each step
* moved into one "Technical details" disclosure. Internal notes about what our
* test tool doesn't support yet no longer show up on your test results at all.
* Public seller signup is now fail-closed behind the existing IU Rate Card pilot flag. The storefront option and public pricing preview stay hidden until that flag is rolled out globally, while the complete IU signup experience remains available for launch.
* New AdsWizz connections now pin a versioned API-key contract with fixed Domain and Forecasting endpoints, so setup and credential rotation reject incompatible configuration before it reaches the ad server. Existing AdsWizz connections continue to work without changes.
* New SpringServe connections now pin a versioned authentication contract for email/password exchange or API-token access, so setup and credential rotation reject incompatible configuration before it reaches the ad server. Existing SpringServe connections continue to work without changes.
* Media buys, Pending operations, and ad-server connection warnings now read in
* plain language instead of internal codes and ids. A stuck buy's reason and
* error now show as a sentence ("The source couldn't be reached — the platform
* is retrying") with the underlying code kept as a reference line, not the
* headline. A row without a resolved buyer name leads with an honest "Media
* buy" or "New buy awaiting review" instead of the bare `mb_…`/`cr_…` id. A
* failed-forward group's recovery class ("transient", "structural") is now a
* sentence too. An unreachable ad-server source now names the source ("Your
* ad-server source Google Ad Manager couldn't be reached...") instead of "ESA
* connection 42", and a widget or task that fails to open now says so in plain
* language ("This view didn't load — try again.") instead of "MCP app failed
* to load."
* Setup now tells you the truth about where you actually are. Clicking around
* the rail while your storefront setup checklist was open no longer scolds you
* to "finish or cancel it before it gets buried" — that warning only fires when
* you've actually left something unsaved elsewhere; opening a checklist you
* haven't touched yet never triggers it. The go-live progress band on a
* brand-new storefront now reads "N to do" instead of "N blocked" — a required
* step you haven't started yet isn't the same as one you tried and got stuck
* on, and the band now agrees with what each step's own card already says
* ("Not started"). And the "Your storefront is live" banner no longer shows up
* by accident: if we don't have a clear signal your storefront is actually
* live, we say so instead of guessing green.
* Sellers can now declare, per product, that a product's inventory has the Scope3 Prebid module installed — ask Murph "turn on the Scope3 Prebid module for product X" and Murph flips the flag through the wholesale-authoring API. Read + write in the same tool: ask "is the module active on product X?" for a read-only check. When on, Scope3 stamps a package-ID key-value on the resulting ad-server line item at forward time; when off, Scope3 skips the stamp. Only ESA-hosted wholesale products are managed through this tool — third-party sales-agent products stay under your own agent's `get_products` response.
* On the early-access `/mcp/v3` surface — not switched on for any seller yet — your Playbook now owns your brand and operator house discounts, and you can pull up any earlier version of your selling guidance in full.
* Setting a discount is part of saving your Playbook, alongside your guidance and your pricing. It works one rule at a time, not as a list you replace: a discount you don't mention stays exactly as it was. To remove one, name the buyer's domain and whether it is the brand discount or the operator discount, since a domain can carry both and they are different rules. If you set several at once and one fails, we tell you which one and keep the rest.
* You can also read your discounts back — on their own, or beside your pricing when you read the Playbook — and ask what a specific buyer's domain would resolve to. That preview shows the corporate chain the domain rolls up (`converse.com` → `nike.com`) and the nearest rule on each side. **It is not the price a buyer gets.** A real buy resolves the buyer's brand and their agency separately and applies whichever discount is larger, so treat the preview as "where would a rule for this domain land", not "what will they pay".
* Every Playbook save still creates a new version and makes it live in the same call — there is no separate step that reactivates an old one, which is why rolling back means saving the old content again. You can now read one past version in full to do that, and it tells you up front whether it would still be accepted: guidance written before we split pricing, discounts, markets, and acceptance rules into their own surfaces gets rejected if you save it back unchanged, and you find that out before the save rather than from the error.
* Nothing on `/mcp/v2` changes.
* Monetization: none. This remains part of the existing `v3-agent-surface` preview and adds no package, entitlement, differentiation, price, usage meter, or billing change.
* Preview measurement uses the existing redacted MCP action ledger. At each cohort review, count house-discount searches, Playbook reads that request discounts or one historical version, and Playbook saves that set or remove discount rules, split by success, unchanged, refusal for incomplete evidence, and partial application. Expand only after every enabled configured test storefront has completed one successful relevant read and every attempted discount write has a confirming read that agrees with the reported outcome. Pause expansion if a response presents a hierarchy preview as the buyer's effective price, reports an incomplete list as complete, or omits a rule that was already applied from a partial-failure result.
* Ask your storefront agent to retire a wholesale product and it now covers both endings: archive and delete. Archiving takes the product off the market. Buyers stop seeing it, its name, inventory selection, and prices stay as you left them, and making it `active` again brings the same product back under the same id. Deleting removes the product from the source permanently. Because that cannot be walked back, your agent confirms the product's exact stored name before it removes anything, and it refuses to delete one that is still `active`, since buyers can discover and buy it right now — archive it first. Deleting an id that is not there is reported as unchanged, not as a deletion. Deleting never touches your ad-server inventory: the ad units, placements, and targeting you packaged stay where they are, and selling that inventory again means authoring a new product, which gets a new id rather than the one you deleted. Creating and editing products behave as they did before.

## 5.39.0 — August 3, 2026 at 10:09 AM UTC

* On the v3 agent surface (still a preview), `save_coverage` can now add or remove one publisher domain, and claim or retract one property under a domain, without restating your whole domain set.
* Single-domain edits used to work by rebuilding that whole set from a fresh read and writing it back. That could lose an edit someone else made while the read was in flight, and it could delete domains the read did not return — so when a read came back incomplete, `save_coverage` refused the edit outright rather than risk it. Neither applies now: one edit is one declaration, so a single add or remove goes through however much of your roster the read covered. Removing a domain we discovered on your site rather than one you declared now comes back as a conflict, instead of reporting a success that removed nothing.
* Property claims are new here, and they stay at property grain. A claim needs a property id, an identifier, or a name — we never invent property identity. When the publisher's own `adagents.json` declares the same property, the publisher's record is what takes effect and your claim is kept on it, so it returns if the publisher later stops declaring that property. A property that came from the publisher cannot be retracted this way. Retracting a claim that is already gone is a success with nothing changed, not an error, so a retried retraction converges instead of alternating.
* Declaring the complete set still replaces the set, and it now tells you when its own report is partial. The write always applies your full declaration — the set is yours to declare. But we compute what was added and removed by comparing against the domains we could read first, so when that read is bounded the response says `removalReportComplete: false`, tells you how many of your domains it could see, and warns that more may have been deleted than it listed. When the read is complete the lists are exact, as before. Only domains you declared are ever reported as removed: one we discovered for you follows its own source and survives, whether you ask to remove it directly or leave it out of a full declaration.
* Two details for anyone reading the response programmatically. Every outcome list is now `{ items, count, truncated }` — a replace can touch thousands of domains, so the list carries at most 50 while `count` stays the real number; read `count`, not the length of `items`. And a read that trimmed a domain's *properties* no longer counts as an incomplete *domain* list, so a declaration matching your domains is still reported as changing nothing even on a publisher with thousands of properties.
* The v3 preview guide now covers reading and editing coverage, and the v2 publisher-domains guide documents the single-domain add and remove routes and when to prefer them over replacing the whole set.
* The v3 lifecycle remains inside the existing `v3-agent-surface` preview and does not expand enrollment. Availability, entitlements, pricing, paid-add-on composition, and packaging do not change; rollback is disabling the preview flag or reverting the surface commit, with no data or billing migration to unwind.
* Your seller dashboard and Signals now offer a real "Try again" when they can't load, instead of a dead-end message with no recovery but closing and reopening the page. The error also shrinks to fit its own message instead of leaving a tall empty space beneath it.
* A bookmarked or shared demand-inbox link now opens the same view as the rail: every entry path opens the newer ledger where it's on, instead of the older read-only history.
* Seller Setup source cards can now open their existing specialist detail and diagnostics surfaces directly.
* New FreeWheel connections now pin a versioned authentication contract, including sandbox setup, so setup and credential rotation reject incompatible configuration before it can reach the ad server. Existing FreeWheel connections continue to work without changes.
* Storefront avails feeds now reject rows with impossible dates, unsupported
* currency codes, booked capacity above total capacity, or CPM values likely
* entered in the wrong unit. Expired rows stop appearing as sellable inventory,
* so buyers see only current, valid availability. Existing valid rows are
* unchanged. No action is needed unless a feed relies on data that was previously
* accepted despite one of these errors; rejected rows include diagnostics to guide
* correction.
* Replacing your publisher-domain set no longer discards what was already resolved for the domains you kept. `PUT /api/v2/storefront/publishers` and the MCP `replace_publisher_domains` operation now apply as a diff: a domain that is in both your current set and the one you send keeps its resolved properties, collections and creative formats, your own seller-declared property claims, its authorization verdict and reason, and its sync timestamps. Only the declared domains you left out are deleted, and only domains that were not there before are created — those start at `pending` because nothing has resolved them yet.
* Previously those two surfaces rebuilt the whole declared set, so resending a set you already had cleared the resolved data on every one of those domains and reset them to `pending`, discarding their authorization verdicts until the next sync re-resolved them. Echoing your own list back is an ordinary thing for a client or an agent to do, so this was easy to hit and slow to notice: the domains reappeared immediately and only their resolved detail was missing.
* Updating `businessProfile.publisherDomains` is a separate path and is unchanged. It already preserved the rows for domains that stayed in the set. Note that its deletion semantics differ from the two surfaces above: it removes every domain absent from the set you send, including ones we discovered or crawled for you, where `PUT /publishers` only removes domains you declared yourself.
* Nothing to change on your side. If a recent replacement left domains showing as `pending` or without properties, the background sync will have re-resolved them; re-read the property roster to confirm.
* Availability, entitlements, pricing, and packaging do not change. This preservation fix ships ungated because it prevents an ordinary replacement request from silently discarding already-resolved seller data; rollback is a code revert, with no schema, entitlement, or billing migration to unwind.
* No seller integration changes are required. Creative delivery now adapts canonical manifests against each seller's exact declared format option before the SDK translates them for legacy sellers, preventing stale labels or guessed seller URLs from selecting the wrong format. Existing buys created before exact seller options were persisted continue sending their concrete canonical payload as before; they are never assigned a guessed legacy ref. Historical creatives that store only an ownerless format ID must be re-uploaded instead of being attributed to whichever seller is selected.

## 5.38.0 — August 3, 2026 at 8:47 AM UTC

* On the `/mcp/v3` preview, a seller agent can now read the media buys on its own storefront. `search({ kind: "media_buy" })` lists every buy that landed there — the buys routed through your storefront and the buys your ad server manages upstream alike — with filters for one inventory source, one buyer, a seller-side status (`sellerStatus`), or a flight-start window. `get({ kind: "media_buy", id })` returns that buy's timeline as your storefront saw it: the approval it went through, the stages it reached, and one entry per inventory source it was sent to, with the source's own reference, the Scope3 reference to quote alongside it, and a summary of what was sent (flight, budget, packages, targeting dimensions). Every stage names its most recent failure with an error code and whether a retry can succeed, so a stalled buy explains itself without a second call.
* The reads say where they stop. A list built while a source was unreachable says so instead of reading as complete, and stale statuses say how stale. Raw request and response payloads are not returned; the timeline already carries the answer they would be read for. A buy that never touched your storefront comes back as not found, not as a partial answer.
* There is no seller-side test-campaign tool, and there will not be one. Testing your storefront means switching to a buyer account and buying from yourself. That path is still being built, so keep using the v2 test-campaign endpoints until it lands.
* `/mcp/v3` stays behind a feature flag with nobody enrolled, and nothing on `/mcp/v2` changes. The v3 Agent Surface (preview) page in the docs carries the full shape.
* Availability, entitlements, pricing, paid-add-on composition, and packaging do not change. These are read-only diagnostics inside the existing preview, not a new billable action; rollback is disabling the preview flag or reverting the surface commit, with no data or billing migration to unwind.

## 5.37.0 — August 3, 2026 at 6:56 AM UTC

* If you have asked Murph to switch your storefront's composition mode, check your capability flags: creative review and campaign approval may have been switched off at the same time. Switching composition mode no longer touches your other flags, but earlier resets were not restored, so ask Murph to show your storefront's capabilities and turn back on whatever you still want to advertise to buyers. Storefronts running on a storefront adapter are the ones to check first, because there your declaration is exactly what buyers see. Elsewhere the reset reached buyers only while composition mode was on; with it off the reset was invisible at the time, and it comes back as off the next time you turn composition on. Storefronts backed by a connected ad server were never affected. The switch was rejected outright for them, so nothing was ever stored.
* One new refusal comes with the fix. Now that a creative review declaration survives the switch, turning composition on can be refused when your storefront advertises creative review and nobody is left to approve that queue: no active approver in your approval routing, and no organization admin to fall back on if you never set routing up. With composition off that promise was suppressed; with composition on buyers can submit creatives, so we refuse the write rather than open a queue nobody owns. Nothing is saved when that happens, and the refusal names both ways forward: name an approver for creative review, or turn creative review off before you switch.
* When you check your flags, expect two values that can legitimately disagree: the ones you declared, and the effective set buyers get after your ad-server setup, your composition mode, and your media-buy approval setting are applied. A save can succeed without changing anything buyers see, so read the effective set back after a write rather than trusting the flags you sent.
* Availability, billing, and packaging do not change. Composition mode remains the same paid add-on with the same eligibility and price; this release corrects how its capability change is stored and refused. The safety fix ships to the existing seller surfaces so it stops further flag resets immediately, while the v3 agent surface remains limited to its current preview cohort.
* For API and MCP integrations, the existing write distinction is unchanged: `PATCH /api/v2/storefront` keeps the capability flags you leave out, while `PUT /api/v2/storefront` stores every flag you omit as off. Continue using the partial patch when you mean to change only selected flags, and read the effective capability set after the write.
* Archiving a storefront signal now says what else it archives, updating one explains which fields are silently ignored, and the signal reference matches what the API accepts.
* Testing your storefront now tells you the truth about what happened. Before, a
* test brief that failed before your agent could answer — rejected credentials, an
* unavailable inventory source or service, an internal error — was reported the
* same way as a genuine "no products matched", so you could go rebuilding
* inventory that was never the problem. A run that couldn't finish now says so
* plainly and offers a retry, and a run that finished with nothing to offer says
* that your agent answered and nothing in your storefront matched this brief. The
* test also states up front, while it runs, and again in its result that it creates
* no media buy and commits no inventory.
* Your demand inbox also leads with the answer you came for. Brief history sits at
* the top, so "has my agent been answering demand?" is the first thing you see, the
* list stays a fixed height instead of stretching down the page, and its totals now
* describe the same set of briefs. A brief your agent declined reads as a normal
* outcome rather than an error — choosing not to bid is your acceptance policy
* working — and red is reserved for a brief your agent could not answer at all. The
* two load-error messages that were nearly invisible are now legible in both light
* and dark mode, a failed decision lookup says your brief history is unaffected,
* and if a background refresh doesn't complete the screen says your history may be
* out of date and offers Refresh in place instead of quietly showing you stale
* rows. When you have no briefs yet, the screen coaches you to run a starter brief
* rather than showing an empty table. Any row opens from the buyer name, so
* keyboard and screen-reader users get one clear control per row. Dates, prices,
* and counts follow your account's language and time zone, and the whole screen is
* available in Portuguese and Japanese.
* Buyer product discovery and creative workflows now use canonical format declarations instead of guessing from legacy IDs. Products and delivery for legacy external sales agents remain supported through exact SDK compatibility boundaries, while internal CreativeMaster identity requires canonical format evidence.

## 5.36.0 — August 3, 2026 at 5:45 AM UTC

* From **Refer a company** in the account menu, signed-in buyer and seller
* organizations can introduce another company and follow its review status. The
* page shows the current offer: 100 Intelligence Units, valid for 60 days and
* usable for IU-rated Interchange activity, after
* the company starts a paid plan or a referred buyer reaches \$10,000 in agentic
* media spend. Scope3 handles outreach and eligibility review; there is nothing
* to enable, and submitting a referral does not itself earn the reward.
* Prospective buyers can now share their target markets, channels, pilot plans, and self-service experience when joining the preview, so suitable pilots can move to solutions review sooner.

## 5.34.1 — August 2, 2026 at 7:56 PM UTC

* Media-buy reads now preserve the canonical delivery-format requirements of newly composed products. Read `formatOptions` for their `format_kind` and `params`; older composed buys keep their exact legacy format readback until those product rows are refreshed.

## 5.34.0 — August 2, 2026 at 5:26 PM UTC

* The Connect sales agent Task now uses a versioned connection definition and labels its existing token authentication as a bearer token. New Google Ad Manager setup also pins a built-in versioned contract for its numeric network code and platform service account. Existing API integrations keep working through the legacy request shape while connection types migrate.

## 5.33.0 — August 2, 2026 at 4:08 PM UTC

* The "Your advertisers" card on the buyer home page now shows "Current" instead of "Open" when displaying the currently-scoped advertiser, making it clear which advertiser you're already in.
* If your storefront had a connected source that wasn't an ad server (for example a modular feed), Signals and Inventory Components previously told you to "connect an ad server" as if nothing were connected at all. Both now say your connected source doesn't expose ad-server targeting or inventory, so it's clear an ad-server connection is what's still missing — not your existing source. The go-live checklist's "Connect ad server" step gets the same acknowledgement when another source is already connected. Nothing to change on your side.
* If your storefront is enrolled in modular inventory sources, add `formatOptions` and `publisherProperties` to every collection before your next avails feed preview or commit. Existing collections without valid declarations stop at `MODULAR_CATALOG_NOT_READY` until you refresh the feed; Interchange does not infer a format from `channel` or a URL-based legacy ID. Buyers need no action: catalog-ready collections continue into buyer products with the seller-declared formats and properties.
* The go-live "Successful transaction" check now matches what you've actually connected. If every connected source is your Scope3-managed sales agent, the check reports done automatically as "Covered by your managed sales agent" — no separate no-spend test needed. If you also connect a third-party sales agent, the check still applies, and now names which source it's asking you to test.
* The Test Runs page no longer leaves you stuck when you have no sandbox test history yet — a "Run a test brief" button on the empty state (and in the history list once you have runs) asks Murph to run a sample buyer brief against your storefront, with the result shown right there.

## 5.32.2 — August 2, 2026 at 2:50 PM UTC

* Collapsing a widget on the Ask Murph page now leaves a quiet single-line row — the widget's name and a small expand arrow — instead of a large bar with a bold "Expand widget" button, so several collapsed widgets stack as a tight list instead of a stack of white slabs. The "still open" reminder for an unfinished setup task also no longer repeats every time you open something else in the same session.

## 5.32.1 — August 2, 2026 at 2:08 PM UTC

* Renamed the shared "Choose an IU plan" surface's internal identifier from `storefront-plan-selection` to `iu-plan` to match the plan's organization-wide scope across buyer and storefront workloads. The Task itself is unchanged — same review, same accept/decline/renewal flow. Any host or integration that referenced the old `storefront-plan-selection` resource URI keeps working: the old URI stays aliased for one release while every client picks up the new one.

## 5.31.2 — August 2, 2026 at 1:23 AM UTC

* The demand inbox and its proposal-pass view now read as one clean document instead of stacked panels. Each screen is a single card with a quiet header, aligned figures, and a flat ledger — no more nested boxes, and a metric with nothing to report reads as its reason in one glance, never as a fabricated zero.

## 5.31.0 — August 1, 2026 at 10:43 PM UTC

* Products built from ad-server inventory now keep the delivery options you selected through buyer discovery and checkout. Inventory Components and Inventory Selector show practical format details, ask for a video length when one is required, and catch options that the selected inventory cannot deliver before saving. Existing composed products continue to work during the upgrade; no action is required.
* Meta's community catalog now identifies Messenger and Threads as Meta-owned properties while keeping formats and placement targeting limited to verified Facebook and Instagram surfaces. No buyer action is required.

## 5.30.0 — August 1, 2026 at 8:29 PM UTC

* Agency and power buyers using Meta product discovery and campaign creation now get safer property handling. Standard products remain limited to disclosed Facebook and Instagram placements, so no action is required. Buyers whom Scope3 enrolls in the AdCP 3.2 candidate can also discover Advantage+ products; those products identify that Meta may deliver beyond the disclosed property list and cannot be targeted to a chosen property list. Contact Scope3 to request candidate access.

## 5.28.4 — August 1, 2026 at 7:34 PM UTC

* Composed product prices now appear on decision records. Simulator comparison cards, the proposal pass, and demand-inbox projections show each offered product's CPM and the cost basis it was priced over — the numbers previously lived only in the agent's written reasoning. Non-CPM pricing is left unlabeled rather than shown as a CPM.
* Simulator comparison cards now read as business documents. A run that made an offer speaks through its products, prices, and reasoning — no status chip, and no "Why declined" label on a run that responded. Runs that produced no offer say so plainly ("No offer", "Did not complete") with the reason. The pinned brief shows the budget, the buyer, when it was observed, and what inventory was frozen with it, instead of raw field names and timestamps.

## 5.28.0 — August 1, 2026 at 5:33 PM UTC

* You can now create a draft product from a publisher's custom creative format. In Property Roster, **Create product** opens a focused task with the publisher format and property scope already attached. Choose an **Ad server**, select the inventory and **Delivery formats** reported by that source, review the product, and select **Create draft product**. The work stays in the task instead of being sent back through chat. Existing products and other product-authoring workflows are unchanged, and the draft remains hidden from buyers until you activate it. Sellers who do not use publisher formats do not need to act.
* For API integrations, V3 `wholesale_product.formatOptions` now uses the same canonical format concepts as V2 and returns saved inventory and format details when a product is read. Calls that omit `formatOptions` keep their existing behavior. During the gated preview, the previously documented snake\_case option fields continue to normalize to the canonical shape; legacy agent URL references remain invalid.
* **Launch:** This is an atomic ungated addition to the existing GA Product Authoring feature (`gate: none`). It expands with the deployment. Reverting this change removes the new Property Roster entry point without changing existing products or the underlying V2 product operations.
* **Measurement:** Track `prepare_wholesale_product` launches, successful `validate_esa_product` and `create_esa_product` operations for drafts carrying publisher format options, validation-to-create conversion, and create failure rate. Acceptance is at least 20 successful publisher-format draft creations across five storefronts with no confirmed regression in existing product authoring and a create failure rate below 5%.
* **Monetization:** None. Product-authoring entitlements, packaging, pricing, and Intelligence Unit treatment do not change.

## 5.27.0 — August 1, 2026 at 4:29 PM UTC

* Modular inventory-source readiness pages now load correctly when account-scoped lifecycle stages are present.

## 5.26.0 — August 1, 2026 at 3:50 PM UTC

* If your storefront uses a CitrusAd modular inventory source, open Buyer Account Mapping, refresh its accounts, and select the CitrusAd team for each operator-and-brand relationship. Interchange then scopes product discovery, media-buy creation and history, delivery reporting, and account resources to that team. Buyers keep using the same requests and receive the newly mapped account-scoped results. No CRM setup is required. Other modular inventory sources are available for binding only when they support all of these account-scoped operations; existing agent, Google Ad Manager, and FreeWheel bindings are unchanged.

## 5.25.1 — August 1, 2026 at 2:53 PM UTC

* Property Roster now turns each discovered creative format into a product-planning action. Expand **Creative formats** to see the inventory where a format can run and the creative a buyer needs, then choose **Use in a product** to continue. If a format does not match a current property, the roster guides you to review its property mapping instead. Format IDs and sources remain available under **Technical details** when you need them.

## 5.25.0 — August 1, 2026 at 1:27 PM UTC

* Media buys now send package pacing to sellers only when the buyer explicitly authored it, so an internal default no longer blocks otherwise valid Meta campaigns.
* You can now catch problems with publisher format options while authoring a wholesale product. When an entry in `format_options[]` includes a publisher's `publisher_domain`, `format_option_id`, `format_kind`, and `params`, product validation warns if the connected publisher catalog does not contain that option, declares a different canonical kind, or limits it to properties the product does not select. A product can still narrow the catalog option's parameters.
* No action is required for existing products. These warnings are advisory: a catalog lookup problem does not block authoring or change the managed sales agent's validation result. Validation covers product-level format options, not placement-specific availability. AAO registry data still does not authorize a sales agent.

## 5.24.1 — August 1, 2026 at 12:13 PM UTC

* Keep the v3 account status response navigable when buyer readiness is temporarily unavailable.

## 5.24.0 — August 1, 2026 at 11:00 AM UTC

* Sellers can now see source call health alongside ad-server status, sync history, sandbox readiness, and modular-source readiness, without one unavailable check hiding the others. Ad-server setup and credential changes remain in the secure interactive setup experience, and unavailable operations are reported clearly. No action is required.
* Simulator runs no longer appear in the Demand inbox. What-if executions were surfacing as phantom ledger rows with an empty buyer and counting into the scoreboard; the ledger now shows only real demand, exactly as the Simulator's isolation promise states.
* In Buyer Account Mapping, sellers with a managed FreeWheel source can now refresh authenticated advertiser choices, then select or import a source binding for each operator-and-brand relationship. Interchange uses that binding for product discovery, media-buy creation and history, delivery, and account resources; no CRM setup is required. Google Ad Manager and third-party sales-agent behavior is unchanged, and modular sources remain unsupported.
* Child storefront admins can now add their own payout entities in **Settings → Billing → Payout entities** without needing access to the parent organization's commercial billing account. Your inherited parent payout details remain the read-only fallback until you add an account-owned destination; no action is required unless you want the child storefront paid separately. Parent organization admins can continue managing a direct child's payout entities on the child's behalf.
* Meta media-buy requests that use a nested ISO subdivision now return an actionable validation error before any provider write. Supported top-level regions and country targeting are unchanged.
* Inventory discovery now reports live, modular, and cached-catalog source failures as a retryable error when no source or fallback completes. It preserves genuine empty successes and no longer describes an unfinished or failed source task as zero matching products.
* When no payout entities are configured, the empty state now shows a labeled Add payout entity action that assistive technology can identify. Nothing changes on your side.
* Agents using the v3 storefront surface can now open the portable Demo Storefront Page to inspect and manage an existing synthetic demo. Demo creation remains a Scope3 platform-administrator action, and Plan & Billing continues to require the authorized human for legal and payout changes.
* Made modular source setup, readiness, avails import, and external sales-agent connection available through the same portable typed Tasks and Pages in every MCP Apps host.
* Storefront operator-domain updates now preserve profile and verification data when a domain is first set or changes only by an equivalent spelling. Account-domain updates keep mirrored storefront domains synchronized without clearing their profile, and storefront configuration remains available when demo status cannot be loaded. Active managed inventory sources without a connection marker now continue to report their connected state. No action is required.
* `PUT /storefront` now protects your existing operator profile when you change `operatorDomain`. If an omitted `description`, `channels`, `membershipStatus`, or `website` contains a value, the request returns a validation error naming the fields that would be cleared. Resupply values for the new operator, or pass `confirmOperatorDomainProfileReset: true` to clear fields you do not resupply.
* If the operator domain or affected profile fields change before your confirmed retry, the API returns a conflict; read the storefront again and retry. An unset or previously mirrored storefront domain continues to sync with the account’s `customerDomain` while preserving populated `description`, `channels`, `membershipStatus`, and `website` values. Only an explicitly divergent operator domain remains isolated from account-domain changes. Calls that keep the same operator domain continue without confirmation.
* Spotify placement IDs in catalogs and delivery reports now use
* `spotify.com:in_stream` or `spotify.com:in_feed` instead of
* `spotify.com:MUSIC`. Update code and dashboards keyed on the old ID. Mixed
* podcast and Audience Network inventory remains unpublished.
* You can now review the canonical creative formats discovered for each publisher in Property Roster. Expand **Creative formats** to see format kinds, dimensions or duration constraints, applicable properties or tags, and whether each format came from the publisher or the AAO registry. No setup changes are required.
* Format discovery does not change authorization. Only the publisher's live `adagents.json` can authorize your sales agent. Media buys still use the format options on each product, which can be narrower than the publisher's discovered formats.

## 5.23.1 — August 1, 2026 at 6:50 AM UTC

* Buyers: Meta paused/no-spend verification now waits a bounded interval for provider cancellation to become visible instead of failing on an immediately stale read.

## 5.23.0 — August 1, 2026 at 6:09 AM UTC

* Buyers: Meta cancellation readback now keeps a directly deleted campaign canceled even while Meta's derived effective status is still catching up.
* Buyers: Meta cancellation readback now treats a directly read deleted campaign as authoritative without querying its unavailable child ad-set edge.
* No action is needed. Spotify campaigns created with regional targeting now complete successfully instead of failing during provider verification, while changed placements, regions, demographics, and unsupported targeting remain blocked.

## 5.22.0 — August 1, 2026 at 4:26 AM UTC

* Buyers: Meta's no-spend verification now distinguishes a campaign that is waiting for creative from the provider-level pause that contains spend. Nothing changes on your side.

## 5.21.3 — August 1, 2026 at 3:53 AM UTC

* Buyers: Meta Instant Form campaigns now accept the provider's disabled Page signal-enrichment default during promoted-object verification while continuing to fail closed for conflicting provider values.
* Buyers: age-targeted product searches now return the age range and determination method on each product, as documented. A product composed against a seller's age signal was answering without its `ext.scope3_product_targeting.demographics.age` block, so the response named an age range in the product title while declaring none of it structurally, and there was no way to confirm the provenance you asked to accept. Requests that restrict `accepted_determination_methods` were affected the same way. No change is needed on your side.

## 5.21.2 — August 1, 2026 at 3:08 AM UTC

* Eligible Meta on-platform conversion campaigns now accept the account-scoped product IDs returned by discovery, avoiding an invalid-product rejection for built-in lead, messaging, and shop goals.

## 5.21.1 — August 1, 2026 at 2:39 AM UTC

* Meta campaign product discovery no longer returns an empty conversion target list, so strict AdCP clients can proceed with eligible campaigns. Nothing changes for value-optimization campaigns.

## 5.21.0 — August 1, 2026 at 2:12 AM UTC

* Spotify ad-set creation and updates no longer stall when Spotify omits the account ID from its response, and invalid region targeting now returns a clear correction before anything is changed. No seller action is required.
* Sellers: In Signal Manager, you can now classify an ad-server signal as Generic, Property, or Age. For an Age signal, map one exact adult range and choose how the age was determined: survey-based, assumptive, user-provided, or user-verified. You can also name the data provider. This lets age-targeted buyers find eligible products instead of receiving a misleading “no inventory” response. Property signals remain available for inventory setup and are not offered as buyer targeting.
* Buyers: Age-targeted product searches now distinguish unavailable age targeting from an empty storefront. A product is eligible only when its age range matches exactly, its age signal comes from the same inventory source, and its determination method is one you accept. If inventory exists but its age mapping or provenance cannot satisfy the request, the storefront explains that age targeting is unavailable instead of claiming there is no inventory. You can optionally restrict accepted determination methods; no action is required if you do not need that restriction, and requests without an age range are unchanged.
* Restore delivery reporting for media buys routed to sellers on the pre-2026-07-28
* MCP protocol.
* Reporting for affected media buys stopped updating on 2026-07-31 and returned an
* authentication error, even though the seller connection was healthy and its
* credentials were valid. Delivery for those buys now flows again, and the missing
* days are backfilled.
* The cause was in the AdCP SDK's protocol negotiation. It probes a seller for the
* newer protocol before falling back to the older one, and a seller that answered
* that probe with an authorization error was treated as having rejected our
* credentials rather than as simply not speaking the newer protocol. Sellers on the
* older protocol are now reached correctly on the first attempt.
* If you export delivery or spend for a date range covering 2026-07-30 or
* 2026-07-31, re-run the export after this release to pick up the backfilled rows.

## 5.20.0 — August 1, 2026 at 1:26 AM UTC

* When work linked to one of your asks is verified as live in production, Interchange sends an update and keeps the ask in Your requests for 90 days. The update shows the release date and version, what changed, and what to do next. Closing an internal ticket or merging a pull request does not trigger this update; after delivery, you can confirm the outcome or say you’re still blocked.
* Settings now reflect successful credential, payment, connection, notification, team, and storefront changes immediately and remain correct after a refresh. Nothing changes in how you manage these settings.
* Wait boundedly for exact Spotify placement and targeting readback when an ad-set create response is incomplete.

## 5.19.0 — August 1, 2026 at 12:27 AM UTC

* From the Modular inventory source workspace, select Preview buyer discovery under a Ready Get products stage and enter a buyer brief to see only the products that source would return. The preview rechecks source status and readiness, records the decision for later review, and never includes products from another configured source. It does not create a media buy, change live products or source setup, or turn on transacting; brief tests started outside a source workspace remain storefront-wide.
* Seller accounts enrolled in the v3 preview can now update their canonical operator domain with `save_storefront`, and `get({ "kind": "storefront" })` includes the domain’s verification state. A no-op save returns `"action": "unchanged"` without writing.
* If changing the domain would clear a populated identity profile, the error names the affected fields. Review them, then retry with `confirmOperatorDomainProfileReset: true` to clear them. Use `PUT /storefront` instead when you need to preserve or replace those profile fields. The v2 Storefront API remains supported.
* Authenticated storefront administrators can now refresh advertiser choices for
* an active managed Google Ad Manager inventory source through the storefront API
* or MCP `api_call` operation `refresh_seller_account_source_accounts`, then
* select the advertiser through Buyer Account Mapping. Interchange automatically
* applies that binding to product discovery, media-buy creation and history,
* delivery, and account resources; buyers do not need to change their requests,
* and no CRM setup is involved.
* FreeWheel and modular sources do not yet support explicit bindings. Leave
* required coverage unresolved rather than importing a guessed account, and use
* `Not required` only when the seller's contract does not require a source
* account.
* Calling the buyer or storefront `api_call` tool with an unknown operation, unsupported path parameters, or missing required path parameters now returns a normal structured error instead of failing client-side output-schema validation.
* Meta connections now discover eligible Page-native conversion sources through the current Business Portfolio ownership and Page advertising-access model when Meta's legacy promoted-Pages inventory is empty.
* Connections now shows an ad platform as disconnected immediately after you unlink it and keeps that state after a page refresh. Nothing to change on your side.
* `PUT /storefront` now protects your existing operator profile when you change `operatorDomain`. If an omitted `description`, `channels`, `membershipStatus`, or `website` contains a value, the request returns a validation error naming the fields that would be cleared. Resupply values for the new operator, or pass `confirmOperatorDomainProfileReset: true` to clear fields you do not resupply.
* If the operator domain or affected profile fields change before your confirmed retry, the API returns a conflict; read the storefront again and retry. Changing an account’s `customerDomain` also leaves a populated storefront and its `operatorDomain` unchanged, so make that change directly through `PUT /storefront`. Account-domain synchronization still runs for an unset or mirrored storefront domain when those profile fields are empty. Calls that keep the same operator domain continue without confirmation.
* Seller-owned inventory-source test plans now find and reuse an existing sandbox advertiser from its brand domain and currency. Complete REST plans bind the resolved advertiser and currency into the single-use execution token and require explicit currency plus creative/no-creative readiness. Product previews stay in the same sandbox account, so repeat no-spend tests no longer require buyer-side advertiser access or a previous run's history. Nothing changes for production advertisers.
* Wait boundedly for exact Spotify optimized ad-set identity, delivery-goal, and targeting readback before accepting a media-buy create.

## 5.17.0 — July 31, 2026 at 8:51 PM UTC

* When buyer-serving calls stop before reaching an inventory source, storefront readiness, Murph, V3 account status, and inventory-source reads now share one explanation of the blocker, its effect, supporting evidence, and exact fix. Billing incompatibilities show advertised and required modes. Source diagnostics also distinguish storefront candidacy from direct source calls, historical empty or slow responses from ranking inputs, and source-exchange latency from total test duration. No setup change is required unless a surfaced blocker names one.
* Require an Enterprise entitlement to create modular inventory sources or attach modules. Existing sources and their buyer-facing storefront behavior remain operational, and managed ad-server connections stay included. Sellers who already have the entitlement need take no action; sellers who need access should contact their account team.
* Wait for Spotify's bounded paused-campaign readback before creating child ad sets.

## 5.16.0 — July 31, 2026 at 8:18 PM UTC

* Parent-organization admins working in a child storefront can open payout details from Settings without being redirected back to the storefront home.
* Source diagnostics now show a real reporting status for sources Scope3 polls,
* instead of always showing "unknown". When a source returns delivery we cannot
* accept, the diagnostics name the field that was rejected, so it is clear what to
* change rather than only that reporting is empty. Re-reading a past day now
* records the same status, and leaves an entry in the report-processing view even
* when the day's delivery is declined.

## 5.15.2 — July 31, 2026 at 8:00 PM UTC

* Select the deployed Meta Facebook Login for Business configuration during OAuth authorization.

## 5.15.1 — July 31, 2026 at 6:56 PM UTC

* Failed inventory-source test campaigns now distinguish a local media-buy preflight failure from reaching the buyer-side `create_media_buy` dispatch boundary. Murph shows the specific per-buy failure and makes clear when no seller call could have been issued instead of replacing the reason with a generic Buyer API error or implying that an attempted buy necessarily reached the inventory source.
* Meta connections now use the Page-scoped access Meta requires when discovering active Instant Forms, allowing eligible lead-optimization sources to appear without exposing or storing Page tokens.

## 5.15.0 — July 31, 2026 at 5:43 PM UTC

* You can now fill wholesale pricing and availability gaps from an ad-server source; prices already supplied by the ad server stay in place. Choose **Import seller feed** to download a pre-filled template, preview accepted and rejected rows and selector matches, and commit the reviewed feed. Each commit replaces only that source’s previous uploaded wholesale feed; rate cards and buyer discounts remain in their existing setup flows.
* Buyer catalog and pricing presentation are unchanged; committed source data continues through the existing catalog flow. This release does not change billing, packaging, margins, or monetization.
* Creative-to-product matching is now safer and more predictable for buyers and sellers. Creatives must match a product's declared format and scoped option exactly; stale or ambiguous legacy labels are no longer guessed. Buyers should re-check creatives that previously matched through legacy aliases, and sellers should verify that their product format declarations are current because those declarations now determine which creatives are accepted. No action is needed when canonical format declarations are already accurate.
* Meta adapter responses now identify Meta request-limit failures as rate limited instead of reporting a generic service failure.
* If your Meta integration sends `targeting_overlay.signals`, replace it with
* `targeting_overlay.audience_include`; the Meta-specific extension is no longer
* accepted.
* On connected Meta accounts, boostable posts from authorized Facebook Pages now
* appear automatically as read-only creatives. Ready Custom and Lookalike
* Audiences returned by `get_signals` can be included or excluded with
* `audience_include` and `audience_exclude`, with no separate ID-mapping step.
* If Page posts are missing from an older connection, reconnect Meta to grant the
* required Page permissions. Creating media buys from existing posts is not yet
* available to ordinary buyer accounts; image and video creative workflows are
* unchanged.
* Meta reconnects now re-request missing or previously declined Page permissions, so eligible Instant Forms appear as lead-optimization sources after reconnecting.

## 5.14.2 — July 31, 2026 at 3:23 PM UTC

* Reconnect Meta once to grant the Page advertising and lead permissions needed
* for Instant Form discovery. Scope3 now requests those permissions and continues
* to fail closed when Meta does not return authorized Form inventory.

## 5.14.0 — July 31, 2026 at 2:11 PM UTC

* Image creatives missing a click-through URL now fail at sync time with a clear error instead of trafficking to GAM with the image URL as the ad destination.
* Meta Instant Form campaigns now discover forms through Pages the connected
* principal can advertise as, using Meta's supported Page-scoped form inventory
* when the ad account's promotable-Page list is empty.
* Your agent now has one way to tell Scope3 what you are waiting on. Use
* `save_ask` for support, product, integration, and commercial asks—and for
* supply when a buyer is looking for inventory—then use the returned id to say
* whether the answer resolved the problem, you received it without disputing it,
* left you blocked, or should be withdrawn.
* Use `search` and `get` with `kind: "ask"` to read the same list from either a
* buyer or seller account. Direct MCP remains limited to enrolled accounts;
* Murph adopts the new tools automatically.
* Enterprise buyers keep the same account and approval workflows. Agency and
* MCP-builder teams can use one filing integration across account contexts.
* Sellers get the same support, product, integration, and commercial filing
* vocabulary plus ask reads; supply filing remains buyer-only. There is no
* pricing, billing, plan, or entitlement change, and storefront ranking and
* inventory visibility are unchanged.
* MCP builders should replace `report_issue`, `report_integration_need`,
* `track_my_product_ask`, `create_supply_request`, and `remove_supply_request`
* with `save_ask`. New Murph turns no longer advertise the retired Murph writers;
* `POST /api/v2/supply-requests` and `POST /api/v2/supply-requests/remove` keep
* working through the API release containing this change. Those calls and
* `list_my_requests` may be removed no earlier than the following API release,
* after usage review; migrate reads to `search` and `get` now.
* Removal also requires 30 consecutive days with at least 95% of first-party ask
* writes using `save_ask`; each compatibility endpoint or alias below 1% of its
* corresponding canonical write or read volume; and filing success no more than
* one percentage point below the 30-day pre-release baseline.
* Keep authoritative zero-value budgets in Meta and Snap media-buy readbacks so one zero-budget campaign cannot invalidate the account's complete creative and media-buy inventory response.
* Ad-server signal drafts now use the source's valid value types and mapping fields consistently, so supported targeting can be validated and created without manual payload repair. Nothing changes in existing saved signals.

## 5.13.0 — July 31, 2026 at 12:58 PM UTC

* Media-buy reads now return their applied optimization goals directly. Campaign updates also reject performance configuration on discovery campaigns instead of silently changing mode, and existing performance configuration can be cleared explicitly with `null`.
* Meta connected accounts now discover active Instant Form conversion sources
* from the selected ad account even when Meta's promotable-Page list is empty,
* while campaign creation continues to verify the exact published Page and native
* optimization readback before returning success.
* When buying Meta inventory through an adapter storefront, buyers can now select one of each product's advertised `optimization_goals`; requests that omit the field continue to use the product default. Meta products advertise their supported metric, conversion, and vendor-metric goals with `max_optimization_goals: 1`. Create, update, and media-buy reads return the selected goal only after Meta confirms the exact optimization-goal and billing-event pair. Invalid combinations fail before any Meta write.
* Existing `bid_price` requests remain supported when the selected pricing option allows a maximum bid. Meta treats the value as the per-auction maximum, and responses return it as `bid_price`. AdCP 3.1 clients cannot request cost caps, ROAS floors, or the AdCP 3.2 `bidding` field. Those requests, including monetary goal targets that would require a stronger policy, fail closed instead of changing the requested semantics.

## 5.12.0 — July 31, 2026 at 12:07 PM UTC

* Your modular source workspace won't send you to add a module you don't need. When we can't read what one of a source's modules does, the lifecycle stages it might have run now say it hasn't declared them, instead of reading as unsupported and pointing you at another module to attach. A stage that genuinely has no module still tells you which kind to add. Murph makes the same distinction now, rather than calling those stages unsupported. Nothing to change on your side: a module we can't read is ours to fix, not a gap in your setup. Every other stage on the source reports as before, and if a stage you're counting on reads this way, telling Murph gets it to us.

## 5.11.1 — July 31, 2026 at 11:45 AM UTC

* Keep Meta placement-only controls scoped to explicit manual-placement buys so exact demographic requests can use Advantage+ placements while retaining strict audience-expansion and age readback checks. Campaign deletion now tolerates bounded provider readback propagation without repeating the delete mutation.

## 5.11.0 — July 31, 2026 at 11:02 AM UTC

* Fix budget updates on pending-creatives media buys not reaching the seller.
* When a buyer updated a media buy using a product-level budget while the buy was waiting for creatives, the updated budget was saved locally but not forwarded to the seller. The buy would continue running at the original budget.
* Fixed the self-serve Prebid.js `orgId` reveal — asking Murph "what's my Prebid.js orgId" now returns the URL instead of an error. The tool had been failing since it shipped because the REST route wrapped its response outside the standard envelope; the response now follows the same shape as every other v2 endpoint.
* Social media buys now report the actionable AdCP setup state consistently across platforms. A paused buy with no creative reports `pending_creatives`, then `pending_start` while a creative-ready flight is still in the future; its retained pause becomes visible only when the buy is otherwise launch-ready. If you filter media buys by status, include these pending states when looking for paused setup holds. The underlying ad-platform campaigns remain safely non-serving throughout setup.
* Products are refreshed after an advertising account connection or credential changes, so a newly selected product can be bought without replaying stale account authorization.
* A new `PUT /esa/{esaId}/default-advertiser` sets the default advertiser — the advertiser a buyer's spend books against when no per-buyer rule matches — on whichever ad server backs an embedded sales agent. It works for Google Ad Manager today; pair it with `GET /esa/{esaId}/gam/advertisers` to find an advertiser id. AdsWizz sources are accepted but both setting the default and listing the roster with `GET /esa/{esaId}/advertisers` return an error until a pending embedded sales-agent release lands, so wait for that release before using either against AdsWizz. `PUT /esa/{esaId}/gam/default-advertiser` is unchanged and existing Google Ad Manager integrations need no update; per-buyer mapping rules remain Google Ad Manager only, and FreeWheel and SpringServe are not supported.
* Image uploads now validate that the file can be decoded before storing it. Uploads of corrupt or truncated JPEG, PNG, GIF, or WebP files are rejected with a validation error instead of being silently stored and sent to ad servers.

## 5.10.0 — July 31, 2026 at 9:17 AM UTC

* Fix canceled media buys reverting to pending approval.
* A race between the cancel database commit and the forward-worker claim stamp allowed the approval-forward worker to pick up a just-canceled buy and push it back to the seller, reverting the buyer's cancellation.
* Seller-specific canonical format selections now carry their exact scoped identity through media-buy creation and creative sync, while injected or inconsistent route metadata is rejected.
* Meta storefronts now preserve exact brief-grounded age targeting when Meta adds
* known disabled audience controls to its readback. Requested controls must still
* round-trip, and active, missing, or unknown controls continue to fail closed.
* Existing `/mcp/v3` searches are unchanged unless `kind: "ask"` is explicit. Buyer agents can keep the requests their account filed in the same workflow they use for buying, while seller agents can do the same in their storefront workflow. Each can optionally narrow their own account's asks by type or open/closed state, then pass the opaque result id to `get` with the same kind for one ask.
* The read keeps Scope3's workflow status beside the requester's separate answer, so Scope3 marking an ask resolved and the requester reporting that they are still blocked remain two facts. Internal workflow fields and account-routing identifiers are not returned. An ask id from another account is indistinguishable from one that does not exist.
* Ask titles can contain customer-supplied text, so asks appear only when `kind: "ask"` is explicit; unrelated broad searches do not pull them into context. The existing `v3-agent-surface` flag remains the rollout and kill switch.
* The glossary now defines **Supply ask** — an ask for inventory we do not carry —
* including the part that decides whether yours is one: it needs a buyer who can
* actually spend, so a curator buying on behalf of demand qualifies while a
* publisher who wants demand for their own inventory is asking for something else.
* A withdrawn supply ask keeps its record as evidence the demand existed.
* It also settles a phrase you may have seen: "demand signal" describes what an ask
* is evidence *of*, not an object you create or read, and not a kind of signal —
* those are targeting material a seller authors.

## 5.9.3 — July 31, 2026 at 8:09 AM UTC

* Meta storefronts now preserve exact brief-grounded age bounds when Meta returns
* its canonical age-range alias or omits the default false unknown-age control.
* Explicit unknown-age choices still round-trip, and a broader provider readback
* still fails closed.
* Your ad server source was upgraded on 30 July 2026. These fixes are already
* live — this note is late, and one of them is worth acting on.
* **Check any media buy you cancelled before 30 July.** Cancelling a buy did not
* reliably reach your ad server, so a buy you believe is cancelled may have kept
* delivering. Cancellation is dispatched upstream now, but it does not retroactively
* stop anything that was missed: please verify directly in your ad server for buys
* you cancelled before that date.
* Also fixed, no action needed:
* **Delivery reports honour the window you ask for.** A report for a specific
* date range previously returned a different period's numbers.
* **Product targeting keys are kept when you save.** Custom targeting keys on a
* product were merged rather than dropped.
* **An explicit `delivery_type` is no longer overridden.** Saving a product as
* `guaranteed` without pricing options could silently return it as a
* non-guaranteed auction product.
* **Creative format selectors are emitted in canonical form**, and adapter
* booking-lifecycle capabilities are now declared, so a buying agent can tell
* what your source supports before it tries.
* Canonical selections projected from a seller's older named formats now retain that seller's exact route through later media-buy creation, updates, and assigned creative sync. Buyers and sellers do not need to change their integrations; missing or ambiguous mappings remain excluded rather than guessed.
* The seller widget now calls a signal a **signal**, in all nine languages. The
* menu entry, the workspace heading, its tabs, and the create and validate
* controls all match the API and the documentation, which already used that word.
* Its two tabs still name the two layers they always did: **Ad-server targeting**
* is what your ad server already contains, and **Signals** are the ones you
* authored from it — browsing the first still creates nothing.

## 5.9.1 — July 31, 2026 at 7:01 AM UTC

* Seller Setup labels a modular source "Modular source" on its card, matching the name every other surface uses. It still said "Feed-backed source" there.
* Three things a seller or their agent could look up and not find are now in the
* glossary:
* **Composed product** (`cf_…`) — built to a buyer's brief at discovery time,
* not authored by you — and **Passthrough product**, which belongs to a
* third-party sales agent you connected. Together with **Wholesale product**,
* all three kinds you see in reporting now have a definition and an id prefix.
* **Property signal** — the ad-server key-value that lets a property you
* declared in `adagents.json` be found in the ad server that serves it. It is a
* signal by mechanism, not something a buyer targets, and it never appears in a
* brief.
* **Component or selector?** The same ad unit is both, in different roles. There
* is now a rule: component when the subject is what you sell, selector when it is
* where it runs.

## 5.9.0 — July 31, 2026 at 4:20 AM UTC

* Modular inventory source access no longer drops out mid-session when the
* feature-flag service is briefly slow to answer. A seller who is enabled for
* modular inventory sources keeps access for the cached verdict window instead of
* seeing "Modular inventory sources are not enabled for this customer" on the next
* call.

## 5.8.0 — July 31, 2026 at 3:16 AM UTC

* **Buyers:** When you call `get_products`, a seller's older named format can now appear as a canonical `format_options[]` entry if that seller published a valid mapping. Nothing changes in your integration; existing canonical options and legacy `format_ids[]` keep their current shapes.
* **Sellers:** To make an older named format available through `get_products`, add a matching `canonical` declaration to that format in `list_creative_formats`. Dimensions and duration must match. Interchange ignores invalid or conflicting mappings; if a returned product remains unresolved, the seller result includes details in `projection.diagnostics`. For new products, publish canonical `format_options[]` directly. See [Get products across storefronts](https://docs.interchange.io/v2/buyer/discovery/multi-storefront-get-products#canonical-options-from-older-seller-formats).

## 5.7.2 — July 31, 2026 at 2:37 AM UTC

* Murph now files integration requests from a concise description and the conversation already in progress, instead of asking sellers to complete a repetitive setup form. Nothing changes on the seller’s side.

## 5.7.1 — July 31, 2026 at 1:57 AM UTC

* A media buy the storefront could not place with its source now reports `canceled` instead of `pending_start`.
* When `create_media_buy` is accepted but the forward to the underlying source fails (a malformed request, an unreachable source, a credential fault), no media buy is ever created upstream and none ever will be. Those buys previously reported `pending_start`, which AdCP defines as "ready to serve and waiting for its flight date to begin" — so a buy that had already failed looked like one that was about to launch, indefinitely. They now report `canceled` with `cancellation.canceled_by` set to `seller`, and the cause (`invalid_request`, `source_unavailable`, `not_authorized`) in the response `errors[]`.
* `rejected` is unchanged and still means what it always did: a source considered the buy and declined it. A transport or credential failure is not a seller's refusal, so it does not read as one, and retrying such a request may succeed.
* `get_media_buy_delivery` also changes for a buy spread across several sources: a source whose delivery could not be read this call no longer drags the whole buy's status down to `pending_start`. The status now reflects the sources that did respond, and the unreadable source is reported in `errors[]`. When no source can be read at all, the call still returns `SERVICE_UNAVAILABLE` rather than zeroed totals under a misleading status.
* The storefront API and the seller assistant now call a signal a **signal**. The
* operations that list, create, read, replace and delete one are described that way
* in the API reference, and the assistant uses the same word when it talks to you
* and when it asks you to approve a change. The raw material you build a signal
* *from* keeps its own name, **ad-server targeting** — browsing it still does not
* create anything.
* Nothing you call changes: operation names, paths and fields are untouched
* (`create_signal`, `list_esa_signals`, `signalId`), so integrations need no
* update. This completes the API half of the rename announced earlier; the seller
* widget still reads "Signal components" and follows once its translations are
* reviewed.

## 5.7.0 — July 31, 2026 at 12:39 AM UTC

* Buyer agents using V3 now receive account setup and destination readiness
* directly from `get_status`, without being offered a V2-only setup tool that the
* V3 surface does not support. The V2 Buyer Setup page remains available and is
* unchanged.
* Pinterest connections now request the `catalogs:read` and `catalogs:write` OAuth scopes, so syncing an advertiser catalog to Pinterest works. Previously the connection only asked for ad and Pin permissions, and Pinterest rejected every catalog feed registration made through it.
* If you already have Pinterest connected, reconnect it to grant the catalog permissions. Your existing campaigns, Pins, and reporting keep working in the meantime — only catalog sync needs the new grant.
* Nothing changes for your existing `support` and `product` calls if you do nothing.
* `save_ask` now covers everything you can be waiting on Scope3 for, and lets you update an ask after you file it. Alongside `support` and `product`, file `supply` for inventory we do not carry (name the domain in `subject`, the channel in `channel`), `integration` for a counterparty we do not connect to (name it in `subject`), or `commercial` for pricing, terms, billing, or a rate-card exception. `type` is optional now — omit it when you are not sure and we route the ask instead of you holding it back. A `supply` ask is the one type that needs an account set up to buy; every other type files from any account.
* To update an ask, call `save_ask` again with the `askId` it returned, passed back as `id`, plus a `requesterState`: `confirmed_resolved` (what you wanted happened), `accepted` (you have heard our answer and are not disputing it — not the same as resolved), `still_blocked` (our answer did not work), or `withdrawn` (never mind; the record is kept). An optional `note` replaces the note on that ask; omit it to leave the existing one alone — this door cannot blank a note. Your answer sits next to ours instead of overwriting it, so "we called it resolved" and "I am still blocked" both stay visible as separate facts.
* Filing needs only read access. Updating needs write access from that account's own session — a staff or agent session without a customer identity can file and read asks but cannot answer them. Withdrawing narrows further: only the person who filed that ask, or an account admin, can do it. `title`, `type` and `severity` are fixed once an ask is filed.
* Buyers and sellers use the same door for support, product, integration, and commercial asks. A seller-only account cannot file a `supply` ask because that route represents inventory a buyer intends to purchase; sellers can still file every other ask type, and no seller workflow is removed.
* This does not change pricing, billing, packaging, take rates, or any other monetized surface. The `v3-agent-surface` flag is the rollout and kill switch. We will measure adoption by the share of `save_ask` calls using `supply`, `integration`, or `commercial`, and operational health by successful opaque tracking-id issuance; index failures now alert through Sentry as well as logs.

## 5.6.0 — July 30, 2026 at 10:45 PM UTC

* When you open Source Diagnostics for an inventory source, you can now see its
* recent outbound call latency, successes, errors, and timeouts alongside the
* preceding equal window. Only calls linked to that source appear there; calls
* made without a source link are excluded. Nothing to change on your side.

## 5.5.1 — July 30, 2026 at 10:17 PM UTC

* Allow exact zero-spend nested-geo DRAFT cleanup before transient lifecycle projection fields materialize.
* Storefronts we broker buys for are now recorded with the reporting arrangement
* they actually use, which is the schedule Scope3 reads delivery back on. Where a
* stale setting had us also asking your endpoint to push daily report webhooks, we
* no longer send that request. Nothing changes for buys whose products declare
* their own reporting capabilities, and nothing changes about the delivery figures
* buyers see.

## 5.5.0 — July 30, 2026 at 9:42 PM UTC

* Sellers running an AdsWizz embedded sales agent can now list their ad-server advertisers through the storefront API. `GET /esa/{esaId}/advertisers` reads your roster live from AdsWizz and returns it whole, so finding the advertiser id your buys book against no longer means asking us to look it up for you.
* Applying that id as your source's default advertiser is not part of this release — that step is still Google Ad Manager-only. If you run AdsWizz, contact support to have your default advertiser set.
* Google Ad Manager sources are unchanged: a GAM network holds far more advertisers than is practical to read live, so it keeps listing from its synced cache via `GET /esa/{esaId}/gam/advertisers`.
* Buyer and Seller Setup now use the same clear checklist for going live.
* For buyers, Setup separates the three account-level requirements—confirm the company operating the account, accept the terms, and keep the account in good standing—from the requirements of each seller or buying platform. This makes it clear whether the buyer can transact anywhere and what remains before a specific destination can accept a buy.
* The company website used for buying is now separate from the organization used for sign-in. An account admin can confirm or change it without changing SSO, invitations, memberships, or advertiser brands. When trusted company records show that a brand belongs to the verified parent organization, Setup can recognize that relationship; agencies and other operators can still verify their own domain directly.
* Connecting is free. Sellers that do not require credentials have no connection step. Other destinations show only the provider connection, account selection, advertiser mapping, or payment setup they actually require. Payment details are requested only when Interchange processes the transaction.
* For sellers, the same activation language and company control now appear in Storefront Setup. Payout work has its own **Get paid** track, and missing bank details are identified as a payment delay rather than a storefront-launch blocker. Inventory and settlement-currency requirements remain separate.
* ### Who notices what
* **SMB and first-time buyers:** Setup provides one next step and explains “can buy now” without protocol language.
* **Enterprise brand and agency buyers:** company identity and account standing apply once across every seller, while each destination says who controls the account and who bills it.
* **Builders and power buyers:** account status now distinguishes platform readiness from destination readiness, with the same result available in chat and the Setup page.
* **Sellers and storefront operators:** Storefront Setup uses the shared go-live checklist, while payout tasks remain visible without blocking launch.
* ### Monetization
* No new charge is introduced. Connecting a seller or platform, finding accounts, matching an advertiser, and viewing existing campaigns remain free. Existing media costs and payment requirements are unchanged.
* ### Measurement and acceptance
* Acceptance covers sellers that need no credentials, destinations whose payments are processed by Interchange, choosing the correct advertising account, cases where company information cannot be found, verified parent-company and brand relationships, and independently verified agencies. It also covers matching status results across chat and Setup, production widget builds, and browser screenshots of missing-company, known-domain, unknown-domain, and ready-to-buy states. Activation measurement uses the platform's readiness result rather than reconstructing readiness from clicks.
* The launch dashboard will use the existing `activation:choice_shown`, `activation:door_chosen`, and `activation:choice_deferred` events for entry-path adoption, plus successful and failed `get_buyer_readiness` requests for setup reliability. Readiness responses provide the outcome measures: `platformReady`, `canBuyAnywhere`, destination totals, and the counts for ready, connection-needed, and blocked destinations. During alpha we will review the choice-to-door conversion rate, readiness-request error rate, platform-ready rate, and can-buy-anywhere rate by entry path each week.
* ### Rollout and rollback
* The feature remains behind `alpha-opt-in`. Start with internal organizations and invited alpha buyers. Expand the cohort only after the staging and production browser flows are green for open signup, invitation bypass, known domains, unknown domains, and a ready-to-buy account; after at least 20 admitted buyer setup sessions have produced a readiness result; and while readiness requests remain below 1% server errors with no Sev-1 or Sev-2 activation incident for seven consecutive days. A wider rollout additionally requires a reviewed weekly dashboard for the named adoption and outcome measures above.
* The kill switch is the existing `alpha-opt-in` cohort. Stop expansion immediately on a threshold breach. Remove the affected cohort entries to return those buyers to the waitlist gate, while retaining only the internal test organizations needed to diagnose the failure. Organization-scoped invitations remain the controlled admission path during recovery. Re-enable a cohort only after the failing browser scenario or readiness request has a regression test and the seven-day reliability window restarts.
* Storefront administrators can now update account routing across inventory sources in
* one reviewed change instead of editing each GAM, FreeWheel, or other source mapping
* one by one. In the Buyer Account Mapping Page, choose \*\*Import buyer account
* mappings\*\*, upload `source_account_bindings.csv`, review every create, update, and
* archive, then commit the accepted change atomically.
* No migration or immediate action is required; use the import when you want to replace
* manual source-by-source maintenance. Manual mappings and mappings owned by another
* feed remain protected. This first release imports only `source_account_bindings.csv`;
* it does not import `seller_accounts.csv` or `account_mappings.csv`, or create CRM
* records, relationships, grants, inventory sources, or native source accounts.
* Campaign search now returns `nextCursor` so agents can paginate past the first page. `save_campaign` warns on silent no-ops (brief/flight null clears, create-path flags). `save_media_buy` now validates budget and flight upfront instead of silently discarding them, and reports phase in V3 vocabulary. Error codes unified across the buyer surface.
* Widgets now fit the window they open in instead of guessing at it. Twelve surfaces — the demand inbox, seller dashboard, seller setup, release notes, property roster, activity, inventory components, source diagnostics, modular and third-party sources, buyer discounts, and the avails upload — capped themselves at a fixed height that overflowed shorter screens, leaving the bottom of the widget out of reach. Each now takes exactly the height your window allows, keeps its summary band pinned while the detail scrolls beneath it, and uses the full width of the pane. The widget bar also no longer repeats the title the widget already shows.
* Creative sync now correctly reports `error` when per-creative results from the storefront source all fail. Previously, `sync_creatives` reported `synced` at the top level even when every creative was rejected by the downstream agent, masking failures and making retries appear to succeed. Additionally, non-object asset values (null, string, number) inside a creative's `assets` map are now rejected before the payload leaves the platform, surfacing an actionable error message instead of a cryptic downstream validation failure.
* **Sellers:** You can now stop accepting new business without interrupting existing delivery or losing an approved buy that has not reached a source. In Storefront settings, choose **Hold new business**; API integrations can set `isPaused: true` through the v2 Storefront API. This removes products from buyer discovery and blocks new buys and buyer edits. Approved unsent buys remain queued and forward automatically when intake resumes, while storefront preview remains available. No migration is required. Use campaign controls if you need to stop live delivery.
* **Buyers:** When a seller holds new business, its products are unavailable in discovery and you cannot create or edit a media buy with that storefront. An already-approved buy that has not reached a source remains queued and forwards automatically when the seller resumes intake, so you do not need to resubmit it. Campaigns already delivering continue unchanged. Buys that failed before this release remain unchanged.
* TikTok audience and signal reads no longer fail on accounts where TikTok's reported audience count includes entries its list API does not return.
* Agents connected to the v3 MCP storefront preview can now read and manage
* storefront settings, exact advertiser relationships, signals, and approval
* work items with dedicated tools. Existing settings do not change on
* their own, so sellers only need to act when they want an agent to update this
* information. Buyers continue to see the capabilities and selling terms a
* seller publishes; they do not see the seller's setup records or get a new
* buying workflow from this preview.

## 5.4.0 — July 30, 2026 at 6:31 PM UTC

* If you maintain a custom buyer or storefront API/MCP client, or a sales-agent
* integration, regenerate it against the current schema and adopt the canonical
* fields below. This is the only customer action required.
* Product discovery, creative sync, and media-buy creation now use the same
* URL-free AdCP format contract across buyer and seller surfaces. Declare product
* options with `format_options`, select creative formats with `format_kind`,
* select package formats with `format_option_refs`, and read product cards from
* their inline fields.
* A connection explicitly negotiated onto the legacy protocol can continue
* unchanged. At that compatibility boundary, Interchange continues to accept and
* project legacy `{agent_url, id}` references and media-buy `format_ids`;
* connections using the current schema must use the canonical fields above.
* Interchange chat, the Interchange UI, and built-in adapter connections adopt
* the contract automatically. Their setup and workflows do not change.
* Media buys now keep billing responsibility consistent from creation through
* execution, so fee and ledger reporting continue to match the seller account
* even if account mappings change later. Buyers and sellers do not need to change
* their workflows, and historical ledger entries are unchanged.
* Audience discovery on TikTok and Snap storefront connections now returns the account's full customer-list audience inventory, including audiences created outside Scope3 — previously only platform-created audiences were visible.

## 5.3.1 — July 30, 2026 at 3:45 PM UTC

* Fix campaign pacing under-delivering on mid-campaign executes.
* Campaign fallback pacing now distributes a buy's budget only across periods that are still active at execution time. Previously, a buy executed mid-campaign had most of its budget silently assigned to elapsed historical periods and dropped before being sent to the seller.

## 5.3.0 — July 30, 2026 at 3:11 PM UTC

* Your agent can now create and update campaigns and media buys with `save_campaign` and `save_media_buy`; campaigns and media buys are also now readable through the `search` and `get` tools. When updating a campaign, pass `expectedRevision` from your last read to prevent overwriting concurrent changes. Launching a campaign to active still requires human confirmation, and seller acceptance of media buys is not yet available through the agent surface.
* Creative operations (get, update, delete, bulk-update) now recognize creatives attached to a campaign via all three membership paths -- the original ownership field, `campaign_creative_mapping`, and `creative_manifest_campaign`. Previously, creatives linked via the assignment API were invisible to get and update.
* Users with multiple Interchange accounts can now log in via magic code and password as well as the standard OAuth flow. The previous fix only covered the OAuth code exchange path.
* When running a source test campaign, Murph now correctly reports that discovery was blocked (for example, because the agent doesn't have sandbox mode enabled) rather than saying the source returned 0 products. The two situations require different follow-up actions: a sandbox capability gap needs the agent updated; zero products from a working discovery means checking the agent's inventory or advertiser targeting.
* Sellers can now self-serve their Prebid.js `orgId` — the value they paste into the `scope3RtdProvider` real-time data module's config — by asking Murph "what's my Prebid.js orgId?" (or any variation of the same question). Previously this required an issued credential from the Scope3 team; now Murph returns the exact URL directly from your storefront so you can drop it into `pbjs.setConfig(...)` and continue with the install. Prebid Server's `auth_key` remains issued by Scope3 — the self-serve reveal covers Prebid.js only.

## 5.2.0 — July 30, 2026 at 12:34 PM UTC

* Creative files uploaded from Creative Assets now keep the social ad format you
* selected all the way to the connected ad account. An upload stops with a clear
* error if the social network needs information that is missing or does not
* confirm the creative and package assignment; it no longer appears successful
* with an empty or unusable ad. Meta image uploads use your authorized Page,
* default to **Learn more**, and do not require headline or body copy.
* When you attach a creative to a campaign in chat, the success summary shows
* which ad placements are ready only after the seller confirms the creative is
* available for delivery. A rejected or still-pending assignment returns a clear,
* retryable error instead of a success summary. Pending approval details also
* name the affected creative files.
* Connected social platforms now offer only the creative formats they can create
* reliably. An unsupported format fails before anything changes in the connected
* ad account.
* No buyer setup changes are required.
* Seller impact: no operational workflow changes. Sellers keep the same catalog,
* approval policies, and package controls; the buyer now sees a success summary
* only after the seller's existing confirmation is received.
* You can paste a failing request into a support ask, headers and all. Bearer tokens, API keys, JWTs and cloud access keys are now replaced with `[REDACTED]` before the ask is stored, sent to the Scope3 team, or recorded in the audit trail — on every copy, not just some of them. Only the credential is replaced: your sentences, timestamps, ids and error text arrive exactly as written, because they are what makes the ask answerable. Nothing to change on your side, and it applies to every ask type. It recognises known credential shapes rather than every possible secret, so still rotate anything you think was exposed.

## 5.1.0 — July 30, 2026 at 11:41 AM UTC

* Connected Meta products now list verified Facebook and Instagram Feed, Stories,
* and Reels placements. Buyers and agencies can select the product's
* publisher-domain placement references when creating or updating a media buy;
* leaving `placements` unspecified keeps Advantage+ and all existing calls
* unchanged.
* API buyers can request package performance by setting
* `reporting_dimensions.placement`; directed-campaign REST callers use
* `placementBreakdown=true`. Spotify reports only publisher-contained `MUSIC`
* inventory. Spotify Audience Network podcast inventory, TikTok's
* cross-publisher bundle, and any placement without exact provider readback stay
* unpublished.
* No seller setup is required. This adds no charge and does not change product
* pricing or packaging.
* Editing a product through Murph is now a change rather than a rewrite. Ask it to
* rename a product or take one off sale and it sends just that, leaving everything
* it did not mention exactly as you set it — so an edit can no longer quietly drop a
* price, a channel or a targeting rule. The approval step now shows you exactly
* which fields are changing, rather than a whole rebuilt product to check line by
* line.
* Paused media buys now retain the provider's authoritative revision and action metadata, and live adapter checks verify that nested region requests fail closed before any provider mutation.
* Provider capability coverage for audiences, signals, and event sources on connected ad platform accounts is now documented. The new reference page shows, per platform, which reads return the account's complete inventory and which are partial (bound-only), synthesized, or platform-managed — including the TikTok and Snap audience caveat, where only audiences created through Scope3 are visible.
* Controlled Meta products now preserve exact age and gender targeting through
* launch while rejecting any targeting that no longer matches the selected
* product.
* In **Buyer Account Mapping**, sellers can now review one relationship per
* operator and brand, see its private coverage across active inventory sources,
* and search or paginate the account roster. Open it with `get_seller_accounts`.
* The Page is read-only and does not change existing account routing.
* Download the normalized source-binding CSV template, your current healthy
* bindings, and the active native accounts reported beneath each
* source. Equal native IDs in different sources remain separate, CRM is optional,
* and no source topology or native ID is shown to buyers. CSV upload and commit are
* not enabled yet; imports will require a signed preview and one atomic,
* version-checked commit rather than applying rows partially.

## 5.0.0 — July 30, 2026 at 9:54 AM UTC

* Spotify storefront connections now support event-source discovery (`sync_event_sources`); Amazon's `get_signals` no longer returns a demo placeholder — Amazon signal enumeration is unavailable until AMC integration ships.
* Ask for one exact adult age range in a product-discovery brief—for example, “ages 21–35”—and storefronts now offer products only when the connected platform can execute those exact bounds. The selected range is preserved through media-buy creation and readback; on Meta, people whose age is unknown are excluded unless you explicitly include them. Meta and Spotify accept continuous ranges within their limits. Snap, TikTok, and Pinterest accept only exact combinations of their native age buckets, while other adapters do not support age targeting yet. Open-ended, disjoint, exclusionary, ambiguous, under-18, or unsupported requests are not widened or guessed: an adapter that cannot represent the request contributes no matching product. Existing supported briefs require no changes; if discovery returns no matching product, rewrite the brief as one explicit supported range. This applies to age carried by the selected product, not `targeting_overlay` or changes to an existing media buy.
* If you call seller MCP tools directly, replace `get_business_profile` with
* `get_media_kit`; replace `get_merchandising_rules` and `get_selling_terms` with
* `get_playbook`; and replace `get_acceptance_policy` with
* `get_business_rules`. Your saved configuration and version history are
* unchanged.
* Seller configuration now uses three matching names: **Media Kit** for what
* buyers see, **Playbook** for how you package and price, and **Business Rules**
* for what you accept and when a person reviews it.
* Fixed execute\_campaign failing with "no pricing options" for wholesale products stored under account-scoped catalog keys. The reconcile path now reads all catalog account keys for the storefront instead of only the public partition, matching the forward path's behavior.

## 4.150.0 — July 30, 2026 at 8:30 AM UTC

* Buyers can now select supported performance goals on TikTok, Snap, Pinterest,
* LinkedIn, Google Ads, and Spotify packages. Product discovery states each
* platform's exact goal capabilities, creation fails before spending when a goal
* cannot be applied, and creation verifies the provider's stored goal before the
* buy can proceed. Reddit and Amazon reject optimization-goal requests until
* their provider identity and readback gaps are implemented.
* Buyer agents can now call `get_account_resources` on a platform-composed
* storefront to list the audiences, signals, and event sources attached to a
* linked account. The tool returns live, cursor-paginated, opaque references with
* per-source capability and coverage metadata. It does not return audience
* membership, event payloads, setup secrets, private source IDs, or source-native
* account IDs. Check `partial`, `truncated`, and each source's coverage before
* treating the response as complete.
* **Who this is for:** Buyer agents are the direct user; enterprise brand and
* agency buyers receive the same account-scoped result through their agent. The
* seller impact is disclosure of opaque capability, coverage, freshness, and
* error state for sources already attached to an active buyer grant. Sellers get
* no new workflow, and buyers still cannot see native source topology or account
* IDs.
* **Packaging and rollout:** This is included in existing sales-agent connections
* with no new billable surface or pricing change. `gate: none` is intentional for
* this atomic, read-only launch because the existing authenticated principal,
* active account grant, and bound-source relationship are structural gates. The
* kill switch is removal of the custom-tool and adapter signal registrations;
* broader provider coverage requires authoritative account-scoped enumeration and
* acceptable partial/error rates.
* **Measurement:** Standard MCP calls to `get_account_resources` are the adoption
* event. Monitor calling buyer principals and linked accounts, successful grant
* resolution, complete versus partial responses, unavailable-source and
* truncation rates, resource counts, and cursor completion.
* When updated Terms of Service appear in Interchange and require a new acceptance, eligible organization administrators can review them immediately or choose **Review later** until the displayed deadline. After that deadline, other members see that an administrator needs to act. Negotiated pricing stays attached when the update is a minor version.
* Nothing changes for the current v3.0 terms, and no action is needed until an updated version is published. Patch revisions that do not materially change the terms continue with notice and continued use; material minor and major revisions require an administrator's affirmative acceptance. If agreement status cannot be verified, API and agent actions pause with a retryable error instead of proceeding without confirmed terms.

## 4.149.0 — July 30, 2026 at 3:27 AM UTC

* The Demand inbox now reads as an honest scoreboard. A figure the platform
* couldn't compute says why — "Nothing decided yet", "Nothing booked yet" — instead
* of showing a bare "N/A" or, worse, a zero that looks like a real result. A lost
* brief is presented as history rather than an error, and "agent-led" is no longer
* coloured as the better outcome than "human-led". The scoreboard now stays pinned
* at the top while the ledger scrolls beneath it, so a long list never pushes your
* numbers off the screen, and the ledger fits a phone-width window without
* scrolling sideways. Filtering to a buyer with no briefs now says "No matches for
* this filter" and offers a one-click reset, rather than showing a blank table. You
* can refresh without leaving the page; if the refresh fails, your last figures stay
* on screen with a note instead of the page going blank. Dates, currencies and
* counts follow your language and region, and the screen's own labels are now
* translated.

## 4.148.0 — July 30, 2026 at 3:10 AM UTC

* Region targeting now refuses nested ISO subdivisions on Meta, Google Ads, Snap,
* TikTok, LinkedIn, and Spotify because those provider searches do not return
* enough hierarchy to distinguish a child from a larger same-named parent.
* Previously, some French département codes and other nested subdivisions could
* silently resolve to a larger region, causing broader delivery than requested.
* Top-level state and region targeting, including Meta's translated provider
* names, continues to work as before. Pinterest, Reddit, and Universal Ads
* continue to accept nested subdivisions because their provider paths do not
* infer identity from a provider name.
* Merchandising decisions now quarantine inventory bundles that the current creative-format contract cannot execute safely and show a clear seller-readable explanation instead of raw validation details. The Simulator also identifies its starter fixture as a Display brief tested against the seller's current inventory, so non-Display sellers know to use a channel-matched brief.
* Release notes now says what each update is and who it is for. Every entry
* carries how significant it is (Fix, Improvement, Feature, or Headline), whether
* the capability is still Alpha or Beta or is being retired, and why it is in your
* list — **Changed for you** and **In your setup** only when Interchange verified
* your account, and **For all accounts** when the change applies to everyone in
* your role, so a general change never reads as one about you. The feed also
* states what **New** means and what clears it: opening **For you** moves your
* read position, and browsing Explore or Recent updates does not.
* The page itself now fits the window instead of growing without limit — the
* count of what changed for you stays visible while the feed scrolls beneath it —
* and dates read in your own locale and timezone. An empty **For you** points you
* to Explore rather than dead-ending, a failed refresh keeps the updates you were
* already reading instead of blanking the page, and every update can be sent to
* Murph for an explanation, including ones with no linked feature page.
* Buyer agents can now resolve a brand from its domain before creating an advertiser. Existing advertiser creation and REST integrations continue to work as before, with no setup changes required.
* Seller agents can now read the active account, selectable accounts, delivery and margin reports, and safe modular-inventory product and capability data by stable operation name. Booking, configuration, work-item detail, and credential changes remain in their confirmation-gated tasks or trusted operator screens.

## 4.147.0 — July 30, 2026 at 1:50 AM UTC

* Eligible connected ad accounts can now find platform-managed conversion
* outcomes in `sync_event_sources` and use them in compatible media-buy
* optimization goals without adding a buyer pixel or server event. No setup
* change is required: eligible sources appear automatically for the selected
* account, and existing calls behave as before unless a built-in source is
* selected.
* Media teams can optimize eligible Meta campaigns for shop purchases, Messenger
* contacts, or Instant Form leads. Amazon profiles and Google Ads accounts can
* also discover supported platform-managed outcomes from their account data. For
* API and agent builders, Meta verifies the native optimization goal, destination,
* and promoted object before returning a paused media buy. Built-in sources are
* discovery-only: attempts to change them fail per source, events cannot be logged
* to them, and Scope3 does not invent health scores for them.
* Seller agents using the v3 surface can now reach every supported field, including wholesale-product status filters. Misspelled fields return a correctable validation error instead of being silently dropped. No action is required.
* Campaign teams can now include or suppress Meta Custom and Lookalike Audiences with AdCP's native `audience_include` and `audience_exclude` fields. Create, update, and tracked media-buy reads return the audience IDs confirmed by Meta. No change is needed for Meta packages that do not target these audiences.
* API integrators that send Meta audience IDs through the legacy `targeting_overlay.signals` extension must move them to `targeting_overlay.audience_include`; the old field is no longer accepted.

## 4.146.0 — July 29, 2026 at 10:41 PM UTC

* Operator-domain verification now only accepts brand records backed by domain control. A record you published at your own domain (`/.well-known/brand.json`) or registered yourself through the AAO registry counts as evidence; a record contributed about your domain by someone else does not, because it does not show that you asserted the relationship. This tightens who can claim to operate under a domain.
* Verification also no longer consults the AAO brand-hierarchy endpoint, which was retired in the move to AdCP v3. While it was unavailable, that check could not complete, so an alias or rebrand operator domain that we could not confirm is now reported as "Scope3 could not complete this check" rather than as missing evidence — you will not be told to fix or republish a declaration that is already correct. Confirming these relationships against the AdCP v3 model is in progress.

## 4.145.1 — July 29, 2026 at 8:09 PM UTC

* Bulk-update `format_id` now applies correctly. Previously, setting `format_id` in a bulk-update request always silently failed with a validation error because the required internal flag was not threaded through the bulk-apply path.
* Fix two bugs blocking TMB Chime campaign execution.
* Cancel no longer reverts: `cancelMediaBuy` now stamps both `pending` and `approved` rows in `storefront_pending_media_buys` so an operator approval that arrives after the buyer cancels cannot resurface a dead buy. A new guard in `updateMediaBuyFromResponse` blocks any incoming status update (including authoritative v3) from reverting a buyer-canceled buy out of CANCELED.
* Execute no longer 500s: the `completeDiscoverySession` call in `executeCampaign` now handles "not found or not accessible" and "lapsed" session errors the same way it handles "already completed" -- by skipping cleanly instead of propagating a 500.
* `upgradeManifest` now validates the resolved format\_kind through the same canonical identity check as creative creation. Upgrade requests where the format\_kind is inconsistent with the creative's existing assets return a validation error.

## 4.145.0 — July 29, 2026 at 6:35 PM UTC

* Sellers can now disable and re-enable inventory sources directly from the source diagnostics setup panel, without needing to contact support or run SQL queries. The disable action includes a confirmation step to prevent accidental changes.
* Creative assignment now enforces advertiser ownership: a creative belonging to one advertiser can no longer be attached to a campaign belonging to a different advertiser within the same account. The assign endpoint returns 422 when advertiser IDs conflict.
* Collection fan-out skips cross-advertiser members and returns an `ownership_excluded` count in the response — if that count is non-zero, promote the skipped creatives to the correct advertiser before retrying. Sellers are not directly affected by this change.
* Fixed intermittent REFERENCE\_NOT\_FOUND errors when discovering products from pubX. The SDK's async polling was making account-less requests to sources that require account context on all calls.
* Meta campaign data stays reachable after an access-token refresh. Meta
* partitioned its stored adapter state — targeting provenance and account
* pagination — using a key derived from the access token whenever host credential
* identity was unavailable. Refreshing that token changed the key, so anything
* recorded under the previous token became unreachable and a later targeting
* update could fail to find its own history.
* The partition now comes from durable account identity, which a token refresh
* does not change. Snap, TikTok, Spotify, Pinterest, Reddit and LinkedIn already
* work this way; Meta was the last one that did not.

## 4.144.0 — July 29, 2026 at 4:58 PM UTC

* Campaign reads can now bypass cached media-buy state when a buyer needs to
* confirm a lifecycle change immediately. This prevents a successful pause,
* update, or cancellation from briefly appearing unchanged.
* Users belonging to multiple WorkOS organizations can now log in. Previously, if a user was a member of more than one org, WorkOS returned an organization selection error that blocked login entirely.
* Ask Murph what you have open and you get one list of support, product, and supply asks, each with a status that moves as the work does. A product ask now follows the engineering work it is attached to; a supply ask follows that seller and channel through onboarding. Before this, a product ask read "Tracked for product review" from the day you filed it until the row dropped off the list; that is now just its starting state, and it moves from there. Every ask carries one status from a closed set (`received`, `accepted`, `in_progress`, `done`, `closed`) plus a `statusLabel` and `statusDescription` written for you. Internal workflow state names and ticket references never appear in a customer response, and a state we cannot describe honestly stays at `received`.
* `GET /api/v2/asks` is now documented in the buyer and storefront API references, so your own agent can read the same list. It is read-only, takes no customer parameter, resolves your account from the API key you call with, and returns up to 25 asks per call alongside `hasMore`. If a source cannot be read, the response names it in `unavailableKinds` instead of returning an empty list that would read as "nothing open". The two undocumented reads it replaces, `/api/v2/customer-picture/requests` and `/api/v2/customer-picture/ask-status`, now return 404 — point any call you have at `GET /api/v2/asks`.
* Which statuses a kind reaches differs, and the read says so rather than implying otherwise: support and supply asks both keep a short recently-resolved window, so a supply ask shows up as ready before it ages out instead of quietly disappearing — dated from the marketplace evidence that made it ready, not from when your request row was last touched, so a seller that went live yesterday shows as ready even on an old request. Two gaps are named rather than papered over: a product ask leaves the list once the work ships or is dropped, and a cancelled supply ask leaves the list too, because we have no reliable record of when it was cancelled and would rather drop it than show you a made-up date. Supply asks are the sellers and channels you asked us to bring into the marketplace, so you see them only if you have filed one. Support asks filed before this change may not yet show a next-update date or a still-blocked confirmation. Full details: [Ask Murph → Your requests and support](/v2/setup/ask-murph).

## 4.142.0 — July 29, 2026 at 1:22 PM UTC

* Reading an ad-server-backed product now reports its pricing the way buyers see it. Uploaded wholesale pricing is applied when your catalog refreshes, but a product read went straight to your ad server, which never learns about that upload — so a product your feed had priced still came back as "pricing unresolved", permanently on any ad server that doesn't report pricing. A product you priced with a fixed rate reads as priced too. Products your feed hasn't priced are unchanged: still unresolved, with the reason.
* Wholesale pricing uploads now accept CSV files that arrive as `text/plain`. Text editors, Slack, and some operating systems label a `.csv` attachment this way, and those uploads were previously rejected before reaching the parser even though the file was valid CSV.
* Creative asset URLs are now round-trip safe for filenames containing `%`, `?`, or `#`. Such filenames previously produced a URL that could not be resolved back to the stored asset.
* Changing one field on a wholesale product no longer means re-sending the whole
* product. `patch_esa_product` applies only the fields you name and leaves
* everything else exactly as it was, so renaming a product or flipping its status
* can no longer clear the prices, channels or targeting you never mentioned.
* `update_esa_product` still replaces the whole product for callers that hold a
* complete one.

## 4.141.0 — July 29, 2026 at 12:45 PM UTC

* The Campaigns page now shows filters by phase, handling, and search; a stats band with live/draft/blocked counts; per-campaign attention signals; and load-more pagination. Launching the Campaigns page from the agent also now scopes to an advertiser when one is active in the conversation.
* Fix brief-mismatch in inventory-source test campaign execution. The plan tool now includes the captured brief verbatim in its nextActions so Murph carries it to the execute call, and the execute tool description makes clear the brief must match the one used during planning. A different (or defaulted) brief causes discover\_products to return zero results and silently breaks execution.
* The connected-account subscription read now reports the tracked-presence sweep cursor: `lastPresenceSyncedAt`, `lastPresenceSyncStatus` (`SUCCESS`, `ERROR`, or `SKIPPED`), and a sanitized `lastPresenceSyncError`. An empty audience/event-source presence list is now distinguishable from a sweep that has not yet visited the account.
* Seller approval verdicts (approved/rejected) are no longer reset to pending on every creative re-sync when the creative content has not changed. Previously, each outbound sync overwrote the stored verdict regardless of whether the adapter reported any content change.
* Fixed an issue where retrying `execute_campaign` on a cross-currency media buy always failed with "This media\_buy\_id is already bound to a different immutable FX rate." The FX lock's `rate_as_of_date` column (PostgreSQL `DATE`) was returned by the driver as a JavaScript `Date` object, but compared with `===` — which checks reference identity, not value equality. Two separate reads of the same date always failed the comparison.
* Fixed an issue where reconnecting a Meta storefront connection via Settings → Connections left the connection in an error state. The OAuth flow completed successfully but the credential status remained broken on subsequent reads.
* Fix storefront forwards silently failing after ESA v1.30.0 enforcement. When forwarding a media buy to a canonical managed sales agent, legacy `format_ids` are now stripped from the outbound packages before dispatch. The canonical `format_kind`/`params` selector is preserved. Legacy AGENT sources are unaffected.
* You can now change the geography of a running campaign on every social ad
* platform Scope3 connects: TikTok, Reddit, Pinterest, LinkedIn and Spotify join
* Meta and Snap. Previously these five refused every targeting change on
* `update_media_buy`, so the only way to correct a campaign's geography was to
* create a new media buy.
* Geography is declared state, not an edit. The regions you list are the regions
* that deliver, and a region you stop listing stops delivering. Send
* `geo_regions: []` — or omit `geo_regions` while supplying `geo_countries` — to
* return a campaign to country-level delivery. Countries you don't restate carry
* forward, and a country with no region of its own is untouched. Omitting
* `targeting_overlay` entirely leaves targeting alone, so budget and date changes
* don't require restating geography.
* Unresolvable region codes are refused before the platform is called, so a failed
* targeting change never leaves a campaign half-updated. Dimensions other than
* geography are still refused on update with `UNSUPPORTED_TARGETING_DIMENSION`.
* One Spotify correction worth checking your integration against: a Spotify ad set
* carries a single country, and a request naming more than one used to deliver to
* the first and discard the rest without telling you. That request is now refused
* with a 400 naming the countries it received. If you send multiple countries to
* Spotify today you are already only delivering to one of them — split them across
* packages to reach all of them.
* See the connect guide for the current per-platform table.
* Google Ads now applies `geo_countries` and `geo_regions` on `create_media_buy`.
* Country and region codes resolve against Google's own location inventory at
* request time, so any ISO 3166-1 country or ISO 3166-2 subdivision Google
* supports is available rather than a fixed list.
* This closes a gap where Google Ads advertised four targeting dimensions through
* `get_adcp_capabilities` and applied none of them: a campaign you targeted at one
* country delivered everywhere, and nothing in the response said so. That silent
* failure was already stopped — Google began refusing targeting it could not
* apply — and geography now works rather than being refused.
* Two Google-specific behaviors to build against:
* Google targets geography at the campaign level, not per ad group, so every
* package in one Google media buy must declare the same geography. A buy whose
* packages disagree is refused with `INVALID_PACKAGE_MIX` before anything is
* created — use separate media buys for separate geographies.
* A region code that doesn't resolve to exactly one Google location, and a
* location lookup that fails, are both refused before any campaign is created.
* Nothing is half-built.
* `keyword_targets` and `negative_keywords` are still not applied on Google Ads
* and are still refused. Geography applies on create only; changing it on an
* existing Google buy is refused.
* One reporting limitation to plan around: Google delivery reports break geography
* down by country, so a campaign you target at a region reports against its
* country rather than the region. The targeting applies — you just can't yet see
* the region back in `get_media_buy_delivery`.
* Murph now says plainly when an approved action failed before anything could be written, while continuing to ask for state verification when a timeout or server error leaves the outcome uncertain.
* TMP eligibility on storefront forwards is now derived entirely from `Product.trusted_match.identity_match`. An additional internal enrollment step required behind the scenes on top of the product declaration has been removed.
* Sellers: no change in how you set up TMP — declaring `identity_match: true` on a product remains what enables it. Outbound line items on identity-matching products now carry the package-ID key-value automatically once the declaration lands, without waiting on an internal follow-up.
* A Terms of Service update within the same major version no longer asks you to re-accept. If your organization has accepted v3-0 and Scope3 publishes v3-1, you keep working — no prompt, no interruption. Only a new major version requires an admin to accept again.
* Two pieces of vocabulary now match the protocol and the API, so the docs and your agent use one word each.
* **Wholesale product** is now defined in the glossary: the product *you* author on a managed sales-agent source, told apart from a composed product (`cf_`, built to a brief at discovery) and from a third-party agent's passthrough products. "Create products from ad-server inventory" opens with that three-way distinction, and clarifies that a *component* is the raw ad-server material you select from, never something you author.
* **Signal** replaces "signal component" throughout the documentation. It is the same thing under one name — every API operation has always used `signal` (`create_signal`, `list_esa_signals`), and the prose had drifted. The raw material you author a signal *from* keeps its own name, **ad-server targeting**. Some in-product copy still says "signal component" and will follow.

## 4.140.1 — July 29, 2026 at 11:54 AM UTC

* Murph now names and requests every required signal field before creating a component, instead of returning an unnamed “Field required” error after validation.

## 4.140.0 — July 29, 2026 at 9:39 AM UTC

* With a linked storefront account, `get_media_buys` can now return media buys from each available inventory source the seller has explicitly mapped to that account. Discovered buys use stable storefront IDs and are tracked, read-only records; pass the same linked account and ID to `get_media_buy_delivery`. Calls without an account are unchanged, and sources without a native-account mapping are not included in account-wide discovery.
* Reviewing one buyer exchange is clearer and more honest. On a phone-width
* screen the allocated money no longer hides behind a sideways scroll — each
* product now lists its price and allocation on its own labelled line. A booked
* amount reads at full precision (£95,000, not £95K), so the number you quote is
* the number that was recorded. A lost exchange reads as history rather than an
* alarm, the pass timeline stays neutral because it is a record of time rather
* than status, and the letter grade now says "Grade" beside it. If the exchange
* fails to load you get a Retry instead of a dead end, and the error text is
* readable in dark mode. Dates, prices and budgets now follow your own locale and
* time zone, and the screen's labels are translated. Anything that was never
* captured still says so — "Not recorded", never a blank that could read as zero.
* Compare how your Merchandising Agent would answer the same brief under different configurations on the new Merchandising Simulator page — without changing anything live. A simulation starts from a scenario (a sample brief, one you wrote, or one a buyer sent you) and runs your baseline plus up to three variants — a different negotiation posture, price adjustment, rate card, or bundle rules — through the same engine that answers real briefs. Each card shows the products offered and their CPMs, and every variant states its delta against the baseline: how many products moved, exactly which ones dropped or joined, and the price change. When a variant produces no offer (an acceptance-policy decline, for example), its card says why. Run every variant with one action; results are saved, so you can come back to them any time. A simulation shows what your agent would offer, not how a buyer would respond, and it never changes your live configuration.
* Meta ad platform connections now automatically extend their access token before it expires. Previously, Meta tokens silently expired after 60 days and required a manual reconnect from Settings > Connections; the background credential health sweep now extends them in place, keeping delegated workflows running uninterrupted.
* A `create_media_buy` call that used to return 200 for a targeting dimension a
* platform doesn't apply may now return 400 — check your error handling for
* `UNSUPPORTED_TARGETING_DIMENSION`.
* Each ad platform applies only a handful of AdCP's 28 targeting dimensions. Until
* now, a dimension a platform didn't implement was accepted and silently dropped:
* the call succeeded and the campaign delivered without it, with nothing telling
* you the targeting never applied. If you set targeting that a platform didn't
* support, those campaigns reached a broader audience than you asked for, and the
* spend went with them. Those requests are now rejected before the platform is
* called, so no campaign is created.
* `get_adcp_capabilities` is also corrected. Some platforms had declared targeting
* they never implemented — Spotify's audience include/exclude, Amazon's
* `geo_countries`, and Google Ads' `geo_countries`, `geo_regions`,
* `keyword_targets`, and `negative_keywords`. `media_buy.execution.targeting` now
* lists only what a platform applies, so a platform you use may list fewer
* dimensions than before, or refuse a request that used to appear to succeed.
* Either way, that targeting was never reaching the platform.
* Changing targeting on an existing buy is separate and still narrower. Snap now
* supports geography changes on `update_media_buy` — previously it accepted them
* and silently discarded them — joining Meta. TikTok, Reddit, Spotify, Pinterest
* and LinkedIn continue to refuse any targeting change on update; create a new
* media buy instead. See the connect guide for the per-platform table.
* Pause, update, and cancel now keep using the connected ad account's delegated
* credentials after a buyer creates a campaign through an internal social-adapter
* storefront. This prevents lifecycle actions from incorrectly asking for a new
* OAuth authorization or losing the provider campaign while canceling it.
* Operator-domain verification now accepts owner-registered brand records as ownership evidence. If you registered your brand through the AAO registry API rather than publishing `/.well-known/brand.json` for the crawler to find, that record previously did not count toward verifying an alias or rebrand operator domain, even though records contributed by third parties did. Registering the record yourself is stronger evidence than a third-party contribution, and it is now treated that way.
* Brandfetch-enriched records are still refused: they describe a brand but assert nothing about who owns or operates a domain.

## 4.139.0 — July 29, 2026 at 2:41 AM UTC

* Product discovery no longer slows down as a storefront accumulates inventory sources. A storefront with hundreds of sources could previously exceed the discovery time limit and fail `get_products`; its catalog is now read in a fixed number of queries regardless of how many sources it has.
* Fix CANCELED campaigns displaying incorrectly as DRAFT in the Campaigns view.
* The button that adds a modular source now matches the task it opens. Seller Setup still said "Add feed-backed source" while the task it launches is called "Add a modular source" — the same mismatch in Portuguese and Japanese. The docs and Murph now use one name for these surfaces too.
* Several seller widgets now scroll within a fixed height instead of growing unbounded, so long content no longer cuts off or blocks what renders below it: Sales-agent health, Ad server source, Demo storefront, Avails commit, and Get ready to sell setup.
* Nothing changes for accounts that are already live. No existing contract can enter the state below.
* When Scope3 sets up a new organization on standard terms, an admin at that organization now accepts the Terms of Service. Scope3 provisions the account and no longer records acceptance on your behalf.
* Until an admin accepts, `get_billing_account` reports `plan.contractStatus: "awaiting_acceptance"` with a `nextAction` of type `ACCEPT_TOS`, and endpoints that require an active contract return 403. That action carries the route and tool that resolve it — `POST /api/v2/accept-tos` and `accept_tos` — so read it rather than hardcoding either. The endpoint is unchanged. In Interchange, the same acceptance appears as "Accept the platform terms" on Plan & Billing.
* Acceptance claims the contract Scope3 provisioned instead of creating a new one, so a rate card negotiated at setup stays in force once your admin accepts.
* Accounts that inherit their organization's contract cannot accept for themselves; `accept_tos` returns 403 for them. One admin on the organization accepts, and its accounts are unblocked, rather than transacting on terms nobody agreed to.
* If someone at your organization is set up but blocked, the person who needs to accept is an admin on the organization itself.
* Turning off review for creative submissions or media buys (setting `creativeApproval` or `mediaBuyApproval` to `auto`) now requires an explicit acknowledgement: pass `acknowledgeNoHumanReview: true` when calling `set_approval_settings` or `update_storefront`, or check the confirmation box on the Selling Terms Page. In `auto`, nobody reviews the item, and for media buys your Acceptance Policy is not consulted at all. Tightening back to `manual`, or saving a setting that is already `auto`, needs no confirmation.
* Buyers can continue creating and managing campaigns through the existing product discovery and media-buy APIs; no action is required for integrations already using those APIs. The never-enabled connected-account create, update, plan, and accept routes are removed and now reject requests, so any integration attempting to use them must move to the buyer APIs. Connected-account subscriptions remain available for read-only campaign mirroring, refresh, and delivery views. Seller storefront presentation and ranking are unchanged.
* Media buys running on a source that reports a day's delivery as a single total, rather than a day-by-day breakdown, now show that delivery in reporting. Previously it was discarded, so those buys reported no delivery at all even while they were serving.
* Delivery for a day that is still in progress is now included too, and refreshes as the day continues.
* Sellers see the same delivery reflected in their realized cost basis, which previously stayed empty for these sources.
* Storefront readiness now tells you why an operator domain is pending verification, and who has the next action. Previously every cause produced the same "pending verification" message, which listed all the possibilities and often said the blocker was waiting on Scope3 review even when the action was yours.
* You now see one of four specific outcomes: your account domain needs ownership approval before alias evidence is checked at all; your account has no registered domain yet; published AAO or brand.json evidence does not link your operator domain to your account domain; or Scope3's evidence check did not complete, in which case Scope3 owns the retry and no action is needed from you. Murph reports the same cause and owner as the readiness check rather than defaulting to "waiting on Scope3 review".
* A check that fails to complete is no longer reported as missing or invalid evidence, so you will not be sent to fix evidence that is already correct.

## 4.138.0 — July 28, 2026 at 9:02 PM UTC

* Buyer agents can keep their existing `get_products`, `create_media_buy`, and
* `update_media_buy` calls. When a request includes a linked storefront account,
* the storefront now routes each inventory source with only the account identifier
* the seller assigned to that source.
* Before an inventory source is contacted, the storefront confirms that the buyer
* grant is active and that the source has one current, unambiguous mapping. An
* inactive grant or a missing, ambiguous, or stale mapping fails closed for that
* source; buyer agents should continue handling standard AdCP errors.
* Sellers must repair an affected mapping before the buyer retries. This release
* does not add a seller setup screen, and it does not change pricing, billing,
* calls without a linked storefront account, or legacy natural-key accounts.
* Account-specific media-buy history, reporting, audiences, and event sources are
* not included in this release.
* Eligible buyers can now create an Interchange organization when buyer admission is open and choose whether to start in the app, build with the API, or connect an assistant. An organization invitation bypasses the public signup waitlist and joins the recipient to that specific organization; it is not a reusable or storefront-scoped admission link.
* Buyer admission remains controlled by the `alpha-opt-in` rollout. When admission is closed, brand-new advertiser signups continue to see the waitlist.
* The buyer-agent activation contract now also defines staged benchmark evidence and measurement for evaluation, customer claim, storefront-neutral transaction readiness, and the first governed buy.
* ### Who notices what
* **SMB and first-time buyers:** an admitted signup continues into organization creation and then shows one plain-language choice for where to begin. A closed signup still ends at the waitlist; no technical action is required.
* **Enterprise brand and agency buyers:** an organization-scoped invitation remains the governed way to join the intended organization without entering the public waitlist. It grants no access to any other organization or seller.
* **Builders and power buyers:** the starting choice names the app, API, and connected-assistant paths explicitly. Choosing one does not remove the other two.
* **Sellers:** not applicable. This changes buyer admission and the buyer's starting surface; it does not change seller ranking, storefront presentation, inventory labels, or seller setup.
* ### Monetization
* None in this slice. Creating a buyer organization and choosing a starting path does not select a paid plan, activate a billable feature, or change media settlement. Existing route-specific billing and any later account-activation pricing remain unchanged.
* ### Measurement and acceptance
* The four Chromium scenarios are the release acceptance gate: closed signup reaches the waitlist, open signup reaches verification, an organization invitation bypasses only the public waitlist, and an admitted buyer reaches the three-path starting choice. The UI emits `activation:choice_shown`, `activation:door_chosen`, and `activation:choice_deferred` as product-analytics projections.
* The server-owned KPI contract names `activation_started`, `buyer_signup_completed`, `activation_door_chosen`, `first_authenticated_call`, `customer_claimed`, `storefront_ready`, and `first_governed_buy`. Zero-touch activation requires `first_authenticated_call` with no `scope3_operator` intervention between it and `activation_started`; time-to-first-call is measured from `activation_started` for agent-first journeys or `buyer_signup_completed` for human-first journeys. These KPIs are not claimed from browser analytics alone: they become reportable only from the durable activation stream defined in [AI-2900](https://linear.app/scope3-projects/issue/AI-2900/open-byoa-buyer-admission-zero-touch-signup-to-first-api-call).
* You can run each saved Simulator alternative against the seller settings captured with the scenario, then compare the resulting decisions without affecting buyers or live analytics. Every attempt remains available for review, with up to 25 attempts per alternative and 100 per scenario. No action is required in your live setup.
* Fix multi-size image package format IDs sending as `display_image:None×None` on creative update and re-sync paths. The update path now resolves the correct sized format ID (e.g. `display_970x250_image`) using manifest asset dimensions, matching the behavior on initial execution.
* Setting or rotating a sales-agent source's credentials is clearer and safer:
* credential fields stay masked and no longer trigger browser autofill or
* password-manager save prompts, replacing an existing credential says so up front
* (and never shows the old value), and the "credentials saved" confirmation is now
* legible in dark mode. Nothing to change on your side.
* Managing your storefront's buyers is clearer and safer. Disabling an invite
* link now asks you to confirm and tells you exactly what happens — buyers who
* already joined keep their access, and anyone still holding the old link can no
* longer use it. Minting, copying, and disabling a link show progress while they
* run and confirm when they're done, so you always see the result. Buyer statuses
* read in plain traffic-light color (a suspended buyer is no longer flagged like
* an error), and when you have no buyers yet the screen coaches you to share your
* invite link instead of showing an empty table.
* `agentPersonality` on your business profile is deprecated. An agent does not have a personality of its own — the voice buyers hear is your **brand's** voice, read from your brand manifest's `tone` alongside your logo, colours and tagline. Nothing ever consumed the field, so nothing changes in how your storefront sounds; it stays writable only so you can clear an old value, and we have stopped showing it in examples.
* Your pricing facts now accept the AdCP pricing models — `cpm`, `vcpm`, `cpc`, `cpcv`, `cpv`, `cpp`, `cpa`, `flat_rate`, `time` — and nothing else, and the **Selling Terms** page offers them as a list instead of a free-text box. Previously it took any text: you could type a shape we cannot transact, it looked saved, and everything downstream quietly ignored it. If your price list has a shape that isn't in that set — share of voice, a day-part premium — that is worth telling us rather than working around, because it means we cannot yet model something you sell. Nothing you have already saved is affected, and `cpm` remains the default when you don't say.
* There is also a new page explaining **merchandising** end to end: the four surfaces that steer how your storefront sells — selling terms, approval settings, acceptance policy, and merchandising rules — which fact each one owns, why a rules version that restates a price is rejected, and what actually changes the moment you save. It spells out the two things sellers most often conflate: your acceptance policy says *what* is acceptable, your approval setting says *whether a human reviews*, and in `auto` mode the policy is not consulted at all.
* A modular inventory source now shows its pipeline: every lifecycle stage in the order a booking moves through them, whether each one runs automatically or waits for a person, how many tasks are open on it, and when the module behind it was last checked. Stages nothing on your source handles are listed too, saying which gap they are — a stage with no module of the right kind reads differently from one whose module doesn't cover it, because the fix is different. This replaces the separate readiness and modules panels, which between them said the same thing twice and never said how a stage actually works.
* Webhook URLs must now be directly reachable public HTTPS endpoints. Sellers
* registering partner-agent URLs and buyers configuring storefront callbacks
* should update any URL that uses HTTP, resolves privately, or redirects.
* Sellers receive a validation error when registering an incompatible URL, and
* unsafe buyer callback destinations are not called. Nothing changes for existing
* public HTTPS endpoints.

## 4.137.0 — July 28, 2026 at 6:30 PM UTC

* You can save a buyer brief and up to three private merchandising alternatives without changing how your live agent sells. Simulator work stays out of live brief history, analytics, learning, and commercial results. Nothing changes on your side until you choose to create a scenario.
* Your Property Roster now holds every property your publishers declare, and answers at the level you ask at.
* Large networks were silently capped at 5,000 properties per domain. A domain declaring 6,843 sites kept 5,000, the rest were never recorded, and asking your agent whether a site was covered could come back "no" for a site you do sell. Every declared property and collection is now stored, however many there are. Each domain also carries `propertyCount` and `collectionCount` — how many it actually has, which can exceed what a single response returns — and the response carries a `truncated` object naming any part it left out. `totals` describes your storefront rather than the response, so if you compared the resolved-property count on your publisher list against your roster and the numbers disagreed, they now agree.
* Every property carries its own `authorization`. Read `grain` alongside `status`: a negative is definite, because a publisher domain that does not authorize your agent authorizes nothing beneath it; a positive is inherited from the domain rather than proven against the exact selector the publisher bound your agent to. A property you declared yourself, or one under a domain whose last check did not complete, reads `unknown` rather than claiming to be sellable.
* A domain that serves something unreadable at `/.well-known/adagents.json` now says so instead of reporting that no file exists. `adagentsStatus` gains `invalid` — a document is published there and is not a usable `adagents.json`, commonly an HTML page or a redirect. `no_adagents` now means only what it says. The remediation differs: fix the file you have, rather than publish a second one.
* Property key-values are reachable from your agent. `get_property_mappings` returns the current bindings and `replace_property_mappings` replaces them; preview first with `params: { dry_run: "true" }` and a body of just `{ mappings }`, and the preview reports which rows mapped, which did not and why, and whether each key-value and ad-server selector exists in your ad server.
* Finally, a storefront that sells through a platform account connection is no longer told to publish an `adagents.json`. Those storefronts get selling rights from the connection, no `adagents.json` will ever resolve, and the roster, readiness checklist and your agent now all say the authorization verdict does not apply rather than showing a permanent failure.
* Audience-targeted buys forwarded to a Scope3-hosted sales agent now carry the package-ID key-value on the ad server line item. Previously the key-value was omitted for these sources, so the line item was less restrictive than the campaign's audience targeting intended and could serve on ad requests carrying no identity-match signal.
* Buyers: audience-targeted campaigns on these sources now deliver only against the audience you specified.
* Sellers: for products you declare as identity-matching, line items created on your ad server now carry the package key-value and target more selectively than before. Expect tighter, better-qualified delivery on those line items.
* Your saved Simulator scenario now uses the same selling logic as live demand while keeping the captured brief, inventory, rules, and pricing frozen. Existing scenarios need no action and still cannot change live seller settings.
* The three source surfaces now use the name the documentation already uses: a modular inventory source. They previously said "feed-backed source," which named a source after one of its modules — a modular source can just as easily carry an ad-server or human module, and every one already has a booking ledger alongside its avails feed. Nothing about how a source works has changed: the workspace, the add-source task, and the avails upload all behave exactly as before.
* Managed ad-server inventory now preserves canonical creative format details through order creation, preventing valid fixed-size image packages from being rejected by a lossy legacy ID. Scope3's buyer path is already migrated, so sellers do not need to change their ad-server setup and buyers do not need to change how they create media buys. FreeWheel capability checks also resume automatically after vendor permissions recover, including before the first media buy.
* Approving a wholesale pricing upload now actually commits it. Previously, if you attached your pricing file and then approved the upload on a later message — the normal way an approval works — the commit could not read the attached file back and stored nothing, while the retry reported the upload as complete. Sellers who uploaded the same feed repeatedly were told each time that it was live when no rows had been saved. Approved uploads now read the file from where it was stored when you attached it, so the commit lands regardless of how many messages passed between attaching and approving. If the file genuinely cannot be read, the upload now says so and asks you to re-attach it rather than reporting success.
* More generally, any action that needs your approval no longer claims to have happened when it failed. An approved action that errors is now reported as not done, so you are asked to review and approve it again instead of being told a change was saved that never was. A successful approved action is still applied only once.

## 4.136.0 — July 28, 2026 at 2:39 PM UTC

* EUR buyers can now add products from USD-priced adapter storefronts (Meta Ads, Google Ads) to campaigns without a CURRENCY\_MISMATCH error. FX conversion is applied at execution time when the buyer-to-seller currency pair is supported by marketplace FX.
* Inventory source tests now run against the exact product you selected during planning. Previously a test could fail to build a campaign when the selected product fell outside the top slice of discovery results, even though the source could sell it.
* Buying accounts are now identified consistently to sellers. Every step of a campaign (product discovery, account setup, booking, updates, cancellations, and delivery reporting) now sends the same buying organization for a given advertiser, so a seller opens and bills one account per buyer instead of several. Previously the identity varied by step, and on updates and cancellations it was taken from whoever was signed in, which could present the same buy under two different buyers.
* Buyers who have not recorded their own company domain are identified as operating through Interchange. Record your company domain in account settings to be identified under your own organization instead.
* If you have not recorded a company domain, the name your sellers see for you changes with this release. Sellers who create accounts on first contact will open a new one for you on your next request, and campaigns you have already booked stay on the account they were booked under. Nothing stops delivering and no reporting is lost, but for a short period the same seller may show you two accounts. Recording your company domain later has the same effect once more, so it is worth doing before your next campaign rather than during one.
* The Creative Assets dashboard now shows platform-specific ad formats (such as Meta image and video feed formats) in the format selector when creating or uploading a creative for campaigns that include Meta products.
* Opening a feed-backed source in Murph now tells you whether it can sell before anything else: live or in setup, how many avails it holds, and the single next step. Lifecycle stages, the modules behind them, and the work waiting on a person sit below that. Adding a source is now its own task with three fields — a name, where its avails come from, and how often they arrive — replacing eight more that had no effect on how the source ran. Uploading avails is a separate task that still previews before it commits, and the result now names the rows that were rejected alongside the ones that landed, so you can fix the export and upload again. Nothing is offered to buyers until you commit avails rows. Sources you already created keep working, and half-finished setup resumes where you left it.
* When you call `add_discovery_products` after a prior execution, `execute_campaign` now warns you that the pending media buys no longer reflect your current discovery selection. Previously, the tool retried the stale state silently. The warning returns the affected media buy IDs and a `hint` field with the recovery path.
* To apply the current selection and execute in one step, call `create_media_buys` with `replace: true` and `mode: "execute"`.
* Sellers: not applicable — this change is buyer-side only and does not affect seller-visible storefront ranking, rendering, or labeling.
* Fixed a bug where running a test campaign against an inventory source that requires authentication would silently return zero products instead of testing the source correctly.
* Flight dates now read the same wherever you are. A campaign or media-buy flight was formatted in the reader's own timezone, so a window that starts on 1 January showed as "Dec 31" for anyone west of UTC — whether the date arrived as a calendar date or as the instant that day begins. A flight bound names a day, and is now shown as that day.
* Fixed an issue where a media buy package containing multiple image creatives of different sizes (e.g. 970×250 and 728×90) sent a generic `display_image` format ID to the sales agent instead of the correct sized format ID for each creative. The sales agent can now route each creative to the correct sized placement.
* Fixed Murph telling you a report had not been filed after it was successfully filed. Asking for help through the Scope3 team now confirms the filing correctly, with its reference, instead of offering to file it a second time.
* The IU plan selection surface now formats prices, discounts, and dates for your
* account's language and time zone, and the "pricing changed while you were
* reviewing it" notice reads as a calm heads-up that stays legible in dark mode —
* never a red alarm. Your confirmation is still bound to the exact offer you saw:
* a superseded price is refused cleanly and shown again for a fresh confirmation.
* Read the brief your Merchandising Agent answered as a business document. A proposal pass opens on the advertiser, who it came through, and the buyer's ask in their own words — then budget, flight, markets, channels, how they want to transact, and how long you have to respond. Their requirements read as sentences: placements, exclusivity, policies, the metrics they expect back, performance standards, and approved property lists and catalogs by name. Anything the buyer did not send is simply absent. The exact request, its identity, and its capture evidence sit under Technical details.
* See the proposal your Merchandising Agent sent, as the pitch it is. A pass leads with the plan's name, its scale, and its argument for the brief, then one line per product with its price and its share of the plan. Expand a product for why it is in the plan, every pricing option offered and where your selection sat against market guidance, where it runs, who it reaches, and what it reports. When the buyer committed a single exact budget, each share also reads as money. The exact response and its capture evidence sit under Technical details.
* Fixed storefront inventory-source callbacks rejecting RFC 9421 signatures. The sales-agent and storefront-catalog callbacks already accepted them; the inventory-source rail did not, so a source signing to current AdCP defaults had every delivery rejected with a 401 even though its signature was valid.
* All three inbound rails now verify [RFC 9421 HTTP Message Signatures](/v2/storefront/inventory-sources/webhook-signing#rfc-9421-message-signatures) as well as HMAC-SHA256, which AdCP deprecates and removes in 4.0.
* If your source was already signing with RFC 9421 and getting 401s, it should start being accepted with no change on your side. If you want to move a source off HMAC, publish a `jwks_uri` in the `agents[]` entry of your `brand.json` and send `Signature` and `Signature-Input` on each delivery; HMAC keeps working until you do.
* Two details to check when you switch: sign the `@target-uri` as the callback URL we registered with you (we verify against that, not the inbound `Host` header), and always send both RFC 9421 headers, since a lone `Signature` is rejected rather than quietly falling back to HMAC.

## 4.135.0 — July 28, 2026 at 11:10 AM UTC

* Creative requests for AudioStack now use the standard `audio_hosted` format and duration parameters, with no agent URL or separate AudioStack catalog. Meta, Pinterest, and Snapchat validate publisher format options against their registry declarations, while Figma frame names remain tenant-local build settings. Retailers using CitrusAd or Criteo own their catalog entries under their retailer domains. Buyers sending legacy agent-URL selectors to AudioStack or Figma must switch to these canonical fields.
* Authoring buyer discounts is clearer end to end. When you add, edit, or remove a rate-card discount, the Save button now shows an in-flight state and the widget confirms exactly what applies afterward ("Added a 15% brand discount on nike.com, off wholesale"). If the server rejects a save, you get a plain notice that the change did not take and nothing changed — never a silent no-op. Percentages format for your locale, and a failed initial load now offers an in-place retry. Discount pricing rules are unchanged: brand and operator, the larger discount wins, always floored at your wholesale cost.
* Source health no longer reports missing advertisers for ad servers that do not run an advertiser sync. Only Google Ad Manager syncs an advertiser roster; on FreeWheel, SpringServe, and AdsWizz sources that check now stays quiet instead of asking you to grant advertiser access your ad server never uses.

## 4.134.0 — July 28, 2026 at 8:04 AM UTC

* Meta product discovery now surfaces exactly one product per Meta campaign objective. "Meta Conversions Campaign" is renamed to "Meta Sales Campaign" to match Meta Ads Manager's current UI. The "Meta Video Views Campaign" and "Meta Reels Campaign" options are removed — briefs mentioning video views or reels now route to the Engagement and Awareness objectives respectively.
* Source health no longer tells you your ad server has withheld reporting or forecasting access when we have never actually been able to check. The diagnosis now reports what Interchange observes, and names the date of the last completed check, so a result from days ago is not presented as today's status.
* Advertiser-visibility warnings now name your own ad server. A FreeWheel, SpringServe, or AdsWizz source no longer tells you to go check a Google Ad Manager service account.
* Embedded storefront offers now appear as sellers configured them: full creative requirements are preserved, and guaranteed and non-guaranteed fixed-price offers no longer look identical. Buyers get the intended format and price without changing how they discover or select products.
* No seller or current buyer-integration changes are required. Existing package and pricing configuration remains valid. If an older buyer retries a previously cached price identifier that matched more than one offer, the request now returns an error instead of risking the wrong price; refresh the product list and retry with the returned identifier. Older identifiers that match one offer continue to work. Storefront lifecycle, previews, and status behavior are unchanged.
* Buyers enrolled in the directed-campaigns alpha can now read the platform-reported audiences and event sources tracked on a connected seller account with `GET /storefront-connections/{connectionId}/accounts/{accountId}/presences` (or the `list_storefront_connection_account_presences` operation). The response is read-only and reference-only: identity, sync status, and row/event counts for each object — never member lists or event payloads. Objects the seller discovered on its own have no buyer-level master until explicitly adopted; objects already pushed from your account carry their audience or event source ID.

## 4.133.0 — July 28, 2026 at 1:18 AM UTC

* You can now book Meta Lead Generation campaigns through the API, MCP tools, and the Murph assistant. When a respondent taps your ad, they complete a Meta Instant Form — pre-populated from their Facebook profile — without leaving Facebook or Instagram.
* To book a Leads campaign, provide the `lead_form_id` of an Instant Form authorized on your Meta ad account. If you omit the field, the API returns the authorized list so you can select the correct form. Leads campaigns use `LOWEST_COST_WITHOUT_CAP` bid strategy, so no bid price is needed. Spend is billed directly through your connected Meta ad account at Meta's standard delivery rates — no additional platform fee applies beyond your existing Meta connection.
* App Installs (Meta App Promotion) are not yet supported; this release covers Leads only.
* The Demo Storefront now reads honestly across its whole life. A live demo shows
* a green status with the days remaining; one that is close to expiring turns
* yellow; and an expired demo shows a calm gray "Expired" state that explains the
* seven-day demo ended on its own and coaches the next step — connect a real
* inventory source or ask an admin to provision a fresh demo. Resetting or
* deleting a demo now confirms exactly what is affected (synthetic demo data only,
* never your account or real members), shows a progress label while it runs, and
* leaves a visible result. Dates follow your workspace locale and time zone.
* When you create a signal component from your ad server's targeting, the Signal
* components workspace now tells you where the component went — it appears under
* Signal components — and how to change course (rename, reprice, or remove it),
* instead of just saying "created." Your ad server's own segment, key, and value
* names and ids always display exactly as your ad server reports them.
* Seller dashboards now load for active and paused storefronts. The dashboard had continued validating retired storefront lifecycle labels after the API moved to the canonical pause-state contract, so it rejected otherwise successful analytics responses and showed a generic loading error.
* Storefront test-campaign plans no longer show source-catalog pricing option IDs that execution cannot accept. Pricing summaries still show the option name, rate, and currency; omit `pricingOptionId` to let execution select the buyer-facing option.
* The standard plan sizes, the break-even points, the calculator and the worked examples are now all on one page — [How IU billing works](/v2/buyer/billing/how-iu-billing-works) — instead of the table being repeated on the Organization IU Rate Card page. That page now points to it and stays on its own subject: the Effective Rate Card that binds your organization.
* Two protections moved with the table, onto the page that carries the numbers: the standard list is not everyone's price, and prices are published per currency rather than converted from USD. Nothing about the figures themselves changed.
* Buyer account requests to a hosted storefront now wait for the seller's decision when no approved relationship exists. `sync_accounts` returns a submitted task and an account with `pending_approval` status instead of presenting an unreviewed account as active; buyers can poll that task or call `list_accounts` to see the current result. The account can then be linked to an existing billing relationship, routed through Interchange, sent through onboarding, or rejected. This release adds the account lifecycle and audit history, but not the seller management page, CRM import, or ad-server account-mapping feed.

## 4.132.0 — July 28, 2026 at 12:13 AM UTC

* The activities under calibration now read the same way on the Rate Card page and in Plan & Billing. Two the page listed — proposal evaluation pass and comparative proposal ranking pass — were missing from the product's list, and multi-seller product ranking was in the product's list but missing from the page. All three now appear in both.
* One correction worth naming: Plan & Billing described a Murph working session as priced "per five working sessions" while showing its rate as 1 IU. The rate was right and the description was stale. A Murph working session is 1 IU, and the description now says so.
* Nothing about what you are charged changes. These activities are shown for planning, are not part of an accepted Rate Card, and cannot draw down your IU balance.
* Documented the signing contract for async task webhooks that sales agents and inventory sources push back to Interchange. [Signing the webhooks you send us](/v2/storefront/inventory-sources/webhook-signing) covers where the signing key comes from (the `authentication.credentials` value in the `push_notification_config` we send on each call), the exact signed message, the `sha256=` prefix, the timestamp format and skew window, reference implementations in Node, Python, and Go, and a troubleshooting guide for a rejected delivery.
* This contract was previously unpublished, and the only webhook signing scheme in our docs was the buyer subscription scheme, which is different and incompatible. Both pages now cross-reference each other so the two cannot be confused.
* **Action may be required if you hand-rolled your signer.** Signature validation is now stricter and rejects three malformed shapes that could previously slip through: a duplicated `X-ADCP-Signature` or `X-ADCP-Timestamp` header (send each exactly once), a signature that is not exactly `sha256=` followed by 64 lowercase hex characters, and a timestamp containing anything other than digits. If you sign with the official `@adcp/sdk` webhook emitter you are unaffected. If you built your own, check it against the reference implementations on the new page before this release reaches you.
* `fee_rate_percent` in the media buy budget breakdown now consistently reports the fee as a percentage of the media budget (fee / media × 100), regardless of how the rate was stored. Previously, some buys showed the gross-basis rate (fee / all-in total) and others showed the net-basis rate depending on when and how the terms were set, producing different numbers for the same underlying fee on the same advertiser.
* LinkedIn seller-managed campaigns can now target states and regions: pass ISO 3166-2 codes such as `AU-NSW` in `geo_regions`, and Interchange resolves each code to its matching LinkedIn location before the campaign is created. Country-only targeting behaves exactly as it did, campaigns you already created keep their targeting, and only new creates use the new behavior. Geo targeting is state the campaign declares: if a package requests both a region and its parent country (`geo_countries: ["AU"]` with `geo_regions: ["AU-NSW"]`), New South Wales delivers — Australia as a whole does not. Any other countries requested in that package still deliver. If LinkedIn can't resolve exactly one match for a requested region, the request fails before a campaign is created. Nothing else to change on your side. Region targeting is set when the campaign is created and can't be changed afterward — targeting a different region means creating a new campaign.
* Meta media buys can now change or remove region targeting on update, not just at creation. The `geo_countries`/`geo_regions` you send on an update become the complete targeting for that package, replacing what was there rather than merging with it. Clear a region (or leave `geo_regions` off the update) and the package reverts to full-country delivery; add one and it takes effect on that same update — no need to recreate the media buy. Other countries in the same package keep delivering as before. An unresolvable or ambiguous region is rejected before anything changes, so a bad update never leaves a media buy partially retargeted.
* Sellers whose managed ad-server connection was created before the sandbox test account carried an ad-server advertiser can now run a sandbox test campaign.
* Preparing the sandbox account reported the account as not ready and stopped there, because it only ever set up an account that did not exist yet. Connections made before the sales agent started creating the sandbox advertiser therefore stayed blocked at test-campaign validation, and the storefront could not be opened for transactions. Preparing the account now completes the setup of the existing one instead of reporting it as unusable.
* Connections made since then were already set up correctly and are unchanged.
* Snap media buys placed through Interchange can now target specific states, provinces, and other ISO 3166-2 regions (for example AU-NSW or AU-VIC), not just whole countries. Set `targeting_overlay.geo_regions` on a Snap package the same way you already do for Meta: Interchange matches each region code against Snap's region list and attaches the matching native region ID before creating the campaign. Region and postal-code targeting can't be combined on one package — send one or the other. If a region code can't be matched (missing, ambiguous, or duplicated), the request fails before Snap creates anything, so you see the error immediately instead of an under-targeted campaign. Existing country-only Snap campaigns are unaffected; nothing changes on your side unless you start setting region-level targeting. You set region targeting when you create the media buy; to target a different region, create a new one.
* Hand your Merchandising Agent a brief without leaving chat. When a brief reaches you as a document (an RFP, a spreadsheet, a forwarded agency email), drop it into the composer. Your agent reads it, shows you the brief it recognized, and waits for you to confirm — nothing is saved or run until you do. If you drop a media kit, your agent also tells you in chat which of its claims your storefront can and can't back yet. On confirmation, your agent works the brief the same way it works a live buyer's brief, finding matching products and composing a proposal, then lands it in your Demand inbox marked as uploaded so it never reads as live buyer demand. Review it the way you would any incoming brief. Available once the Demand inbox is on for your storefront.

## 4.131.0 — July 27, 2026 at 6:18 PM UTC

* Activating a connected social account now draws IUs from your organization's wallet for each account-month, at the price on your accepted Rate Card — 4 IUs per account-month on the standard card. Your balance goes down, and the usage appears on Settings → Plan & Billing → Usage & credits. No money is charged for it: charging is switched on per organization, never silently, and it is still off. Connecting and mapping accounts stay free, and there is nothing to change on your side.
* While charging is off, account-months past your included allowance accrue as overage you can see but are not billed for. If usage billing is later switched on, overage still accruing in the open period becomes chargeable.
* Each metered account-month records the accepted Rate Card version that priced it. A change to the standard count cannot reprice a month already metered, and it reaches you only through a successor Rate Card you accept.
* Marketplace and buyer storefront responses now distinguish whether a seller is
* available to buy from from whether buyer credentials are connected. Buyers get
* an accurate availability label and a readiness field for integrations; sellers
* using a pass-through sales agent are presented as buyable without an
* Interchange wholesale catalog. No setup or buying-workflow change is required.
* A failing MCP tool now reports its actual error. Tools that declare an output schema returned their ADCP error envelope — `code`, `message`, `suggestion` — in `structuredContent`, but that schema described only the success shape. Because an MCP client validates `structuredContent` against it on every call, the client rejected the error envelope and raised `Structured content does not match the tool's output schema`, hiding the real reason the call failed and the guidance for recovering from it. Each tool's output schema now declares both outcomes, so the error reaches you intact. Affects `get_products`, `create_media_buys`, `update_media_buy`, `api_call`, `list_buyer_activity`, and the storefront and operator tools that declare output schemas.
* Spotify media buys now resolve ISO region and state targeting to provider-native geographic identifiers and reject unsupported targeting before creating provider entities. Region targeting is set when the media buy is created and can't be changed afterward — targeting different regions means creating a new media buy.
* `search` on `/mcp/v3` now covers the documentation as well as your own objects, and searches all three sources by default: `objects`, `docs`, and `specs`.
* Asking "which of my sources are failing" and asking "what does authorization actually mean" are the same question at two altitudes, so they are the same tool. An agent doesn't have to guess whether the answer is a record in your account or a paragraph in the docs. It asks, and gets whichever it is. Every documentation result carries a link, so an answer can be checked rather than taken on trust.
* `docs` is the Interchange documentation for what this platform does; `specs` is the AdCP protocol spec for what the protocol defines. They are reported separately, because "the protocol allows this" and "we support this" are not the same claim.
* The object half is storefront-scoped and today covers inventory sources; a buyer account gets the documentation results and an explicit note that objects were not searched. `/mcp/v3` is behind a feature flag with nobody enrolled yet. Nothing on `/mcp/v2` changes.

## 4.130.0 — July 27, 2026 at 5:09 PM UTC

* When a storefront returns no products and says why, buyers now see the reason. Storefronts hosted on Interchange are dispatched in-process, and that path rebuilt the response envelope from `products` and `proposals` alone — discarding the storefront's own `message`. A storefront that declined to sell ("This storefront is blocked and cannot transact") reached the buyer as `status: completed, product_count: 0` with no explanation, indistinguishable from a storefront that simply had nothing to offer. The message now travels with the response and appears on the matching `ext.interchange.storefront_results[]` entry, as it always has for storefronts reached over the network.
* Setting up a feed-backed inventory source now reads more clearly. Readiness and setup steps stay neutral while a source is still being set up — in-progress work is no longer shown in an alarm color — and the Create, Preview, Commit, and Complete buttons show progress and can't be triggered twice while a change is running. A partially set-up source stays in a recoverable state you can resume or remove, and dates follow your locale and time zone.
* You can now pause and reactivate a single media buy without touching the rest of its campaign. Before this, pausing a campaign paused every media buy inside it; there was no way to bring back just one.
* Call `pause_media_buy` or `reactivate_media_buy` (or `POST /api/v2/buyer/media-buys/:id/pause` and `.../reactivate`) with a media buy ID, and only that buy changes state — its campaign and sibling media buys keep running exactly as they were.
* A paused media buy still accepts budget, date, and package updates the same way an active one does, and those updates still reach the seller. Approving an update never resumes a paused buy — reactivating is the only way to bring it back to `ACTIVE`.

## 4.129.0 — July 27, 2026 at 3:33 PM UTC

* Fixed a bug where re-authenticating a Snap account caused the next `discover_products` call to fail with "Buyer has not connected snap for this storefront". The error appeared immediately after re-auth and resolved on retry. TikTok and Meta were not affected.
* Your merchandising rules stay between you and your Merchandising Agent. Until now, a brief your storefront could not fill sent the agent's internal notes to the buyer's agent: your rule text quoted word for word, the ids of the components it ruled out, and which of your signal sources were not live. Buyers now get copy written for them — no products matched this brief, and how to broaden it. Nothing to change on your side.
* For buyers' agents the contract is unchanged: a brief a storefront cannot fill still comes back as `INVALID_REQUEST` with `reason: no_compositions`, carrying either the neutral line or the seller's own wording. Nothing to change there either.
* Whether a buyer hears the reason is now your call. Write the rule into your merchandising rules in your own words: "when we decline because the budget is below our floor, tell the buyer their CPM is short of what we can sell this inventory for and invite a higher bid, without naming the floor." Your Merchandising Agent makes that case in your voice, in a couple of sentences and within what you authorized; a decline that quotes your rulebook, names an internal id, or runs long is replaced with the neutral line. Say nothing about declines and nothing is disclosed. Your own candid account is unchanged on the intelligence run and its decision record, and running a brief past Murph now tells you which of the two a buyer would get.
* The Retry Forward task now shows its chrome in your own language, keeps buy ids and source error messages verbatim, and reads clearly in both its retry and re-send shapes.
* Meta Sales (OUTCOME\_SALES) campaigns can now be created via the Scope3 API. To create a Sales campaign, provide a `pixel_id` (a Meta Pixel or Dataset authorized on the ad account), a `bid_price` (target cost per conversion in the account currency), and optionally a `conversion_event` (defaults to `PURCHASE`; supported values: `PURCHASE`, `ADD_TO_CART`, `INITIATE_CHECKOUT`, `COMPLETE_REGISTRATION`). The campaign is created with `COST_CAP` bid strategy and `OFFSITE_CONVERSIONS` optimization. Meta Sales campaigns also surface during product discovery when the brief mentions sales, conversions, or purchase objectives. No changes to existing campaign creation calls or other Meta campaign types.
* The Property Roster now leads with the answer you came for — how many of your
* publisher domains need attention — and shows each domain's authorization state
* in plain color: green when a domain is authorized to sell, amber when a
* published adagents.json needs a fix, and gray while a domain is still being
* checked or has no adagents.json yet (setup in progress is not a failure). Dates,
* counts, and every label now follow your workspace language and time zone, and
* long rosters keep that headline pinned while the list scrolls.
* The property roster now renders correctly in dark mode: labels, chips, and the attention banner keep readable contrast instead of falling back to light-theme colors.

## 4.127.0 — July 27, 2026 at 12:56 PM UTC

* When `POST /media-buy-approvals/{mediaBuyId}/retry-forward` refuses a forced retry, the error now says which refusal it is in `details.reason`. Two of them share `400 VALIDATION_ERROR` and `field: "forceTerminal"` but call for opposite responses, and until now the only way to tell them apart was to read the English message:
* `upstream_buy_exists` — a source already has this buy. It reached the ad server; reconcile or cancel it there, and never force. `details.sentLegCount` says how many legs.
* `no_failed_route` — no leg was ever recorded, so there is no evidence the forward went unsent. Usually a storefront-level precondition (paused storefront, unconfigured settlement currency, expired FX quote); fix that and have the buyer resubmit.
* `not_approved` — the entry is not approved, so there is nothing to re-send. `details.status` carries the actual state.
* The status code, error code, `field`, and messages are unchanged, so nothing you have written breaks. If you branch on this error, switch from matching the message to reading `details.reason`.
* If your storefront's status ever moves off green — live with an issue worth attention, or stopped because a promise to buyers broke — you now get a notification the moment it happens, with the reason and a link to fix it. You'll hear about it getting worse too (attention escalating to stopped), and you'll hear when it's back to fully live. A storefront still in setup never triggers this — that's expected, not a problem.
* Nothing to set up on your side. This is an operational alert: it always lands in your in-app notification feed and by email, and can't be muted. Slack is the one exception — it posts there only if you've enabled this event type in your Slack configuration. Nothing changes for buyers.

## 4.126.0 — July 27, 2026 at 10:47 AM UTC

* Discovery now keeps products and proposals attached to the correct storefront when sellers expose the same upstream ID. Buyer teams get more reliable seller attribution across discovery, refinement, and media-buy setup, with no workflow change for chat or UI users. API and MCP integrations that already pass the top-level `product_id` and `proposal_id` returned by discovery back unchanged need no action. Integrations that reconstruct IDs from `source_product_id` or `source_proposal_id` should instead preserve the returned `sf1:` or `sfp1:` ID; when a source ID is ambiguous, the API now returns a validation error so the client can re-run discovery and use the returned qualified ID. Sellers need no action: their inventory and proposals now remain labeled with their own storefront instead of being attributed to another seller when IDs collide.
* Pending operations now offers a **Re-send** action on a media buy a source refused, instead of routing every terminalized buy to escalation. Re-sending keeps the buy's ID and your approval — the buyer does not resubmit.
* The action appears only on buys that can actually be re-sent: a source has to have refused the buy after receiving no part of it. A buy that failed before any source was contacted — a paused storefront, an unconfigured settlement currency, an expired FX quote — still shows escalation, because there is nothing to re-send. Groups of failures offer the action only when every buy in the group qualifies.
* Failed-forward rows on `GET /pending-operations` carry a new `action` value, `force_retry`, alongside the existing `retry`, `fix_and_resubmit`, and `escalate`. If you branch on `action`, treat an unrecognized value the way you treat `escalate`.
* Re-sending replays the original payload with only the end date refreshed, so check the flight window first: a buy re-sent days later carries its original start date and full budget over a shorter window.
* Open any Demand inbox row to see the whole exchange: the proposal pass. It shows the brief facts exactly as your buyer sent them, the products your agent proposed with each one's plan allocation and price, a timeline of proposal versions, and the commercial result. Allocation money appears only when the buyer committed a definite budget, never computed against an open range, and prices come from the pricing option the plan actually selected. A won exchange shows its recorded value or says "not recorded" — never a guess — and a lost exchange shows the buyer's stated budget as the demand you didn't close. When a proposal was too old or too large to have been captured in full, the pass says so instead of guessing. Expand any product to inspect the exact recorded snapshot. Nothing to set up; it opens from the Demand inbox once that's on for your storefront.
* `POST /media-buy-approvals/{mediaBuyId}/retry-forward` now takes an optional `reason` (up to 500 characters) recording why you re-sent a buy. It is worth supplying whenever you set `forceTerminal`, which overrides a terminal state in front of your ad server — the reason is recorded against the attempt, so whoever reviews it later can tell a considered recovery from a reflexive one.
* Nothing is required and no existing call changes. A retry without a reason behaves exactly as before.
* Agents connected to `/mcp/v3` get a new tool, `save_ask`, for the two things an account cannot resolve on its own: something is broken, or something does not exist.
* A `support` ask reaches the Scope3 team the same way a problem reported in Murph chat does, and returns a reference id to quote when you follow up. A `product` ask records a capability we do not have; if someone already asked for it, yours joins that entry instead of creating a duplicate. Only the title is recorded on a product ask, so make the title carry the request. Tracking an ask is not a commitment to build it.
* `save_ask` works from any account, buyer or seller, and needs only read permission. Whoever runs into a wall is usually not whoever has permission to fix it.
* Also on `/mcp/v3`: structured responses over 200KB are now truncated. That is a backstop against pathological payloads, not a size to design against.
* `/mcp/v3` is behind a feature flag with nobody enrolled, so there is nothing to call yet. Nothing on `/mcp/v2` changes.

## 4.125.0 — July 27, 2026 at 7:51 AM UTC

* Buyers can now create TikTok carousel ads with 2–35 distinct square images in a chosen order. Interchange verifies that every image is available in the selected advertiser’s TikTok account, and the ad stays paused until TikTok returns every image in that same order.
* Your storefront has a new Demand inbox: one front-of-house ledger of every buyer brief your agent answered, the proposal it produced, the buyer's feedback, and whether you won — with the money attached. Each row carries the buyer's stated budget range from the brief, won rows show the booked or delivered value in its own currency, and a Booked YTD tile totals this year's wins per currency. The metrics strip also shows briefs this year, how many you answered, your win rate (first responses only — the widget explains the count), your average grade, and how many briefs the agent led versus a human; filter the ledger by buyer from the header. Every number is drawn only from what actually happened — a metric with nothing recorded yet reads as unavailable rather than a misleading zero, and a brief captured before we started keeping canonical records shows "artifact unavailable" instead of a reconstruction. Nothing to set up; open it from the Demand row in your rail once it's turned on for your storefront.
* Buyer MCP clients can fetch the tool list again. `get_products` declared an output schema that was not a JSON Schema object at the root, and because an MCP client validates the whole `tools/list` page at once, that one tool made every tool on `/mcp/v2/buyer` disappear — claude.ai reported "tools fetch failed", Claude Code indexed no tools, and the TypeScript SDK threw before returning. The schema now describes both a complete and a field-projected response as one object, so the page parses. `/mcp/v2/storefront`, `/mcp/v2/murph`, and `/mcp/v3` were never affected.
* `get_products` also now returns `name` on every product even when your `fields` selection leaves it out, matching AdCP: `product_id` and `name` are always included regardless of selection. Previously a narrow `fields` list could return products you had no way to label.
* Snap `discover_products` and `get_products` calls that fail due to a missing or
* mismatched ad account selection now return a descriptive `INVALID_REQUEST` error
* instead of the generic "Upstream request failed". This applies to all synthesized
* correctable errors from the Snap adapter (account required, invalid account,
* account mismatch, incompatible product selection, etc.).
* Buttons that open a second workspace from a seller widget work again. "Open sync & diagnostics", "View details", "Open full diagnostics", and "Add another ad server" on the Ad server source page — plus the equivalent launches from Pending operations, Sync diagnostics, Release notes, and Test runs — were failing with "Couldn't open that workspace. Try again." These launches were being resolved against the buyer tool set, which does not contain the seller tools they open; they now resolve against the seller tool set.
* Delivery reads for TikTok campaigns that cover multiple days now succeed instead of failing with a "delivery is not authoritative" error. The daily report returns one row per day for a campaign, and the completeness check was mistakenly comparing that day-row count against the provider's per-campaign count. Spend now uses base-10, currency-aware minor-unit rounding; the package breakdown lists every ad group in the campaign (including those with zero delivery); and package totals are cross-checked against the campaign report within a bounded tolerance for provider reporting lag. When pagination cannot be corroborated, report spend diverges beyond that tolerance, or a spend value cannot be represented safely in the account currency, the request still fails closed rather than returning partial numbers. Nothing to change on your side.
* TikTok delivery reads now accept the integrated report's documented live response shape when `page_size` reports the number of returned daily rows instead of echoing the requested capacity. Arbitrary page-size mismatches, incomplete pages, duplicate rows, and unstable terminal pages still fail closed.
* Budget and end-date changes that a publisher accepts for later processing now apply to the live buy on their own.
* When you submit a change, the publisher may apply it immediately or accept it as a task to complete later. The second case only ever resolved if the publisher called us back, and for publishers that do not, the change could sit until it timed out a week later without applying. It is now also resolved by asking the publisher directly, so a change lands as soon as they confirm it.
* Two related corrections:
* A change that has been submitted is no longer announced as though it were already live. You are told it was submitted and is awaiting confirmation.
* Submitting a budget or date change while an earlier one is still with the publisher is now rejected, with an explanation of what is already in flight. Previously the second submission merged into the first, leaving a combination neither one asked for. Other updates to the same buy, such as creative changes, are unaffected.
* How you submit a change has not altered.
* You can now see at a glance whether each storefront is live and healthy. Every storefront gets one status, computed once and shown the same way everywhere it appears.
* The readiness response (`GET /api/v2/storefront/readiness` and the `get_storefront_readiness` tool) carries a new `liveness` verdict with four values: `setup` (gray — not live yet, as expected while you set up), `live` (green — buyers can discover and buy), `live_attention` (yellow — live, with something worth acting on), and `live_critical` (red — live, but something is broken that affects buyers). Every verdict comes with a one-line reason; during setup it also counts the go-live steps remaining.
* The same status shows on the seller setup screen and as a per-storefront dot in the account switcher. Clicking a storefront with a yellow or red dot takes you straight to the screen where you can fix it.
* Two guardrails keep the status honest: a disconnected source that isn't behind any buyer-visible product won't turn your status red, and storefronts that pass buys through to an external platform or your own sales agent aren't held to merchandising steps that don't apply to them.
* Nothing to set up on your side. Nothing changes for buyers — no new fields, and discovery, media buys, and settlement behave exactly as before.
* A media buy that an inventory source refused does not need to be rebuilt under a new ID. The seller can re-send the original — same media buy ID, their approval intact — once the cause is fixed.
* Sellers do this with `POST /media-buy-approvals/{mediaBuyId}/retry-forward` and `{"forceTerminal": true}`, or `retry_forward_media_buy_approval` over MCP. It is an API control today: the retry action in Pending operations still covers transient failures only and routes a refused buy to escalation. Buyers cannot re-send a buy themselves; ask the seller.
* This corrects the v4.118.0 note, which told buyers that terminalized buys could not be retried in place and to resubmit under a fresh media buy ID. That was wrong. The control has always existed; it was missing from the API reference, and the reference described terminal failures as unrecoverable.
* Three limits. A buy that failed before any source was contacted — a paused storefront, an unconfigured settlement currency, an expired FX quote — records no forwarding leg and cannot be recovered this way; it needs a fresh submission. The original payload is replayed with only the end date refreshed, so a buy re-sent days later carries its original start date and its full budget over a shorter window. And it applies only to a create approval the seller already approved: a rejected buy has nothing to re-send, and an update approval ignores the flag. Before forcing a retry, check the flight window and check the ad server for an order a partial write may have left behind.
* `forceTerminal` is now published in the API reference, and a new [Retry forwarding](https://docs.interchange.io/v2/storefront/media-buy-approvals/tasks/retry-forward) page covers how to tell a delivered buy from a refused one, what to check before forcing one, and how to read the result. Platform behavior is unchanged — existing calls do exactly what they did before.

## 4.124.1 — July 26, 2026 at 5:49 PM UTC

* Adapter connections now report classified account-discovery failures and hide expired, abandoned OAuth attempts instead of rendering duplicate storefront rows.
* Adapter OAuth expiry checks now support the PostgreSQL version used by deployed environments while preserving safe handling of malformed legacy timestamps.

## 4.124.0 — July 26, 2026 at 3:24 PM UTC

* Storefront Activity now shows dates and times in your own locale and timezone, and its "couldn't load" messages are easier to read.
* You can now update a media buy directly by its ID: `PATCH /api/v2/buyer/media-buys/{mediaBuyId}` on the buyer REST API, and the matching `update_media_buy` tool on the buyer MCP server. Send only the fields you want to change — name, flight dates, package budgets and pacing, product budgets, optimization goals, or creative assignments — without routing the edit through the campaign update, which still works unchanged. An update that would break a campaign invariant fails with a specific error instead of being silently adjusted — for example a pricing option that settles in a different currency than the buy, a budget increase past the campaign's remaining budget, an edit to a buy on a tracked (seller-mirrored) campaign, or a buy or campaign that has already ended. Flight dates outside the campaign window are the one exception — they apply, the campaign flight widens to cover them, and the response includes a warning saying so.
* Separately, creating media buys (`create_media_buys` on REST and MCP) now rejects manual product selections against a performance campaign — the platform selects and allocates the product mix on those toward your objective. If your integration hand-picks products for a performance campaign, those requests now fail with a validation error; drop the manual selection and let the campaign allocate, or make the selection on a discovery campaign instead.
* Sellers: nothing changes on the seller side — updates reach sellers through the same execution and approval path as campaign-routed edits, and a rejected buyer request never contacts the seller. Monetization: none — no billable surface or metering change; the verb is covered by existing buyer API terms. Exposure: ungated (`gate: none`) — an atomic, additive verb on the existing authenticated buyer surface; rollback is a code revert with no data migration. Adoption: `update_media_buy` call volume and per-failure-mode error mix via workload-attributed buyer activity; the success signal is direct mutations on multi-buy campaigns, which previously had no verb (baseline zero). Full launch record: the commercialization brief on AI-4576.
* Nothing to change on your side, and nothing starts charging in this release.
* A seller organization accepting an IU plan for the first time now receives a one-time 100-IU credit on better terms. You no longer have to be a new customer to qualify, and the credit spends on any IU-priced activity rather than storefront setup work only. One credit per billing organization, valid 60 days from the day you accept — counted in days, not billing cycles — with the exact expiry date shown on Settings → Plan & Billing → Usage & credits. One plan covers an organization's selling and buying work, so setup and buying draw on the same 100 IUs.
* **How IU billing works** is a new page that follows one charge end to end: what an IU is, what consumes one and what is always free, the seven steps from a published price to an invoice, worked examples for a light month and a heavy one, and a calculator for which plan is cheapest at your volume. Two numbers worth taking away: above 200 IUs a month the 250 plan costs less than pay-as-you-go, and above 650 the 1,000 plan costs less than the 250. If you reconcile invoices, *Checking our numbers* lists the exact reads each charge was built from. If you would rather not read a rate card at all, ask Murph what something costs or why a charge appeared — it answers from the same page.
* The Organization IU Rate Card page now shows the standard plan sizes and prices as the agreed standard model rather than provisional figures. They are not published in production, so nothing on that page is an offer you can accept today, and the per-activity IU counts we are still calibrating stay marked as such.
* Separately, on Plan & Billing: accepting terms and saving billing details now update the page immediately instead of needing a reload, and an account with setup still outstanding now shows that outstanding step instead of reporting good standing.
* Managed evaluation in `get_products` is more reliable: the evaluation model is now shown the exact output shape (including enrichment and refine variants) and explicit field limits, so evaluations no longer fail open when the model formats its verdicts with invented field names or oversized reason lists. Fewer executions report `status: degraded` with `evaluated: false` pass-throughs.
* Directed-campaign mirrors of a connected TikTok account now keep syncing when the provider's advertiser details omit an unrelated presentation or financial field (such as balance, language, role, or account creation time). Media-buy reads only need the account's identity, ownership, and currency, so those reads no longer fail — and disable every mirror — over a field they never use. Account identity, ownership/scope, and currency are still checked strictly and still fail closed. If a periodic sync does fail, the subscription now keeps the machine-readable diagnosis (`errorCode`, `errorField`, `errorReason`, `upstreamCode`) so a later read can tell a provider-shape error apart from a credential or configuration problem; a successful sync clears it. Nothing to change on your side.
* Murph now checks the source-specific publisher authorization guidance before advising modular sellers, and keeps documented API field names intact in its replies. Nothing to change on your side.
* Product discovery now honors the requested product fields. Murph carries ordinary product results up to 32K characters and explicitly pages or narrows anything larger instead of treating the visible products as the complete catalog. Existing requests need no changes.
* The published plan sizes and prices are the standard USD list, and the billing docs now say so where the numbers are. Two clarifications: your Effective Rate Card is the authority — an authorized discount, a negotiated package, or an enterprise offer replaces the list figures, and Plan & Billing shows list and effective price side by side before you confirm. And prices are set per currency rather than converted: a plan in EUR, GBP, or AUD is its own published number, not the USD figure at an exchange rate, and the currency on the revision you accept is the one your invoice, charge, and wallet use. The plan calculator now states that it computes the standard USD list rather than a quote.
* The pages also now say what happens when standard prices change: a change arrives as a **new published revision**, never as an edit to a revision anyone accepted. Your binding pins the version, term, and prices you agreed to, so a change to the published table does not change what you pay — you would see a successor offer and decide whether to accept it.
* Sellers: the same three clarifications now appear on the storefront billing page, which carried the identical table. One plan covers an organization's selling and buying work, so the list, the currency rule, and the revision behaviour are the same on both sides — and the storefront page no longer describes the plan values as "not final" when they were agreed on 2026-07-22.
* When you open a media buy's timeline to trace where it's stuck, stage times and
* budgets now read in your own language and time zone, and the surface is
* localized in Portuguese and Japanese. A forward that failed once but then
* recovered on retry no longer shows as a red alarm — only a buy that is actually
* stuck is flagged. Nothing to change on your side.
* Pinterest media buys now validate region and state targeting against Pinterest before creating a campaign, and send canonical provider geo identifiers instead of treating subdivisions as metro locations. Region targeting is set when the media buy is created and can't be changed afterward — targeting different regions means creating a new media buy.
* Murph now keeps its full tool catalog on escalated questions. When a question
* was escalated for extra precision, Murph was reducing its own tool surface to
* fit a model that could not hold it, then answering on a different model that
* could — but without the tools it had just put down. Escalated questions could
* therefore be discussed but not acted on. Murph now picks up the full set again
* once it has the room, so an escalated question gets the same actions available
* as any other.
* When your seller analytics dashboard has no negotiations yet in the selected
* window, it now opens to a clear "no runs yet" line instead of a screen of
* empty zero charts — and the run-window date range no longer shows a blank
* "- to -". Once buyers start negotiating with your agent, the full dashboard
* (win rate, booked budget, delivery, posture conversion, and recommendations)
* is unchanged.
* The seller setup widget now shows one clear storefront status: gray while you set up, green when your storefront is live, yellow when something needs attention, and red only when a live storefront can't sell. Setup steps stay neutral — remaining work shows as progress counts and a single next action, never an alarm — so red means stop, not "still setting up."
* Buyer surfaces are unchanged: this reworks how sellers see their own storefront status, not what buyers see in discovery or transactions.
* Agents connecting to the storefront MCP server now receive full operating guidance at connect time, instead of a single reminder about notifications. The server tells your agent to orient with `get_storefront_readiness`, confirm operation names through `ask_about_capability` before calling `api_call`, route "how do I" and "why is this stuck" questions to Murph, make one verified mutation per turn, and look up publisher authorization rules rather than answering them from memory.
* This closes a gap for anyone driving their storefront from their own agent — ChatGPT, a custom client, or any MCP host — where that guidance previously reached only our own assistant. The storefront skill also now states Murph's real capabilities: it searches the published docs and inspects your live storefront state.
* The full contract is documented in [Built for agents](https://docs.interchange.io/v2/setup/built-for-agents).
* TikTok media buys can now set a package's `geo_regions` field for region-level targeting alongside `geo_countries` — any ISO 3166-2 subdivision TikTok itself supports is resolved live against TikTok's own location inventory, and a subdivision TikTok can't confirm is rejected before the campaign is created, rather than silently dropped to country-level. Region targeting is set when the media buy is created and can't be changed afterward — targeting a different region means creating a new media buy.

## 4.123.0 — July 26, 2026 at 12:24 AM UTC

* You can now list a media buy's packages in one call and tell them apart. `GET /api/v2/buyer/media-buys/{mediaBuyId}/packages` (MCP operation `get_media_buy_packages`) returns each package with its product, its own flight window, and the pacing period it covers. Going from "the display package ending 2026-08-11" to the right package id no longer means reading the whole campaign or asking your seller for an export. The response leaves out targeting, creative, and format detail on purpose, keeping it small enough for an agent to read in full.
* Package ids are opaque. The trailing number on a storefront-minted id like `sf_pkg_..._3` is the order the package was dispatched in, not the period it covers, so read the new `pacingPeriod` field instead of parsing the id.
* Interchange now also keeps the flight window it asked for when a seller's response leaves it out, so newly created paced packages carry their own start and end dates. No package created before this change has a pacing period recorded, and roughly 9 in 10 have no flight window either. Neither gap can be filled in later. Product name plus budget will sometimes narrow those packages to one, but not when the pacing schedule gave those periods the same budget, in which case the package can't be addressed individually through the API and your seller is the way to reach it.
* If you manage your buys in chat, nothing changes for you.
* Campaign lists now default to your live working set: every campaign that could still spend — active, draft, and paused — across both platform-managed campaigns and tracked mirrors from connected seller accounts. Connect a seller account and your live spend there appears in `GET /api/v2/buyer/campaigns` and `list_campaigns` immediately — while the account's finished history (completed and canceled campaigns) stays out of the ambient list. Pass explicit statuses or the new `status=ALL` to reach it, and use `management=managed|tracked` to narrow by who operates the campaign. This revises the earlier managed-only default before its flag retires: flood control now lives on the status axis, so nothing you could still run is ever hidden.
* Nothing changes for sellers, and no new seller data is exposed: the campaigns involved are the buyer's own campaigns in their own connected account, mirrored under the subscription the buyer already authorized — this change only adjusts which of those already-visible mirrors appear without a filter.
* Connected ad-platform accounts now show their campaign footprint at a glance. Each account card on the Connections page carries a rollup: how many campaigns are tracked and how many are active, tracked and managed spend over the trailing year, always in the account's own currency (never converted or totaled across currencies), and a managed-share bar showing how much of that activity runs through the platform. For brand teams, that answers "how much of our TikTok activity runs as managed campaigns?" without opening a report; for agency teams, it makes connected accounts comparable across clients. A "View tracked campaigns" link drills into the tracked campaign list for accounts mapped to a single advertiser. In the campaigns widget, a new Managed / Tracked / All switch narrows the list by who operates each campaign. The default list still shows what you're working on: active and draft campaigns, both managed and tracked; completed or paused history stays out unless you ask for it.
* New TikTok campaigns created through Interchange no longer expand into delivery destinations Interchange cannot verify, and automatic delivery in TikTok search is off. Existing campaigns with other delivery settings remain visible but read-only; make any changes to them in TikTok Ads Manager. The public `tiktok_for_you_feed` placement ID remains unchanged; Interchange maps it to TikTok's provider enum internally.
* Your storefront now keeps the canonical record of its exchanges: the exact AdCP `get_products` request it received (content-addressed, secrets redacted) and, for every brief it answered with a proposal, the exact response it returned with immutable product snapshots. (Wholesale catalog pulls record the request only — a catalog listing is not a proposal.) Retrieve them with `GET /brief-artifacts` and `GET /proposal-artifacts` (REST or `api_call`); each demand-inbox row links the brief artifact that produced it. Records from before capture began report the artifact as unavailable — nothing is ever reconstructed after the fact.
* Pausing a Snap campaign in Interchange now remains in effect when you add or
* replace creative later. The campaign and its ad groups stay paused until you
* explicitly resume it, so routine creative work cannot restart spend. Resuming
* checks that every active package has a creative and that Snap accepted the
* change; if Snap's state cannot be confirmed, the campaign stays paused.
* For an existing Snap campaign, your first budget, schedule, or creative change
* may ask you to pause or resume it once so Interchange can record your choice.
* Enterprise teams can apply this safeguard across automated or high-volume
* campaign operations. Lean teams get the same protection with no setup or
* reconnect. Seller workflows, pricing, billing, entitlements, and planned media
* spend do not change.
* Reddit media buys now normalize country and region targeting to provider-native ISO identifiers and reject invalid regions before creating provider resources.

## 4.121.0 — July 25, 2026 at 9:41 AM UTC

* Your TikTok product catalog is now read and updated only through the TikTok business account that owns the connected advertiser. Currency, region, and item-status totals come directly from TikTok. Seller storefronts and published inventory are unchanged, and no action is needed unless a sync now stops because the advertiser and catalog are not owned by the same TikTok business account; correct that connection and retry.
* Media buy reads now tell you when a change you submitted has not taken effect yet. Every field on a media buy describes what is **currently delivering**, and a submitted-but-not-yet-applied change appears separately as `pendingChange`, whose `differences` map spells out the live and proposed value for each field it would change.
* Previously a buy with a queued change could report `PENDING_APPROVAL` in `mediaBuyRefs` while `get_media_buy` and the delivery poll reported the live values, with nothing anywhere saying a change was waiting. A buyer polling status could reasonably conclude an update had gone live when the buy was still delivering the old budget and end date.
* **Corrected behaviour, worth checking your integration:** `mediaBuyRefs[].status` now always reports the **live** status of each buy. A buy that is delivering with a change awaiting approval reads `ACTIVE` and carries `pendingChange`; it previously reported `PENDING_APPROVAL`, which described a version that was not delivering. That value was never documented as a pending-change signal, so this is a correction rather than a contract change, but if you inferred queued changes from it, read `pendingChange` instead.
* A buy awaiting its **first** approval is unaffected: `status` still reads `PENDING_APPROVAL` with no `pendingChange`, because nothing is live behind it yet.
* Sellers see no change. This affects the buyer read surfaces only; storefront approval queues, seller media-buy lists, and the approval flow are untouched.
* Treat a change as applied only once `pendingChange` is absent. See [Media buy lifecycle → Pending changes](https://docs.scope3.com/v2/concepts/media-buy-lifecycle#pending-changes-what-is-live-vs-what-you-asked-for).

## 4.120.1 — July 25, 2026 at 1:40 AM UTC

* `get_campaign_products` now returns the package IDs for every media buy that has packages. Some buys came back with an empty `packageIds` array even though the packages existed, which forced buyers to source package IDs from their seller instead of from the API.
* No action is required for existing Snap connections. Creative assignments now
* recover one exact Snap Ad after retries or lost responses, and creative
* inventory preserves the buyer's source creative and original assets. Missing,
* duplicate, substituted, or cross-account provider objects fail closed. The
* ordinary assignment path retains its existing activation behavior; the
* future-dated readiness fixture is the path forced to stay paused. There is no
* pricing, billing, entitlement, or media-spend change; the capability remains
* included with existing Snap adapter connections.
* The protected readiness check can now verify a future-dated paused Snap
* campaign from creative upload through complete inventory, package assignment,
* provider review state, exact Ad materialization, zero delivery, and terminal
* cleanup. It remains disabled unless an operator enables an identity-free image
* or video fixture in the protected staging overlay.
* Per-package delivery figures (spend, impressions, clicks, completions) are now correct. Each delivery report's per-package daily breakdown is accumulated into a per-day ledger, so a package's lifetime delivered totals are the sum across days rather than the most recent window. This fixes an undercount in the per-package delivery shown on media-buy lists and detail, and it strengthens the budget floor that stops a package budget being reduced below what it has already delivered.
* TikTok catalog sync now safely resumes after a timeout or interrupted create without creating a duplicate catalog or feed. If TikTok cannot identify exactly one matching result, the sync stops and asks you to retry after provider inventory converges instead of repeating the write.

## 4.120.0 — July 25, 2026 at 1:00 AM UTC

* Your TikTok catalog sync now stops before changing anything when TikTok returns an incomplete feed or inventory from another account, preventing the wrong catalog from being used. If a catalog that previously synced now fails, verify that the connected TikTok advertiser owns the catalog and that its feed inventory is complete, then retry. This buyer-side change does not alter seller storefront setup, ranking, inventory labels, or any other buyer-visible seller attribute.
* Meta creative-format discovery now honors exact supported filters and bounded pagination instead of silently returning the full catalog.
* TikTok account discovery now honors status and sandbox filters after fully enumerating the provider inventory. Opaque continuation cursors preserve stable, once-only account coverage and reject tampering or tenant, filter, expiry, offset, and inventory drift.
* Snap account operations now keep cached Public Profile and targeting lookups isolated by connection, tenant, selected account, and provider parent. OAuth token rotation forces a fresh provider read; no changes are required on your side.
* Storefront readiness now requires every seller to declare what publisher domains it sells without treating `adagents.json` authorization as a transaction blocker or guessing that the operator domain is inventory. It warns separately about products that lack a declared-domain mapping while legacy catalogs are backfilled. One successful sandbox or live media-buy transaction permanently satisfies transaction validation, and seller-owned no-spend tests can exercise a pre-live storefront without exposing it to ordinary buyers. Narrow operational exceptions use an append-only audited service-override ledger and remain distinct from transaction evidence. Multi-storefront product discovery also preserves a seller's explanation when readiness produces an empty result, so buyers can distinguish an unavailable storefront from one with no matching inventory.
* No action is required for existing Snap connections. Conversion writes now
* report events as processed only after Snap returns its exact valid CAPI
* receipt; matching, attribution, and reporting finalization remain asynchronous
* and are not claimed by that receipt. There is no pricing, billing, or media
* spend change. This capability remains included with existing Snap adapter
* connections; it is not a separate entitlement or paid add-on.
* The protected readiness check also verifies complete Pixel inventory, rejects
* a Pixel outside the selected account, and exercises a synthetic Customer List
* audience through create, replay, update, delete, and final absence without
* customer data or spend. It remains disabled unless an operator enables the
* protected GSM overlay for a dedicated staging connection.

## 4.119.0 — July 25, 2026 at 12:05 AM UTC

* Campaign lists now default to your managed working set. `GET /api/v2/buyer/campaigns` and the `list_campaigns` operation return `management: "managed"` campaigns unless you ask for more: pass `management=tracked` to list read-only campaigns mirrored from a connected seller account, or the new `management=all` to include both states. A subscribed account can mirror thousands of historical campaigns — their scale now lives in the connected-account rollup (`campaignsTracked`, spend rollups, `managedShare`), not in your ambient campaign list. If you relied on the previous default returning mirrored campaigns, add `management=all` to those calls.
* Connected seller accounts now carry a campaign rollup, so each connection shows everything the platform tracks without flooding your campaign list.
* Each account on `GET /api/v2/buyer/storefront-connections/{connectionId}/accounts` returns an optional `campaignRollup`: `campaignsTracked` (campaigns the platform did not set up, mirrored read-only from your connected seller account), `campaignsActive`, `trackedSpend` and `managedSpend` over the trailing 365 days, and `managedShare` — `managedSpend / (trackedSpend + managedSpend)`, the share of reported spend running through platform-managed campaigns, null until spend is recorded. Spend is seller-reported net in the account currency (for campaigns managed through the platform, your full media budget goes to the seller with no platform fee, so net equals your budget), and rollups are never summed across currencies. Connection rows on `GET /api/v2/buyer/storefront-connections` add `campaignsTracked` and `campaignsActive` counts. Nothing changes in billing — the rollup reads what your subscribed accounts already mirror.
* The Media Buys page now leads each row with the buyer instead of the internal buy id, formats flight dates in your locale and timezone, and offers an in-place retry when the list fails to load.
* Metadata separators on Media Buys rows now render with proper spacing; the previous join used a Tailwind utility this package never emits, leaving the dots glued to the text.

## 4.118.0 — July 24, 2026 at 9:12 PM UTC

* If a canonical-image buy was previously rejected and terminalized, resubmit it with a fresh media buy ID after this release; terminalized buys cannot be retried in place. Newly executed and resubmitted buys with one unambiguous fixed image size now send the resolved width and height in their package selectors, so GAM-backed sellers can traffic them. No action is required for other buyers or sellers.
* Fixed-price products authored through managed sales agents now stay buyable after composition, and accepted product changes reach buyer and readiness catalogs without a manual refresh. Managed proposal evaluation now exits a hung provider attempt with enough time to try a fallback before the request deadline. No changes are required on your side.
* Managed evaluation results in `get_products` now say explicitly when a candidate was NOT actually evaluated. When evaluation degrades (deadline elapsed, pass budget exhausted, or the evaluation model was unavailable), candidates fail open as accepts — previously those pass-throughs were indistinguishable from judged accepts unless you read the `reasons` text, so an agent could buy on an accept that never saw its instructions. Each candidate's `ext.interchange.evaluation` (and the deprecated `screening` block) now carries `evaluated: boolean`: `false` means your evaluation instructions were not applied to that candidate, so re-check it before spending against it. The response `guidance` also calls out degraded executions so agents that only read dispositions do not mistake pass-throughs for judgments. Nothing changes for sellers: this labels the buyer-side evaluation verdict, not the seller's candidate, and sellers do not see buyer evaluation results.
* Products returned from embedded sales agent storefronts now retain their canonical creative format declarations in `get_products`.
* Every campaign in buyer reporting now carries its management state: `managed` (authored or adopted through the platform) or `tracked` (mirrored read-only from a connected seller account). The label appears on every campaign block in the `summary` view, on every `timeseries` row, and as a new `Management` column in the CSV export, after `Campaign Name`. Today every label reads `managed` — tracked mirror delivery is not reported on this surface yet.
* If you generate strict validators from the reporting response schema, regenerate them: `management` is a new required property on campaign blocks and timeseries rows. If you parse the CSV export by column position, account for the new `Management` column. Metric values and formulas are unchanged.
* This surface reports managed delivery only — tracked mirror delivery is excluded — so managed totals never silently include tracked spend, and when mirrored spend is admitted it will arrive labeled. The field ships ungated to all buyers (it is additive and constant until then); tracked labels appear only for accounts enrolled in the connected-seller-accounts alpha, once mirror delivery is integrated. No seller-facing behavior changes. There is no billing change. Adoption signal: presence of the `management` field in consumed reporting responses and CSV exports.
* The seller analytics dashboard now answers the headline question above the fold and keeps detail on a single in-widget scroll, so it fits the chat window on first load.
* Chat widgets now follow the chat-surface expanded/collapsed model. An expanded widget takes its content height capped at the chat window, so a dense surface like the seller analytics dashboard no longer scrolls far past the screen on open. Opening a widget holds your view on it: new chat lands below in conversation order and the jump-to-latest pill appears instead of the view being pulled away. Open Pages and Glances gain an explicit Collapse control that tucks them to their named stub in place; sending a message or jumping to latest resumes normal conversation follow.

## 4.117.0 — July 24, 2026 at 6:48 PM UTC

* Campaigns now carry a `management` state alongside `mode`. `tracked` means a campaign you did not set up through the platform: it is mirrored read-only from a connected seller account and updates automatically as the seller changes things. `managed` means a campaign authored or adopted through the platform. Campaign list and get responses include the new field, and `GET /api/v2/buyer/campaigns` accepts a `management=tracked|managed` filter — for example, `management=managed` excludes mirrored read-only shells from your working set.
* If you generate strict validators from the campaign response schema, regenerate them: `management` is a new required response property. Nothing else about existing calls changes — the `mode: "directed"` wire value remains for compatibility, and the word "directed" is retired from campaign vocabulary. Read `management` to know whether the platform acts on a campaign.
* No seller-facing behavior changes: the management state describes the buyer's own relationship to a campaign, and nothing new about a seller is exposed. Outside the connected-seller-accounts alpha, every campaign reports `management: "managed"`; tracked campaigns appear once a connected seller account is enrolled. There is no billing change — the field and filter add no billed usage, and connected-account subscription pricing is unchanged. Adoption signal: use of the `management` filter on campaign list calls.
* Action required for sellers: confirm every storefront settlement currency is supported, fix any readiness blockers, and clear Pause when you want to accept buys. Storefronts now stop accepting new buys whenever required setup is missing or failing, and readiness names the exact issue. Buyers should rerun product discovery if a seller no longer supports the advertiser's currency. Storefronts where the connected platform clears payment directly are unchanged.
* Meta account discovery now honors client pagination after fully enumerating the provider account inventory. Opaque continuation cursors preserve stable, once-only account coverage and reject tampering or tenant, filter, and snapshot drift.
* Retrying a failed campaign execution now submits the same DRAFT media buy, preserving its creative selection, flight dates, pacing, and optimization goals. The `get_products` purchase shortcut also prepares new selections exactly once: stage when you want to review or customize the DRAFT first, or execute when it can be submitted immediately. No changes are needed on your side.
* The seller rail can now be organized around the selling journey — Connect (your sources), Teach (your agent), Pitch (for business), and Execute (what you've won) — so the rail reads as the ingredients of your next proposal instead of a settings menu. Same rows, same permissions; only the grouping changes.
* Meta, Snap, and TikTok storefronts now return account financials consistently through the SDK using the authenticated selected account, while preserving provider-reported currency, balances, spend, and reporting periods.

## 4.116.0 — July 24, 2026 at 4:59 PM UTC

* Snap measurement now validates the complete account Pixel inventory before campaign or conversion writes. Accounts with multiple Pixels require an explicit selection, setup code comes only from Snap, test-event codes reach Snap, and accepted conversion batches no longer overstate asynchronous processing.
* AudioStack and ElevenLabs audio generation now uses the provider account mapped to each advertiser under Settings → Connections. Existing advertiser-specific assignments carry over; no action is needed if those mappings are correct. If you relied on an organization-wide default, map each advertiser before its next generation. Generation pauses when a mapping is missing or a key changes instead of charging another account. Voice defaults do not change, and you can still choose a different voice for one generation.
* For Meta seller-managed campaigns, you can now target states and regions by passing ISO 3166-2 codes in `geo_regions`. Existing country targeting is unchanged. If Meta cannot resolve exactly one region in the requested country, the request fails before a campaign is created.

## 4.115.0 — July 24, 2026 at 3:27 PM UTC

* `get_products` now accepts numeric-string advertiser IDs and normalizes them before processing the request.
* Ad-server-backed inventory sources now surface missing Google Ad Manager team access instead of reporting a successful advertiser sync with no results. FreeWheel delivery reporting, Google Ad Manager inventory filtering, product refinements, and creative matching also behave correctly. If an advertiser sync reports a permissions error, assign the connected Google Ad Manager user to an active team with advertiser access; otherwise there is nothing to change.
* Multi-storefront `get_products` is now the taught front door for buyer agents. Murph recommends the canonical surface first for new product exploration — with progressive polling, optional proposal evaluation, and direct continuation into `create_media_buys` — and reserves Discover Products for existing `discoveryId` workflows and the grouped session view. The buyer documentation hierarchy leads with the same guidance.
* The typed `get_products` and `create_media_buys` MCP tool definitions now share repeated AdCP shapes through standard JSON Schema `$defs` references, reducing their combined `tools/list` payload from roughly 370KB to 169KB so buyer agents spend less context on tool discovery.

## 4.114.0 — July 24, 2026 at 9:02 AM UTC

* Failed social-adapter account syncs now expose stable diagnostic fields to readiness tooling while keeping untrusted provider details out of signed evidence. Nothing changes for successful syncs.
* Snap conversion reporting now verifies that the selected ad account owns the Pixel and counts events only after Snap confirms the batch.
* Approvals now escalate by default. When no approval routing rule is saved, approvals route to your organization admins — admins receive approval reminder and escalation emails (plus in-app notifications) without any setup, and saving a routing rule still overrides the default. If your organization has no active admin at all, approval emails fall back to every active user so blocking work is never silent — and the missing admin is flagged. All four approval kinds are covered (media buys, creative reviews, ad-server approvals, and inventory shortfall reviews — the latter two always route to admins). The Approvals widget's Overdue view is now age-based, so an item with no owner still surfaces once it has waited too long, oldest first. Blocking source problems you own re-nudge you at 24 hours and 7 days if still unresolved, then go quiet.
* Snap account discovery now rejects malformed, duplicate, or cross-organization account data instead of presenting it as an active selectable account.
* Snap account readiness now verifies that the selected account belongs to its exact active, readable OAuth credential. Existing Snap connections require one reconnect after this deployment because pre-deployment account snapshots do not carry the new credential proof and are intentionally not trusted or backfilled. Until that reconnect succeeds, adapter calls fail closed; reachable account and advertiser mappings are then preserved.
* Fixed Meta `discover_products` failing for performance-mode campaigns when the brief does not specify a creative format (image or video). The request now correctly includes the product's supported format IDs rather than an empty list.
* Before your next Snap creative sync, refresh product and format discovery and add a `headline` of up to 34 characters to every full-screen image or video creative. New setup now offers Snap Awareness, Traffic, and Web Conversions with `snap_ad_image_9x16` and `snap_ad_video_9x16`; Catalog Traffic, App Installs, Story Ads, Collection, Lead Generation, Sponsored Snaps, Commercials, generated, and promoted-offering options are no longer returned or accepted for new syncs.
* Existing Snap campaigns and creatives are not edited, paused, or deleted by this release and can keep delivering in Snap. If an account contains another creative format, Interchange leaves that object in Snap and stops creative inventory with `UNSUPPORTED_CREATIVE_FORMAT` instead of showing an incomplete list. Brands and agencies should update shared creative templates and trafficking playbooks; API and MCP integrations should refresh discovery and supply `brand_name`, `headline`, and the advertised image or video asset. Buyers working in chat will see only the two supported full-screen choices, and a missing headline stops before any media upload.
* Pricing, plans, and entitlements are unchanged; this adds no billable surface and does not change seller products, inventory, ranking, or storefront presentation.
* Snap connected-account delivery reports now keep spend in the selected ad account's currency and include every ad squad in the requested window. Shifted, partial, or inconsistent provider reports return an error instead of exposing incomplete billing totals. Nothing changes in your request.
* Snap campaign, ad-squad, ad, creative, media-upload, bid-estimate, Public
* Profile, Pixel, and catalog client methods covered by this release now stop when
* Snap declares an error inside an HTTP success response. Global-ID mutations and
* creative assignments confirm the selected-account parent chain before writing,
* and later-page inventory failures return a bounded host diagnostic instead of a
* successful prefix. This is not a universal Snap-envelope claim: audience batch
* and polling calls and Conversions API HTTP-success envelope semantics remain
* tracked separately.
* Native catalog writes use the selected account's organization and currency,
* stage local mapping changes behind an atomic revision check, and keep durable
* tenant/account/catalog journals for both catalog and product-feed creation.
* Retries after an ambiguous catalog or feed response never repeat the uncertain
* POST. They reconcile only exact complete provider readback, while delayed
* visibility, drift, foreign identities, unselected `catalog_ids`, and concurrent
* stale writers fail closed with no hidden provider or local mutation. No action
* is required.
* Social adapter campaigns now use the Interchange campaign name when creating platform campaigns. Previously, adapters such as Snap, Reddit, LinkedIn, and Pinterest ignored the campaign name and defaulted to a date-based fallback (e.g. "Campaign 2026-07-23"). Google and Amazon used an internal correlation reference instead of the campaign name. The standard ADCP buyer flow also failed to forward the campaign name to adapters even when a name was provided at campaign creation time. All adapters now use the Interchange campaign name, falling back to a date-based name only if no name is available. Ad groups, ad squads, and ads now consistently include the campaign name as a prefix (e.g. "My Campaign - Ad Group 1"), matching the naming convention used by Meta and TikTok.
* Storefront connections now show as connected immediately after mapping a provider account to an advertiser. Previously, the connection stayed in needs\_account\_selection state after a successful mapping, blocking product discovery and capabilities for the advertiser.
* Murph escalation status now treats Linear duplicate tickets as closed, preventing reconciliations from reopening consolidated reports.
* Meta's product catalog now returns results for open or conversational briefs ("What ad products can I buy from Meta?"), matching the behavior of TikTok and Snap. Previously, briefs that lacked explicit campaign language caused Meta to return zero products. Products requiring platform setup (conversions, app installs, lead gen) continue to be excluded from controlled-planning results; the returned catalog reflects what can be booked today. The `scope3_brief_strategy` object in the response still signals any clarification needs so the buyer agent can guide next steps.
* If you're setting up Meta buys through Interchange, only Auction buying type is available today; Reservation (Reach & Frequency) campaigns are not supported.
* Sandbox inventory-source tests for pass-through sources now select real products end to end. When you plan a sandbox test, the product candidates come from the same sandbox catalog the test actually uses, so a product shown in planning no longer comes back as "no matching products" at execution. And re-running a sandbox test for a brand you've already tested reuses the existing test advertiser instead of failing when it tries to create a duplicate.
* Three guardrails now protect live storefronts from silent degradation.
* **Currency changes confirm their impact.** Changing the settlement currency on a live storefront now tells you how many buyer-visible products the change would hide (prices you set directly are only shown in the settlement currency) and rejects the update until you confirm with `confirmCurrencyCatalogImpact: true`. Non-live storefronts and zero-impact changes are unaffected.
* **Stale buy statuses are flagged.** Media buys routed through an ad-platform connection now surface a staleness marker when the platform stops confirming status — the media-buys list carries a `statusFreshness` note ("status last confirmed Nh ago — source unreachable") and a matching `media_buy_status_stale` diagnosis, instead of showing a dead connection's last-known status forever. If the marker doesn't clear, check that your ad-platform connection is still authorized.
* **Stale reporting prices come off the market.** Ad-server-reporting-derived pricing now has a 60-day freshness ceiling: a product whose cached reporting price hasn't refreshed in 60 days is hidden from buyers with a "check your ad-server connection" readiness state, rather than served on a stale price. A fresh sync restores it automatically.
* Buyer note: products hidden by the currency or freshness guardrails drop out of buyer discovery — buyers see a smaller catalog, not an error.
* Platform campaigns created by adapter storefronts (Meta, Snap, TikTok, LinkedIn, Reddit, Pinterest, Google, Amazon) now use the Interchange campaign name chosen by the buyer instead of a system-derived name.
* Existing `get_products` calls require no changes and keep their current behavior unless proposal evaluation is enabled. `discover_products` again applies its established enrichment, relevance, ordering, and refinement behavior when evaluation is omitted.
* Add plain-language instructions under `ext.interchange.evaluation` to evaluate proposals before your buyer agent processes them. Interchange can accept or reject each proposal, attach buyer-owned enrichment, request a bounded AdCP refinement from the originating seller, and reevaluate the revision. An optional comparative pass ranks accepted proposals across storefronts.
* Progressive polls return replacement snapshots. Rankings remain provisional while sellers are pending; an unchanged revision poll is cached, while a changed accepted cohort is ranked again. Unchanged candidate versions do not repeat absolute evaluation. `ext.interchange.screening` remains available as a deprecated compatibility alias for accept, reject, and refine; it does not enable enrichment or comparative ranking.
* One **Proposal Evaluation Pass** processes up to 10 candidates. One **Comparative Proposal Ranking Pass** ranks up to 100 accepted candidates. Both meters are calibrating and report `charged_ius: 0`; provider tokens, retries, cached polls, protocol validation, and seller network calls are not separate passes.
* Reconnect Snap in **Settings > Connections** if Customer List audience sync says the connection cannot prove its identity. Audience create, update, member add/remove, status, and delete now retry without duplicating a list, stay isolated to the selected account, and return only Snap-confirmed outcomes. Incomplete or unfamiliar provider responses stop with an error instead of exposing or changing the wrong audience.
* Snap campaign discovery on selected USD accounts now asks for clarification instead of selecting a product when a brief is ambiguous, unsafe, or missing a supported objective or geography. Non-USD planning remains fail-closed until account-currency pricing is supported.
* Reconnect an existing Snap connection in Settings > Connections before using conversion measurement. New and reconnected Snap connections now request offline-conversions access in both hosted and delegated OAuth flows; Public Profile access remains excluded pending Snap allowlisting.
* Existing Snap campaign calls require no request changes. Campaign creation now confirms that Snap accepted the selected product and targeting before reporting success. Campaign reads show the requested settings, the current settings in Snap, and whether they match, without exposing private audience identifiers.
* If Snap omits or changes required settings, Interchange returns a clear error or reports the difference instead of presenting unverified targeting. Pricing, plans, and entitlements are unchanged; this adds no billable surface.
* Your Snap campaigns now use the selected ad account's currency for prices,
* forecasts, and budgets. Non-USD accounts no longer inherit US-dollar minimums
* or guidance, and inconsistent amounts stop before a campaign is created.
* Nothing to change on your side.
* TikTok directed campaign creation now verifies selected-account ownership, paused materialization, activation response identities, and enabled readback at every hierarchy level. It activates the campaign only after its children. On ambiguous activation, cleanup verifies the exact campaign is paused before requesting deletion, distinguishes confirmed paused containment from a possibly active campaign, and reports rollback only after terminal provider readback. Offering-based packages remain paused until TikTok offering assets can be materialized as runnable ads.
* TikTok product discovery now asks for one campaign outcome instead of returning runnable recommendations from a vague, negated, or competing brief. If prompted, reply with an explicit choice such as `Objective: traffic` and retry; supported outcomes are reach, video views, traffic, conversions, app installs, and lead generation. Otherwise no action is needed.
* No action is needed unless a TikTok creative sync asks you to reconnect. If it does, reconnect TikTok in Settings > Connections and retry.
* TikTok image, video, and promoted-post creatives now keep their names and assets through retries, replacements, and service restarts. Campaign setup stays paused until TikTok confirms the intended creative was attached, and incomplete or conflicting TikTok responses stop safely instead of reporting the wrong status. Older saved TikTok channel selections also continue to work when the channel is still authorized.
* This improvement is for buyers who sync or run TikTok creatives. Seller storefronts and seller workflows are unchanged.
* Existing TikTok campaign calls require no request changes. Campaign creation now confirms that TikTok accepted the selected product and targeting before reporting success. Campaign reads show the requested settings, the current settings in TikTok, and whether they match, without exposing private audience identifiers.
* If TikTok omits or changes required settings, Interchange returns a clear error instead of presenting unverified targeting. Pricing, plans, and entitlements are unchanged; this adds no billable surface.

## 4.113.0 — July 23, 2026 at 11:39 PM UTC

* Delivery reporting now accumulates every counter (impressions, clicks, completed views, views, conversions, leads) into a lifetime total for sellers who report one day at a time, matching how delivered spend already behaves. Previously these counts showed only the most recent report for per-day-reporting sellers, so a campaign's totals could look far smaller than what actually delivered. Cumulative and full-window reports are unchanged.
* When a campaign execution fails because a seller's platform timed out, the error now explains that the media buy may still complete asynchronously and tells you to check its status — rather than surfacing a raw technical message with no direction. A new documentation section on the media buy lifecycle page shows how to receive completion webhooks instead of polling when working directly over AdCP, and the buyer agent now includes guidance on handling timeout errors and the async-acceptance path.
* `create_media_buy` and `execute_campaign` no longer return a misleading "sales agent not found" (404) when the sales agent actually exists but is not active. A pending, disabled, or failed sales agent now returns a specific, actionable error (409 `SALES_AGENT_NOT_ACTIVE`) that names the real reason — for example, that the storefront has not completed go-live and is not transacting yet, so complete billing/payout to activate it. An ID that resolves to a non-sales agent now returns a validation error naming the actual agent type rather than a 404.
* Three settlement and catalog-pricing correctness fixes:
* **Settlement no longer guesses on an unrecorded media buy.** When a media buy's clearing method (Interchange-cleared vs. seller-direct) wasn't recorded at booking time, the ledger now falls back to the storefront's own declared clearing method before defaulting — the same fallback the seller-facing Media Buys list already used to fill in "not recorded" rows. The rare case where neither is known still books safely and is now flagged internally for follow-up, instead of silently assuming Interchange-cleared.
* \*\*A $0 price is never treated as a real price.** A product option carrying a $0 fixed or floor price — the platform's internal "not yet priced" placeholder — is now excluded from composed and pass-through catalog listings instead of reaching buyers as a bookable zero-dollar rate.
* **Unpriced products stay visible to you, hidden from buyers.** A legacy product your pricing feed couldn't price (e.g. a currency mismatch, or an option shape the feed can't match) used to disappear from your catalog entirely with no explanation. It now stays in your catalog — visibly marked as unpriced with the reason — while remaining correctly hidden from buyer discovery until it's priced. A product you priced yourself with a fixed rate in your settlement currency is unaffected: it stays buyable on that price even when the feed can't price it.
* Seller Setup now keeps every inventory source visible and opens the exact ad-server, feed-backed, or external-agent flow when you add another source, without asking for storefront-wide settings again. Uploaded media kits and policy documents now produce separate business-profile, acceptance-policy, and canonical creative-format drafts for review, and the Acceptance Policy page provides a conservative starter policy when no document is available.
* Creative tool connections now show only the relevant Audiences control. Buy and Events no longer appear because those settings do not apply to creative generation. No action is required.
* If Merchandising Rules shows **Needs cleanup**, remove the listed pricing, discount, market, or eligibility statements when you create your next version. The active version remains active in the meantime, but Selling Terms, Buyer Discounts and Buyer Instructions, Business Profile, and Acceptance Policy take precedence. Buyers do not need to change anything: storefront discovery and qualification now use each seller's Business Profile markets consistently.
* Several surfaces now report their true state instead of a misleading default:
* **Go-live catalog check (sellers):** if opening for transactions is blocked by a failed catalog check, the error now names which inventory sources failed (up to three, plus a count) and a coarse reason (timed out, unreachable, errored) instead of a generic "try again in a moment."
* **Publisher domain roster (sellers):** a domain whose adagents.json check hit a transient failure (timeout, DNS, 5xx) now shows "couldn't check yet — retrying" instead of "Unknown," so it's clear we're still trying rather than that we've never looked.
* **Analytics win rate (sellers):** a brand-new storefront with no run history yet shows "–" for win rate instead of a false "0%."
* **Terms of Service (buyers and sellers):** an account whose organization has no valid parent to accept Terms of Service on behalf of now sees a clear "contact support" message instead of the generic "must be a direct admin" error.
* **Assistant render honesty (buyers and sellers):** any tool result that opens a screen — on every MCP surface, buyer and seller alike — now reminds the assistant that it only requested the screen and cannot claim to see it rendered. This previously covered only a subset of seller-side tools.

## 4.112.0 — July 23, 2026 at 9:15 PM UTC

* You can now continue directly from multi-storefront `get_products` into one Interchange cart request. Select storefront-qualified proposals and/or proposal-less products, then choose whether to stage or execute the resulting media buys. Interchange keeps the search and refinement history on the product query and uses a DRAFT campaign as the shopping cart and parent of every media buy.
* Pass an existing campaign or include the fields for a new discovery campaign. If you create one inline, the response returns its campaign ID; media buys are never left without a campaign parent. A proposal selection applies that proposal's product allocations to the cart—the proposal object itself is not sent back for exact execution. `mode: stage` contacts no sellers. `mode: execute` sends ordinary bilateral AdCP `create_media_buy` calls for the resulting buys and reports partial failures per media buy. The seller calls are not atomic, and an unchanged retry does not repeat completed work.
* The new v2 surface is available as `POST /api/v2/buyer/media-buys/batch`, MCP `create_media_buys`, and the buyer `api_call` operation `create_media_buys`. Existing discovery selection and `execute_campaign` workflows remain available and need no changes.
* **Commercial model:** There is no incremental charge for `create_media_buys` at launch, and existing media-buy pricing is unchanged. Retrieval remains included. Optional proposal screening remains a separately measured Intelligence Unit activity, with `charged_ius: 0` while screening is calibrating.
* **Rollout and rollback:** This additive v2 surface launches ungated (`multi-storefront-products` remains `gate: none`). Existing callers enter it only when they invoke the new route or tool, so current workflows do not change. Rollback removes the additive route and tool; discovery selection and `execute_campaign` remain available.
* **Measurement:** `multi-storefront-products` defines active use as returning a multi-storefront `get_products` page or staging or executing qualified selections with `create_media_buys`. Batch audit events distinguish stage from execute and record selection count, inline campaign creation, and whether selections replace or merge. We will monitor successful staged and executed batches, retry/no-op rate, and per-media-buy errors. Healthy expansion means buyers complete multi-storefront carts without duplicate buys after an unchanged retry.
* **Persona pass**
* **Enterprise brand buyer:** Stage a reviewed cross-storefront plan on an existing campaign, inspect the resulting DRAFT buys, and execute only when approved.
* **Large agency / hold-co buyer:** Apply accepted proposal allocations from several storefronts in one cart request while retaining per-buy execution outcomes and retry safety.
* **Scrappy builder / power buyer:** Feed storefront-qualified IDs from `get_products` straight into `create_media_buys`; create the campaign inline when you do not already have one.
* **SMB buyer (novice, chat):** Save selected inventory in a draft campaign cart and review the prepared media buys before any seller is contacted.
* **Seller:** You continue to receive an ordinary one-to-one AdCP `create_media_buy` request. Other storefront selections and the buyer's Interchange cart metadata are not shared with you.
* Existing storefront API calls keep their behavior. Integrations can now clear the first-go-live test-campaign gate without switching to Murph: plan a sandbox inventory-source test to inspect readiness and products, then redeem its short-lived, single-use token to execute the exact no-spend campaign through the real buyer path. The current validation covers product discovery and media-buy execution; it does not create or validate a creative. The existing test-runs API reports the result and its failing step. Seller-scoped test execution provisions a missing storefront wrapper before buyer discovery, while media-buy creation resolves stale selections from authoritative storefront provenance.
* Buyers are unaffected: the canary is confined to the seller's sandbox-capable source and mock product provenance, creates no spend, and does not appear as a live offer or campaign to real buyers. This adds no billable surface, pricing change, plan gate, or packaging differentiation; it makes an existing go-live validation available to authenticated storefront API integrations.
* Exposure plan: `gate: none`. The API ships atomically because authentication, seller ownership, sandbox capability, mock-product provenance, a five-minute token, and single-use execution constrain exposure. There is no cohort expansion: all eligible authenticated storefront integrations receive the same contract. The kill switch is deployment rollback of these additive routes; there is no migration or persisted entitlement to unwind.
* Measurement: named usage signals are authenticated requests to `storefront_test_campaign_plan` and `storefront_test_campaign_execute`, plus terminal success and failure rows in the durable storefront test-run history. Launch acceptance is at least one seller completing the API plan-to-execute path with no real-spend or cross-tenant event, while 4xx/5xx and failing-step rates identify validation or runtime regressions.
* Actions inside interactive chat widgets now finish where you click them instead of posting the same choice back as a new chat request. Product selections save in place; creative campaign assignments and library saves execute directly; event sources and signal components finish in their forms; inventory and creative-reference choices record a quiet completion for the next step. Controls that could not actually complete a task are no longer presented as working actions.
* **Persona pass**
* **Seller:** Inventory, signal, and event-source work stays in the surface that collected the configuration, with an explicit saved or created result.
* **Enterprise brand buyer:** Creative assignments and library roles commit through the governed typed operation, without an extra model interpretation step.
* **Large agency / hold-co buyer:** Repeated product and creative work no longer creates duplicate conversational instructions across accounts and campaigns.
* **Scrappy builder / power buyer:** The same named operations and MCP completion channel work in Murph, Claude, ChatGPT, and other compliant hosts.
* **SMB buyer (novice, chat):** Clicking Save or Attach produces the result shown on the card instead of asking the buyer to explain the click again.
* **Launch plan:** This is an atomic ungated correction to existing GA widget surfaces (`gate: none`). Deploy to every host with the release. Roll back this change if direct operation completion or non-prompting context writeback regresses; rollback restores the former controls without changing any saved campaign, creative, product, signal, or event-source data.
* **Measurement:** Track successful `add_discovery_products`, `attach_creatives_to_campaign`, `save_creatives_to_library`, `sync_event_sources`, and `create_signal` operations alongside `mcp_widget_context_updated` completion events. Watch operation error rate, repeated identical user turns immediately after a widget action, and widget-to-operation completion. Acceptance is zero `sendMessage` calls in API Call, no increase in operation failures, and no confirmed duplicate-composer regressions across five buyer and five seller accounts.
* **Monetization:** None. Entitlements, pricing, settlement, and Intelligence Unit treatment do not change.
* Media-buy updates now leave existing creative assignments unchanged unless you include `creative_ids`. Send the full list to replace assignments, or `[]` to clear them. You can update campaign details or packages without revalidating attached creatives or sending them to the seller again.
* If your integration reads `droppedCreatives` from `update_campaign`, remove that handling: the field is no longer returned.
* For a package without stored flight dates, a date update now returns `CAPABILITY_NOT_SUPPORTED` until the seller advertises supported actions. Retry after the seller has provided that capability information.
* **Persona pass**
* **Scrappy builder / power buyer and large agency / hold-co buyer:** Send `creative_ids` only for an intentional assignment change; ordinary campaign and package updates now leave existing assignments alone.
* **Seller:** No storefront presentation or setup changes are required. Storefronts receive only the requested package update rather than re-forwarded creative assignments. Sellers supporting package date changes should continue exposing their supported actions.
* Three fixes to the storefront operate surfaces. Approvals: routing settings load reliably instead of showing a persistent "Unavailable" error — nothing to change on your side. Media buys: each buy now shows its real settlement method (Interchange-cleared or seller-cleared) wherever it is determinable; buys whose method genuinely isn't recorded say so explicitly — nothing to change on your side. Payouts: banking details no longer block going live. You can activate your storefront first; funds accrue but cannot be disbursed until you add payout details, and the Payouts tab tells you exactly that with an add-details button.
* Active external sources now receive an automatic initial health check instead
* of remaining unclassified until buyer traffic reaches them.

## 4.111.0 — July 23, 2026 at 6:57 PM UTC

* Integrations must send `format_kind` when they create a creative from only a brief or when its legacy format reference conflicts with its asset type or dimensions. Existing canonical requests and supported legacy references continue unchanged when the evidence identifies one canonical kind. Saved creatives now match campaigns and products by that canonical format instead of an imported label. Sellers do not need to change their products or integrations.
* You can now turn reviewed ad-server inventory into a draft product without leaving Inventory Components or Inventory Selector. Name the product, choose the buyer creative formats, review validation results, and confirm creation in the same surface. Nothing is created until you select **Create draft product**.
* If you ask Murph with an exact product configuration, Murph can validate and create the draft through the same product operations. No existing products or publishing settings change.
* Draft products are not visible to buyers until you activate them. This release changes seller authoring only; buyer discovery and active catalog presentation are unchanged.
* **Persona pass**
* **Seller:** Review synced inventory and create a validated draft without repeating the selection in chat. Existing products are unchanged, and the new draft remains buyer-invisible until activation.
* **Enterprise brand buyer:** No workflow or governance change. Drafts created by sellers do not enter discovery until the seller activates them.
* **Large agency / hold-co buyer:** No workflow change and no new catalog rows until a seller activates a draft.
* **Scrappy builder / power buyer:** No buyer API or MCP contract changes; the new operations are storefront-authoring operations.
* **SMB buyer (novice, chat):** No visible change. Murph does not present seller drafts to buyers.
* **Launch plan:** This is an atomic ungated launch within the existing GA Product Authoring feature (`gate: none`). Inventory Components and Inventory Selector are already available to eligible storefront operators; the release replaces their composer handoff with the typed workflow. Expand immediately with the deployment. If validation or create completion regresses, revert this change to restore the prior Murph product-authoring path while preserving all existing products and underlying product APIs.
* **Measurement:** Use API operation telemetry for `validate_esa_product` and `create_esa_product`. Adoption is a storefront completing at least one successful validation; completion is a successful create with `status: draft`. Watch aggregate validation-to-create conversion, field-level validation failures, and create failure rate by storefront. The current REST telemetry does not carry MCP-app resource provenance, so do not attribute aggregate calls to a specific widget until that dimension exists. Acceptance is at least 20 successful draft creations across five storefronts, no confirmed composer-handoff regression, and a create failure rate below 5%.
* **Monetization:** None. Product authoring entitlements, pricing, and Intelligence Unit treatment do not change.
* Delivered-spend on media buys is now accumulated per reporting day instead of being overwritten by the latest delivery report. Buyers and sellers previously saw understated "delivered so far" figures on buys whose sellers report daily (or in overlapping windows), which could let a budget reduction slip below what had already been delivered. Delivery now sums correctly across days and is robust to re-sent, corrected, and overlapping reports.
* Spotify package-budget and end-time updates now use the provider's documented account-scoped `PATCH` method instead of failing with `405` under `PUT`.
* Sales-agent connections whose OAuth refresh grant is rejected now show as degraded and reconnect-required instead of being reported as a source outage. Interchange no longer retries discovery with a known-expired access token, so the actionable credential issue is not overwritten by a misleading endpoint failure or timeout.
* Live storefronts now notify you when your buyable catalog empties — for example, when manual pricing expires — naming the cause and the fix. Going live is now blocked while your catalog can't be verified yet, or when nothing in your synced catalog can actually be trafficked (e.g. video with no duration, or display formats with no width/height); a partial issue still warns without blocking. Readiness also flags active products that reference a publisher domain you haven't declared or authorized.
* Buyer agents can now retrieve every package ID for a media buy and poll or cancel a pending update by its exact proposal ID. Updates that name an unknown package or media buy are rejected before the seller is contacted. Existing integrations do not need to change. Sellers do not need to act; a cancelled proposal becomes terminal, and a late seller callback cannot change the live media buy.
* Widget load failures in chat now name the widget that failed and offer a Retry button instead of a dead-end "MCP app failed to load." strip, collapsed widget bars carry the widget's name, a diagnostics request for an ad-server source opens its sync & diagnostics surface instead of an unrelated "connect a sales agent" form, and the assistant no longer claims a panel is visible when it failed to render.

## 4.110.0 — July 23, 2026 at 4:49 PM UTC

* You can now send one `get_products` request to selected storefronts—or every storefront connected to an advertiser—and receive products and proposals as sellers respond. Each product and proposal ID identifies its originating storefront and can be passed unchanged to later refine and media-buy calls.
* Screening is optional and currently in beta. Add plain-language instructions to have Interchange evaluate each valid proposal against your criteria, then return it unchanged, exclude it from the result, or ask the originating seller to refine it. If screening is unavailable, valid proposals pass through instead of being rejected. Existing unscreened calls are unchanged and remain included at no additional charge. During calibration, screening pass counts and estimated IUs may appear, but `charged_ius` remains `0`.
* Discover Products accepts the same optional screening instructions. When you refine a discovery with screening enabled, Interchange sends the refinement to the seller, then screens the seller’s revised proposals before returning them.
* **Persona pass**
* **Enterprise brand buyer:** Compare proposals from connected sellers under buyer-controlled screening criteria. Existing workflows stay the same unless your media team enables screening.
* **Large agency / hold-co buyer:** Collect products from connected sellers in one progressive request. Optional screening removes proposals that miss your first-pass criteria and asks sellers to refine others before your team compares them.
* **Scrappy builder / power buyer:** Use the v2 REST endpoint or MCP tool. Select storefronts, poll results, and add screening through `ext.interchange`; pass storefront-qualified IDs unchanged into refine and media-buy calls.
* **SMB buyer (novice, chat):** When screening is enabled in Discover Products, proposals that do not meet your criteria stay out of the results, and sellers may be asked to revise others before you see them. There is no API setup.
* **Seller:** Buyers can now compare your proposal with responses from other connected storefronts and may ask you to refine it before review. You receive the bilateral AdCP request only; buyer screening instructions and Interchange coordination fields are not shared. No setup change is required. Complete proposals pass protocol validation, and prompt refine responses can return before the buyer’s deadline.
* Registering a sales-agent source with a malformed credential payload now fails at registration instead of succeeding silently. Previously, an API-key credential sent under the wrong field name (for example `key` instead of `token`) passed validation, showed as configured, and left the agent permanently unreachable with no pointer to the cause. Registration now rejects the wrong shape with a validation error, and credentials already stored under the legacy field name are read correctly.
* Source diagnostics now measure inventory discovery from `get_products` only, so failures in account sync, campaign updates, creative operations, or delivery reporting no longer falsely label a source as unable to return inventory. Those failures remain on their own operational axes. The same correction stops unchanged ESA health conditions from being presented as new Agentic Ops incidents while preserving the underlying health state and recovery re-alerting.
* A2A async discovery polling now recovers the seller's returned server task ID from the paired response before calling `tasks_get`, preventing a failed immediate pre-seed race from polling Scope3's client operation ID instead.
* Read-only source rechecks no longer turn an accepted asynchronous task or an account-required public probe into a critical outage. Pending tasks remain degraded until their correctly addressed background poll records the terminal result, and terminal success clears the health cell.
* Fixed an issue where the storefront setup assistant could stop taking actions (such as re-checking an ad server, inventory source, or compliance status) and reply in text only. These re-check actions now run reliably during setup.
* Spotify campaign creation and readback now preserve the buyer-authored campaign name across provider synchronization.
* TikTok media buys now use the selected ad account's currency consistently from product discovery through campaign creation, monetary updates, and reporting. Conflicting or malformed account details—including unknown account statuses or roles—stop before a campaign budget or bid mutation, while recognized non-approved accounts remain discoverable with a suspended or closed status.
* You can now connect a hosted feed or upload and replace CSV, TSV, Excel, and JSON files directly in Catalogs. Approval counts, rejected rows, and field-level issues stay beside the advertiser feed so you can review and retry the exact change in one place.
* **Persona pass**
* **Enterprise brand buyer:** Review feed changes and rejected items in one governed advertiser workspace; no partner instruction or seller presentation changes.
* **Large agency / hold-co buyer:** Add and maintain feeds across advertiser accounts without moving configuration into a separate chat workflow.
* **Scrappy builder / power buyer:** Supply a feed URL or row-based file directly and inspect the sync result immediately.
* **SMB buyer (novice, chat):** Murph opens the guided Catalogs Page for setup; no API payload or technical prompt is required.
* **Seller:** Not applicable. This changes buyer-owned advertiser feed setup and does not change what buyers see about a seller or what sellers must configure.
* **Launch plan:** This remains behind the existing **Buyer widgets v2** customer flag. Expand after at least 20 successful URL/file syncs across five enrolled buyers with a sync failure rate below 5% and no confirmed return-to-chat regressions. Disable `buyer-widgets-v2` to remove the Page entry while retaining the existing API and Murph catalog paths.
* **Measurement:** Use successful and failed `sync_catalogs` activity records for enrolled buyers, split by URL and inline-file requests. Adoption is a buyer completing either path; acceptance is the expansion threshold above.
* **Monetization:** None. Catalog sync pricing and entitlements do not change.
* If your storefront is in the Trusted Match pilot, you can now declare `trusted_match` on a product directly through the wholesale authoring API. Send the field on `POST`, `PUT`, or `PATCH /tenants/{tenant_id}/wholesale-products` and `get_products` returns it on the next call. `PATCH` is coverage-preserving: omit or send `null` to keep the stored value, send an explicit body to replace it. Declare which runtimes the product supports (context match, identity match), the provider agent URL, and the uid types and countries the declaration covers. The SQL workaround is retired; existing declarations keep working. Storefronts not in the pilot see no change: sending `trusted_match` returns `403 tmp-not-enabled`. Pilot enrollment is managed by Scope3 operations through a new `PUT /tenants/{tenant_id}/adapter-config/tmp-enabled` endpoint.
* Buyers: no behavior change. Buyer agents calling `get_products` continue to receive `trusted_match` on any product where a seller has declared it, exactly as they did before — the field itself and its shape are unchanged; the only change is that sellers can now populate it themselves.
* Monetization: none. Trusted Match itself is priced through the existing sales-agent runtime and identity-match provider contracts; this endpoint does not introduce a new billable surface or entitlement.
* Rollout: gated per-tenant behind `AdapterConfig.tmp_enabled` (ops-provisioned, fail-closed). Expansion: pilot storefronts move to beta once a declared product surfaces on the setup checklist and flows through a forwarded media buy end-to-end; beta moves to GA once the legacy match-flag reader is retired. Kill switch: ops flip `tmp_enabled: false` and writes immediately return `403 tmp-not-enabled`; stored declarations are preserved but no longer emitted on `get_products` from that tenant.
* Storefront Briefs now runs starter discovery tests directly and keeps progress, matched products, errors, retry, and decision review beside the selected brief instead of creating a generated chat prompt.

## 4.109.0 — July 23, 2026 at 2:57 PM UTC

* Seller Setup and ad server source diagnostics now run reporting, forecasting, refresh, and discovery re-check actions through their canonical typed operations. This fixes valid FreeWheel re-check buttons being blocked by a stale host allow-list and prevents the same operation-map drift across other source adapters.
* Answering the first setup question with "sell through Scope3" no longer fails on brand-new storefronts. The intent's capability preset previously tripped a validation that requires an approval reviewer to be configured — a step new sellers had not reached yet. The reviewer requirement still holds where it matters: the approval-routing item on your readiness checklist must be resolved before going live, and explicitly enabling manual review workflows still requires a reviewer up front.
* Discovery tests against an external sales-agent inventory source now return the actual matching products, each with its product id, alongside the match count. For pass-through sources that compose inventory live rather than from a staged catalog, this gives you concrete, addressable products to select when setting up a sandbox test, instead of only a number.
* Test Runs now diagnoses and repairs a failed or stalled sandbox run directly from its detail. The result and retry state stay beside the exact run instead of creating a synthetic chat message.

## 4.108.1 — July 23, 2026 at 8:59 AM UTC

* Campaign re-execution now uses the current FX quote without colliding with the original media buy's locked rate. Existing booked media buys keep their original rates; no buyer action is required.
* Pacing period overrides on pre-execution media buys now apply correctly instead of returning "Media buy not found."
* Campaigns can now use existing static display creatives whose legacy format labels differ from a product's current image-format name when the asset type and dimensions match. This prevents valid campaign creatives from being excluded during media-buy creation without changing the saved creative or weakening video and other format checks.
* Wholesale pricing uploads now close the feedback loop instead of going silent on success. Every preview and commit reports which of your feed's selectors matched a product and which didn't, so a feed that priced nothing because of a selector typo or the wrong selector type is no longer a bare success. Readiness no longer reports pricing as current when a fresh, in-window feed doesn't actually match any product, and it never blocks a source you've priced entirely with operator fixed prices in your settlement currency. A new advance warning shows "pricing feed expires in N days" starting a week before the 35-day staleness cliff, instead of the first sign being products disappearing. Countries suppressed by your minimum line-item spend are now named on the product and in readiness details instead of just vanishing, and a feed row mixing a `GLOBAL` selector with per-country rows for the same selector is rejected rather than silently double-counting avails.

## 4.108.0 — July 23, 2026 at 4:59 AM UTC

* Account admins can now add, view, and remove browser origins for custom agents right from Interchange — no raw API call needed. Find the setting under **API Keys → Browser origins**.
* Scope3 platform administrators can create a separate seven-day Demo Storefront with clearly labeled synthetic Display, CTV, and Retail Media inventory. Each demo includes a sample buyer brief and outcome, plus controls to reset, extend, or delete it. Ordinary seller accounts do not show demo-creation controls. Deletion or expiration removes only the Demo Storefront and its synthetic data. No action is required.
* Go-live checklist buttons now open the right surface. "Add payout details" opens your own storefront's billing setup instead of a different account, and "Fix publisher authorization" opens your property roster instead of the ad-server source page.
* Currency mismatches in your pricing now surface before go-live instead of silently hiding products. A wholesale pricing feed must be single-currency and match your storefront's settlement currency — off-currency rows are rejected row-by-row at preview with a clear reason. A fixed product price in a different currency than your settlement currency no longer counts as a complete price (there is no FX), and setting one warns you immediately at authoring time. When every hidden product's only problem is a wrong-currency price, the Products available readiness check names the currency mismatch directly instead of reporting a generic "pricing unresolved".
* Ad-server source actions now open their connection and diagnostics workspaces directly instead of turning button clicks into Murph chat prompts.
* Buyer Activity now analyzes a selected API call directly inside the Activity page. The answer and retry state stay with the call, and the action no longer creates a synthetic chat message.
* The Campaigns workspace now opens a campaign’s editable creative-to-placement mapping task directly instead of turning the button click into a Murph prompt.
* Release Notes now explains account-specific updates directly inside the selected card. Answers and retry states stay in the Page, and the action no longer creates a synthetic chat message.
* Re-declaring a publisher domain — or resending it in a full publisher-set update — now re-checks its `adagents.json` after a short cooldown, instead of only ever checking it once. A domain that already resolved successfully no longer gets reset to "Checking" when you re-declare it, and a temporary network hiccup while fetching your `adagents.json` is now retried automatically instead of being reported as "no adagents.json found."
* Storefront adapter credential health status (expired, revoked, or errored connections) now persists correctly and triggers the expected seller notifications. A parameter-typing bug in the underlying database write had silently dropped every credential health update and its notification since the health-tracking loop shipped.
* Product discovery now labels result groups as storefronts instead of sales agents. The selector, the summary count, and the results footer all read "storefront(s)," matching how discovered inventory is actually grouped (by storefront).
* Sales agents that answer `get_products` with `input-required` — for example, sellers that need campaign or brief context before they can return inventory — are no longer incorrectly marked unhealthy or sent false "source unreachable" notifications. An `input-required` (or `auth-required`) response is now treated as a healthy, reachable reply: the live discovery leg records the source as healthy and serves any warmed catalog, and the wholesale catalog probe records the capability as unsupported rather than as an outage.
* When a Meta storefront has multiple Facebook Pages authorized for the selected ad account and no `page_id` is provided in the `execute_campaign` request, the error now surfaces the list of authorized Page IDs and names so the buyer's agent can select one and retry. Previously the error was stripped to "Upstream request failed" before reaching the buyer.
* Snap campaign creation now stops safely when Snap returns inconsistent account or status data. It verifies that the campaign is paused before launch, cleans up confirmed partial creations, and clearly reports when cleanup needs operator attention. No action is required.
* Snap media buys now verify countries against Snap's current targeting inventory, reject incompatible products and unsupported targeting before campaign creation, emit provider-valid frequency and audience shapes, and disable provider audience expansion for accepted targets.
* Spotify campaign writes and readbacks now use the account-scoped v3 endpoint as their ownership boundary when the provider omits its retired campaign account field.
* Spotify campaign reads now trust the authenticated account-scoped v3 resource when the provider emits a contradictory legacy campaign account field.
* Spotify media-buy readback now projects its top-level flight from authoritative package schedules so paused creates can reconcile exactly.
* Spotify media-buy readback now accepts the v3 `PENDING_APPROVAL` ad-set state returned immediately after a successful paused campaign create.
* TikTok campaigns now reject targeting that cannot be applied exactly, and Snap campaigns requested as paused stay paused through creative setup. Wholesale catalog reads also return complete, stable inventory metadata.
* TikTok campaigns now use current provider demographic fields, disable native targeting expansion, and verify the paused ad group's targeting and ownership before continuing setup.
* Meta now returns products on open briefs. Geography defaults to US when no country is specified, and creative format no longer needs to be stated explicitly — both gates previously blocked discovery on any brief that didn't name a country and a format keyword. LinkedIn matched-audience products no longer have US targeting silently baked in when the brief contains no geography.
* Fixed four small onboarding friction points: pre-provisioned accounts now get their invite email sent (not just the invitation record), the ad-server connection status now tells you to grant Google Ad Manager access once your service account exists instead of repeating "connect your ad server," a Google Ad Manager credential problem now names the actual fix (granting the service account access) instead of a generic "reconnect," and asking to change approval routing without admin access now tells you to ask an admin instead of a bare rejection.
* Planning a test campaign against a pass-through inventory source now surfaces real, selectable products. Previously, for storefronts that pass inventory straight through from an outside sales agent (product composition off), the planner skipped catalog discovery and returned no product candidates, leaving no way to pick a product for a sandbox test even when the source clearly had matching inventory. The planner now runs a live discovery against the source (falling back to the most recently cached pass-through catalog if the source is momentarily unreachable) so it hands back concrete product ids that a later test execution will actually find.
* Pending Operations now takes sellers directly to the approval, retry, timeline, or source-diagnostics view for each task. When a Google Ad Manager order needs cleanup, the Page offers a confirmed safe archive or a documented manual resolution. No setup change is required.
* Before your storefront activates for the first time, one end-to-end test campaign — product discovery, media buy, and creative against your own storefront — must pass. The new `publish_validation` readiness check runs the same path a buyer would, so a buyer never hits a failure you could have caught yourself. A failing run names the failing step and its root cause right in the readiness checklist, so you fix the exact problem instead of guessing. A pass older than 30 days downgrades to an advisory nudge to re-run, and storefronts that are already live are never retroactively blocked. Run it by asking your agent to run a test campaign, or with `execute_inventory_source_test_campaign`.
* Every readiness checklist item now tells you what it actually demands: `requirement` is `hard` (must be resolved before going live), `soft` (advisory — never blocks), or `platform_default` (the platform applied a sensible default, named in `appliedDefault`, that you can change any time). The checklist is path-aware and now starts with the question everything else depends on — how you sell. A new `selling_intent` check leads the list: complete once you declare it (or automatically inferred from your configuration, so existing storefronts are never blocked retroactively), and a new `approval_settings` item shows the approval posture the platform applied for you.
* Embedded sales agents now wait for trafficking acknowledgement before marking creatives active, and delivery responses serialize scheduled polling times as ISO 8601 strings while omitting the field when no further update is expected. No seller action is required.
* Sandbox inventory-source tests now explain why a test found nothing to buy instead of always reporting an empty catalog. When your source returns inventory but none of it matches the test brief's format or targeting, the failure now says the source returned products that did not match this brief (and how many), rather than claiming the source has no catalog. If the source was skipped or returned an error during discovery, that reason is surfaced too.
* Setup now asks one question first: are you connecting a sales agent you already use, or selling through Scope3? Your answer (`setupIntent` on the storefront) sets the right starting configuration automatically — pass-through storefronts are no longer offered ad-server connection steps they don't need, and sell-through storefronts start with merchandising on. The choice is reversible at any time: updating the storefront with the other intent (or flipping capability flags) switches paths, and the matching setup surfaces appear immediately.
* Connected TikTok advertisers can retry audience creates, updates, and deletes without creating duplicate provider audiences. Pixel and audience ownership is checked against the selected advertiser before a write. Nothing to change on your side.
* Buyers can now set `packages[].startTime`/`packages[].endTime` on `update_campaign` to move an individual package's flight window in place — alongside the existing `budget`, `pacing`, and `bidPrice` fields — instead of canceling the package and adding a new one to shift its dates. The new dates must fall within the media buy's own date range; every other package on the buy keeps its own window untouched.

## 4.107.0 — July 22, 2026 at 5:07 PM UTC

* If your API integration creates creatives, send the documented `format_kind` field. Buyer-created creatives now stay attached to their campaigns and reach sales agents reliably, while campaign format coverage and buyer discovery remain canonical and URL-free. Media-buy responses identify older or incompatible creatives that could not be delivered. Exact format references supplied by third-party systems remain supported at the adapter boundary.
* Sellers do not need to take action. They receive the same creative payload contract, with unsupported creatives rejected before delivery instead of arriving incomplete.
* Spotify account reads now preserve v3 account resources with tax identifiers and use the provider's current currency field, restoring directed campaign synchronization and media-buy readback.

## 4.106.0 — July 22, 2026 at 2:52 PM UTC

* Approval review is now self-contained: inspect the submitted details and
* pre-screen, decide in place, and retry a failed media-buy forward without
* leaving the Approvals Page. A retry requires confirmation and cannot create a
* duplicate booking at a source that already received the approval.
* Video hosted creatives now include a separate `clickthrough` asset when synced to third-party sales agents. VAST creatives are unaffected — click tracking is embedded inside the VAST XML and no separate clickthrough asset is sent.

## 4.105.0 — July 22, 2026 at 1:43 PM UTC

* You can now manage trusted-buyer auto-approve carve-outs directly in a portable
* Buyer Trust Page. Eligible buyers are shown by name with recent media-buy
* activity, every enable or revoke explains its exact effect, and no setting
* changes until you explicitly save it.
* You can now edit pricing rules and creative or media-buy review settings directly
* in the portable Selling Terms Page. The same configuration also works through
* confirmed assistant prompts in any compatible MCP client. Existing settings do
* not change until you save or confirm an exact update.

## 4.104.0 — July 22, 2026 at 11:31 AM UTC

* Seller Analytics and Brief History now show one consistent record for every buyer brief, from fit and posture through response, approval, outcome, and learning. You can search by buyer, brand, brief, date, or outcome, and no setup changes are required.
* You can now edit and activate your Merchandising Rules wherever you open them, review every previous version, and restore an earlier version without leaving the page. You can also ask your assistant to apply exact rules after you confirm them.
* Seller Analytics now identifies the storefront being measured, keeps catalog probes out of recent-run totals, and shows each run's posture and attribution. No setup changes are required.

## 4.103.0 — July 22, 2026 at 9:30 AM UTC

* Fixed advertiser mapping for connected ad-platform accounts while the adapter storefront is still configuring. Buyers can now finish account setup before the storefront begins transacting.
* Account admins can now preview, reactivate, or reuse saved acceptance-policy versions when no version is active. Starter policy templates also match the Page language, while other storefront members remain read-only. No action is required.

## 4.102.0 — July 22, 2026 at 6:53 AM UTC

* Meta media buys now keep exact AdCP targeting by explicitly disabling Advantage Audience expansion and verifying that setting on provider readback.
* Fixed an issue where discover\_products returned 0 results with no error for Meta adapter storefronts when the buyer had mapped an advertiser to a Meta ad account but had not globally selected a default account on their connection.
* MCP tools that declare nullable fields (for example `update_business_profile`) no longer reject valid values with a false "wrong type" validation error. The tool input validator now understands JSON Schema type unions such as `["string", "null"]`.
* Organizations with an accepted Intelligence Unit plan can now be billed on a monthly cycle. The plan commitment is charged at the start of each calendar month, and accrued usage overage is charged automatically when it crosses a threshold during the month. Each month closes with a numbered fee invoice — plan commitment, overage (IUs × rate), and payments applied. Invoice numbers are sequential with no gaps. Invoices appear on Plan & Billing → Payment & invoices and via `GET /api/v2/billing/fee-invoices` (list) and `GET /api/v2/billing/fee-invoices/:invoiceNumber` (line-level detail).
* Organizations with a saved card are charged automatically; invoiced organizations receive the invoice and pay on their existing terms. A failed charge enters the standard payment retry process, with self-serve pay-now recovery on Plan & Billing.
* No organization is charged as a result of this release. Cycle billing is switched on per organization — it requires an accepted Intelligence Unit plan, and you will know before it applies to yours. Nothing changes in how storefronts appear to buyers; this is billing between your organization and Scope3 only.
* Meta connections now recognize the current versioned webhook-field response and automatically maintain their configured ad-account event topics. No action is required.
* Seller-managed campaign readback now retains the selected product and currency when a provider omits those fields from its create response. No action is required.
* Seller-managed campaign refreshes now retain accepted product and pricing identity when the provider omits those fields. No action is required.
* Canceled Meta campaigns now reach terminal readback when Meta removes their ad sets before retained targeting records are retired. No action is required.
* Seller-managed campaign writes no longer remain pending when a provider returns the same flight dates without milliseconds. No action is required.
* Meta campaign package details now consistently include the selected product's currency and product identifiers. No action is required.
* You can now declare properties on your Property Roster before a publisher's adagents.json does — tell your agent about a site, app, or CTV channel you sell (or call `declare_roster_property` / `POST /api/v2/storefront/property-roster/properties`) and it appears on the roster marked "Declared by you". When the publisher's own adagents.json later declares the same property, the publisher's record takes over automatically. If the publisher's file later drops the property, your declaration stays; publisher-origin entries follow the file. You can remove a declared entry at any time. Nothing changes for buyers: the roster is a seller-only surface, and declared entries are never served to buyer tools or buyer-facing property lists.

## 4.101.0 — July 21, 2026 at 11:45 PM UTC

* You can now edit and activate your Acceptance Policy wherever you open it, review every previous version, and restore an earlier version without leaving the page. You can also ask your assistant to apply exact policy text after you confirm it.

## 4.100.0 — July 21, 2026 at 11:27 PM UTC

* Fixed an issue where a user added to an admin or approver role after an approval work item was created could not act on it, even when the routing policy was configured for that role. The authorization check now treats current role membership as sufficient qualification when the routing policy includes a role-based audience.
* Organization invitations can now be accepted or declined while Terms of Service are pending, so invited admins can join the organization and complete its agreement setup.
* Include account IDs and names in the model-visible `list_accounts` summary so MCP hosts can select a connected advertising account.
* Murph now consistently presents buyer budgets and delivered spend in gross (fee-inclusive) terms and no longer asks buyers whether to work in net or gross. When you need the working-media (net-of-fee) figure to reconcile against an IO line, ask Murph for the media buy's budget breakdown and it will show the media, fee, and fee-rate split.
* Meta media buys now preserve the platform's standard audience and location-presence metadata without rejecting an otherwise exact targeting match, while unknown controls and audience expansion that changes delivery remain blocked.
* Require Murph to triage customer issues before preparing a support escalation, while preserving that triage through approval and filing.

## 4.99.0 — July 21, 2026 at 9:47 PM UTC

* Fix package-level delivery breakdown missing from reporting for single-day reports whose reporting period ends at `23:59:59` (end-inclusive) rather than the next day's midnight. These reports were misread as multi-day, which dropped `by_package` metrics that carried period totals without a nested daily breakdown. Package-level impressions, spend, and rate now record correctly for these single-day reports.
* Fixed Murph approval controls disappearing when you reopened or reloaded a chat. The Approve and Reject buttons for a pending action now reliably reappear, so you can approve what you asked Murph to do instead of getting stuck repeating the request.
* RFC 9421-signed webhook deliveries from sales agents are now verified by matching the agent's `brand.json` entry to the endpoint URL we call, rather than an internal identifier. Previously, when the id an agent published in its `brand.json` differed from the identifier stored on our side, valid signatures were rejected with a generic "invalid signature" error and catalog, delivery, creative, and reporting webhooks silently failed to apply. Verification now resolves the agent by URL, caches the agent's declared id, and re-resolves automatically if it later changes, so signed webhooks keep working without manual intervention.
* The pricing-coverage warning no longer counts products that already have a fixed price. A product made buyable by a fixed price set directly on it was still counted as "unresolved" in the source's pricing sync status, so the "upload pricing" warning could ask for uploads nothing needed. The effective coverage summary now counts fixed-priced products as seller-priced.
* Murph's inventory-source sandbox test now checks up front whether an inventory source's sales agent supports sandbox (no-spend) testing, and stops with a clear explanation when it doesn't, instead of creating a test advertiser and campaign and then failing with a confusing "couldn't find the selected inventory" message. When a sandbox test does run and the source returns no inventory, the failure now says the source returned an empty catalog rather than blaming the product you picked.
* Your storefront now has a Property Roster: one place to see every publisher domain you have declared, the properties and collections that publisher's adagents.json actually resolves to, and whether your sales agent is authorized to sell each one. Ask your agent to "open my property roster", or call the `open_property_roster` tool / `GET /api/v2/storefront/property-roster`. Declared properties and collections are now persisted from each adagents.json resolution, so the roster stays accurate as publishers update their files. Nothing changes about how you sell today — this is a read-only view, and unauthorized domains show exactly what to fix. Not applicable to buyers: the roster describes a seller's own publisher relationships and is not exposed on any buyer surface.
* Storefront status now consistently recognizes that ad servers other than Google Ad Manager (SpringServe, FreeWheel, AdsWizz) price through a manual wholesale-pricing upload rather than an automatic ad-server sync. Previously these sources were reported as having unresolved pricing that needed support — and an uploaded pricing feed was ignored until an admin changed a setting — across the readiness view, the ad-server status your agent reports, and admin refreshes. Now every one of those surfaces reads the uploaded feed directly and, when none exists, prompts you to upload wholesale pricing.
* Murph now reconciles a stuck media buy against your ad server. When an order was approved or rejected directly in your ad server (for example, a GAM order handled outside the storefront approval flow), refreshing the source re-checks every non-terminal media buy (pending\_approval, pending\_start, paused) and corrects any status that drifted, so a buy that is really live no longer sits at pending\_approval. Ask Murph to refresh the source and it reconciles the status instead of only filing an escalation.
* When Meta rejects and rolls back a media buy, the connected account no longer remains stuck, so you can retry without changing your setup.
* Fix creative sync to routed sales agents when no explicit placement assignments are provided. Syncing a campaign's creatives to a media buy now binds each creative to the buy's package(s) automatically, so sales agents that require a creative→package assignment (e.g. via AdCP `assignments[]`) receive the binding instead of rejecting the sync with `INVALID_REQUEST`. Buyers who send explicit assignments are unaffected.

## 4.98.2 — July 21, 2026 at 1:38 PM UTC

* Meta product discovery no longer mistakes ISO campaign flight dates for unsupported audience age ranges.

## 4.98.1 — July 21, 2026 at 1:18 PM UTC

* TikTok campaign execution now checks the verified USD and AUD campaign minimum against the net media budget before any provider write. USD package and offering-expanded ad-group minimums are also checked. Budget failures return bounded numeric details and an actionable gross-budget correction while other provider messages remain masked.

## 4.98.0 — July 21, 2026 at 12:33 PM UTC

* Claude can now discover the correct sign-in endpoints for a direct adapter storefront instead of failing while registering the connector.
* If Scope3 has issued your storefront organization a private offer, review and accept it in Plan & Billing before your current term ends. Plan & Billing keeps the current and upcoming plans visible, and starts the accepted plan when the current term ends. Your current price and allowance do not change mid-term.

## 4.97.0 — July 21, 2026 at 11:43 AM UTC

* Official ad-platform connections now expose one canonical provider source ID, such as `meta`, across capabilities, connection summaries, account mappings, and directed subscriptions. Account mapping no longer requires callers to copy a redundant source ID; historical adapter and storefront IDs remain accepted as compatibility inputs.
* When you ask Murph to buy through a named platform such as TikTok, it now distinguishes a direct platform-authored campaign from brief-led product discovery. If your intent is unclear, Murph asks before choosing a campaign mode; direct campaigns no longer get an unnecessary discovery or execution step.
* Plan & Billing now identifies private Effective Rate Cards from the accepted offer and clearly separates IU package terms from existing media pricing.
* Claude and ChatGPT can now finish signing in to a direct Meta storefront. Interchange validates the Meta credential and selected ad account before allowing account-bound operations; no setup changes are required.
* Meta product discovery now understands explicit country names or ISO codes and exactly representable composite age ranges even when the optional brief interpreter is unavailable. Fully specified briefs return reviewable products instead of incorrectly asking for geography or age clarification.

## 4.96.0 — July 21, 2026 at 10:33 AM UTC

* Sellers can now review, create, and update their business profile in a portable Business Profile page. MCP-compatible assistants can also show that page or apply only the profile changes a seller confirms, without erasing saved details they did not mention.
* Fixed brought creatives with generated tracking URLs being removed from media buys as if they lacked required assets. Campaign assignment, package execution, and creative sync now use the same complete manifest asset projection for managed and external sales agents.
* Plan & Billing now shows the exact included IUs, monthly commitment, overage rate, and rollover terms from your accepted Effective Rate Card, including private packages.

## 4.95.0 — July 21, 2026 at 9:54 AM UTC

* Fixed `get_storefront_capabilities` returning `probeStatus: unreachable` for official adapter storefronts (Meta, TikTok, Snap, and others). Adapter storefronts dispatch in-process and always synthesize capabilities without an HTTP probe, so they now correctly report as `reachable` when the adapter is active.
* Clear product ideas shared with Murph are now added directly to \*\*Your
* requests\*\* for product review. Murph avoids duplicate asks and confirms that an
* idea is tracked without implying that it has been promised or scheduled. If
* product tracking is unavailable for the account, Murph says the ask was not
* confirmed instead of claiming success.

## 4.94.0 — July 21, 2026 at 8:54 AM UTC

* Repair existing saved creatives that were attached to campaigns but remained invisible to media buys and sales agents.
* Murph now shows support, product, and supply asks in one customer-safe request
* tracker. Product asks are explicitly tracked for review rather than promised,
* and support asks show recovery status such as the next update and whether the
* customer is still blocked.

## 4.93.0 — July 21, 2026 at 7:47 AM UTC

* If Seller Setup shows **Add payout details**, complete that step before transacting. Interchange pays you for transactions from external Sales Agent sources, so these storefronts need payout details; storefront adapters with a separate settlement agreement do not. You can now set your operator domain and settlement currencies directly in the checklist, then open the correct secure page for payout details and other required tasks. If your storefront already shows as ready, nothing changes.
* Whether you're buying or selling, requests you bring to Murph now keep their type, urgency, and blocked action together for follow-up. Product ideas stay distinct from urgent support problems, and there is nothing to change on your side.
* Buyers with a selected Meta ad account can now inspect recent processing,
* review-issue, recommendation, creative-fatigue, and product-set signals in
* `ext.scope3_provider_signals`. Existing API calls and polling behavior do not
* change when no signals are present, and there is nothing to configure. Scope3
* confirms webhook updates against Meta before they affect campaign state;
* polling remains the authoritative fallback.
* You can review your complete storefront plan terms before accepting them and find the same terms later in Plan & Billing. Existing accepted terms do not change; if a private offer requires review at renewal, it stops at the end of its term until new terms are accepted.

## 4.92.0 — July 21, 2026 at 6:22 AM UTC

* Fixed uploaded video (and other data-URL) creatives silently failing to attach. When a creative was brought into a campaign through the assistant, its media file could fail to link — leaving a creative that showed as "attached" but had no usable asset and could never be trafficked. Brought media is now uploaded to hosted storage with the storage service's canonical asset identity, the same way a direct file upload is, so it attaches reliably and can be sent to the seller for review. If an upload does fail, the incomplete manifest is removed; an existing asset-less upload is rejected with a clear instruction to delete and re-upload it instead of pretending the creative is deliverable.
* Creatives attached from an earlier conversation, a creative library, a collection, or a copy now reach new and existing media buys with their files intact. Previously, a buy could reach a seller without a reviewable creative and appear to be waiting for approval forever. Buyer and seller views now say that no creatives are attached, so the buyer knows to attach or re-upload one and the seller does not need to investigate an approval queue.
* New organizations now get oriented on the Plan & billing Overview before accepting terms: a "What stays free vs. what needs payment" explainer shows that connecting, browsing, discovery, and reading docs and pricing stay free, while media spend and intelligence-metered activities are paid — with every metered activity priced on your published price list before you run it. The plan summary also states plainly that your plan starts once the platform terms are accepted, instead of implying a plan that doesn't exist yet.
* TARS now recognizes punctuated leading Slack mentions as human-to-human
* handoffs and stays silent without running an answer-model turn. Murph follows
* the same leading-addressee rule. Direct mentions now route once and reach both
* assistants without addressee punctuation in the model prompt.

## 4.89.0 — July 20, 2026 at 11:42 PM UTC

* `GET /api/v2/billing/account` now returns your recent prepay deposits in `payment.deposits` (previously always empty): each row carries the amount, currency, effective date, reversal status, and the payment provider and reference recorded with it, projected read-only from the platform ledger. The Plan & billing page's Deposits history card populates from the same field. No action is needed — existing consumers pick the rows up with no API changes, and nothing about how deposits are made, invoiced, or billed changes.
* Monetization: none — this is read-only visibility into deposits that already exist on the ledger; it does not change invoicing, credit terms, packaging, or pricing. Persona: buyer-side (org admins and the builders integrating the billing document); sellers have no deposit surface and are not implicated.
* Cross-currency media buys now keep the exchange rate shown at booking through approval, retries, delivery reporting, and settlement. Buyers can plan against one stable converted price, and sellers receive settlement based on that same rate across every package. We audited current production buys before rollout; no existing buy needs customer action. If a future retry sends different currency terms, Interchange rejects it before spend starts—the buyer should resubmit with the original terms or a new media-buy ID.
* Rotate a generative creative provider key without disconnecting it or rebuilding its setup. Its label, advertiser assignments, and default status stay in place.
* A fixed price set directly on a product now makes it buyable on its own. A pricing option with `is_fixed: true`, a positive rate, and a currency counts as complete pricing — the product is visible to buyers without waiting for ad-server pricing history or uploading a wholesale feed (auction-priced products still need one of those two paths for their percentile guidance and availability). The readiness checklist also stops double-reporting one unresolved-pricing problem: when the "Products available" check already blocks with the upload remediation, the wholesale feed-freshness row no longer appears as a second red row for the same fix.
* The Plan & billing page now shows more of your account's history at a glance. The Overview tab lists recent commercial activity — agreement acceptances (including who accepted and when) and credit application milestones (submitted, approved with the granted limit, declined, or withdrawn) — instead of a permanent empty state. On the Usage & credits tab, day-by-day intelligence spend renders as a time-series chart with per-day amounts on hover.
* The Plan & billing chat widget now matches the web page's balance treatment: an untouched credit line (nothing funded or owed) renders as quiet credit headroom instead of a hero number, so the big figure appears only when it carries news. The usage summary also names your top intelligence-usage feature and its share of spend instead of a generic note.
* `pause_campaign` now returns the full cascade result including `totalMediaBuys`, `successCount`, `failureCount`, and per-buy `mediaBuyResults`. Previously the response always reported `success: true` even when all ADCP calls to the seller agents failed — callers had no way to distinguish a clean pause from a total cascade failure. The always-true `success` field is removed; callers should check `failureCount` to determine whether the pause reached sellers. Sellers are not affected: this change is to the buyer API response shape only; the ADCP calls to seller agents were already occurring before this change.

## 4.88.0 — July 20, 2026 at 7:44 PM UTC

* People who sign up with an organization's verified primary email domain now join that organization as members by default when the domain identifies only one organization.
* **Organization settings → Members** now shows members, admins, pending invitations, pending access requests, and the accounts each active member can access.
* No action is needed to keep this default. Admins who want to review every new member can turn off **Domain auto-join** in Organization settings. Joining the organization does not grant access to child accounts.
* Added `ad_unit_node` as a supported FreeWheel selector type for browsing ad-server selectors, matching FreeWheel's real inventory taxonomy. Previously it was missing from the selector-type list, so sellers could not browse or search FreeWheel ad unit nodes through this capability.

## 4.87.0 — July 20, 2026 at 6:29 PM UTC

* Every Plan & billing tab now shares the redesigned look. No action needed.
* Plan & pricing: your effective terms, rate provenance, and IU plan render in the same clear card-and-stat layout as the rest of the page, with plan selection and renewal management working exactly as before.
* Payment & invoices, Contracts & orders, and Media billing: same content and actions, cleaner presentation.
* Setup answers now preserve every complete command in documented CLI sequences and omit unrelated internal work from customer and prospect guidance.
* New publishers no longer dead-end on pricing or domain authorization. Readiness now measures what buyers can actually purchase: when products exist but none are visible to buyers because pricing is unresolved, the "Products available" check blocks going live and says so directly (e.g. "3 products created, 0 visible to buyers — pricing unresolved") with a link to fix it. A new `GET /api/v2/storefront/inventory-sources/{sourceId}/wholesale-pricing/template` endpoint returns a pre-filled CSV — one row per ad-server selector your products reference, with ids, names, settlement currency, and dates already filled in — so you only add CPM percentiles and monthly available impressions, and your first committed upload now enables the wholesale pricing module automatically. Declaring a publisher domain now resolves its adagents.json immediately instead of waiting for a background sweep, and every domain carries a machine-readable `authorizationReason` (`no_file`, `file_invalid`, `agent_not_listed`, `agent_untyped`, `agent_not_property_bound`, `authorized`) on the publishers API and readiness checklist, so an unauthorized domain tells you exactly what to fix — including pre-3.x adagents.json files that need upgrading to typed authorizations.

## 4.86.3 — July 20, 2026 at 5:17 PM UTC

* Buyer agents now get the exact public AdCP endpoint when asking how to connect to a storefront. Storefront operators now get the exact management MCP and Codex setup details plus independent GAM advertiser-access diagnostics.

## 4.86.0 — July 20, 2026 at 3:04 PM UTC

* Adding, managing, and diagnosing an ad-server source now happen in three focused views instead of one crowded screen. Existing connections, settings, and sync schedules are unchanged; there is nothing to migrate. Use the Connect view the next time you add a source, the source page for day-to-day settings, and Sync & diagnostics for health and run history.

## 4.85.1 — July 20, 2026 at 1:48 PM UTC

* Connected social account campaign lists are now more reliable. Incomplete platform
* responses are rejected instead of being shown as complete, reducing the chance that
* campaigns are missing from buying and reporting workflows. No action is required.
* Murph and TARS now preserve exact storefront connector commands, buyer-facing endpoints, and independent GAM advertiser diagnostics in multi-part setup answers.
* Account administrators can again see older customer-scoped `scope3_` API keys while
* migrating integrations to account API keys. The API Access page had incorrectly hidden
* legacy keys that were not attached to an individual user, even though they remained
* active.

## 4.85.0 — July 20, 2026 at 1:21 PM UTC

* Report the correct unique-publisher count when redeeming seller proposals and improve multi-seller ranking measurement.
* The Payouts tab on Plan & billing has a clearer layout. Payout activity now reads as a proper list with status chips and amounts, payout entities show as structured cards with their currencies and masked account details, and empty states explain what will appear instead of leaving blank space. Setup itself is unchanged — no action needed.
* The Plan & billing Overview is easier to read and more informative. No action needed for any of it.
* Text and spacing across the page now render at the intended size — they were previously \~40% too small next to the rest of the app.
* Sellers: the Payouts card now shows your payout entity count and setup status, with a "Set up payouts" shortcut if you haven't added one yet.
* Buyers on a credit line: until money actually moves, the balance card shows your credit headroom quietly instead of a large number restating your credit limit. The prominent balance returns whenever funds or owed amounts are real.
* The Usage & credits and Accounts tabs on Plan & billing match the rest of the redesigned page. No action needed.
* Usage & credits: your intelligence balance leads with four clear stats (used, remaining, overage, projected), bucket balances render as labeled meters, and the price list and calibration catalog read as proper tables.
* Accounts: the money view of your accounts is a cleaner table with the same delegation, fees, and usage columns as before.
* Existing connections keep working, so no action is required. Settings and Murph
* now use **Connections** and **Connected platforms** consistently.
* For buyers setting up a new Meta connection: use an Ad Account owned by a
* Business Portfolio and add the Scope3 Business Portfolio (Business ID:
* 1091793362240769\) as a partner. Seller storefronts and how buyers see them are
* unchanged.

## 4.84.0 — July 20, 2026 at 9:55 AM UTC

* Plan & Billing now separates your immutable published activity prices from the broader Intelligence Unit catalog still being calibrated. Starting rates for merchandising, Murph, generation, analysis, optimization, document understanding, BigQuery, and managed media are clearly labeled as non-billing estimates that cannot change your accepted Rate Card or debit your IU balance.

## 4.83.0 — July 19, 2026 at 10:53 PM UTC

* Meta audience syncs now reuse the same Meta audience on retries and report a
* failure when Meta does not accept every requested member change or deletion.
* Estimated audience sizes are no longer presented as exact counts, and conversion
* totals include only events Meta confirms. Existing requests do not need to
* change. A sync that previously appeared successful may now return an error;
* investigate that error and retry after the provider issue is resolved.
* The Inventory Components workspace now leads with what to do: a plain-language header explains the job (turn synced ad-server inventory into products buyers can discover), one promoted "Do this next" line replaces the static five-step banner, and mapping statuses speak seller language ("Needs a choice", "Not matched", "Suggested match"). Your accept/hide decisions now survive data refreshes instead of silently resetting — they only clear when you switch sources. The workspace also uses the correct term everywhere: it builds Products (the "Packages" tab and drafting actions were mislabeled — a package is part of a media buy, not what you author here).
* Meta connectors now turn a non-empty advertiser brief into a reviewable campaign
* strategy by default. If the objective, geography, creative format, or another
* required decision is ambiguous, the connector asks for clarification instead of
* returning an actionable product based on a guess. API callers that explicitly
* want raw catalogue discovery can continue to use `buying_mode: "wholesale"`.
* Account API keys managed by WorkOS are now the primary credential in API Access.
* Legacy personal keys appear only for accounts that still have them, with guidance to
* replace and revoke them; customers can no longer create, edit, or reveal a legacy key
* from the Interchange UI.
* Spotify connections now return only advertiser-authorized audiences, Pixels,
* and Conversions API integrations. They no longer substitute demo audiences,
* claim ignored customer-list changes succeeded, expose approximate audience size
* as an exact match count, or hide partial audience deletion.
* Buyers may see fewer audience or measurement objects because unverified and
* synthetic results are no longer returned. Server-side conversion ingestion is
* shown as unavailable instead of accepting events without a provider-confirmed
* outcome.
* No migration is required. Re-run Spotify audience or event-source discovery
* before relying on an existing object; use only the returned advertiser-owned
* identities. Customer-list replacement and conversion event ingestion remain
* unavailable until Spotify can provide safely reconcilable write receipts.
* Reddit-connected buyers now get provider-issued Pixel IDs, account-authorized server events, and retry-safe customer-list updates. Buyer and provider audience aliases share one tenant-owned operation identity, so another connection's same-account audience cannot be changed by raw Reddit ID. Failed or ambiguous Pixel, audience, and conversion operations now stop with an explicit error instead of reporting success. No credential change is required; existing unowned lists remain readable but fail closed for writes. Dedicated live verification remains in progress.
* Google Ads media-buy updates now use provider-derived revisions and exact
* readback for supported Search, Display, Performance Max, and Demand Gen
* campaigns. Pause/resume, seller-package budget, supported ad-group bid, and
* advertiser-timezone schedule changes validate account and package ownership,
* reject stale revisions before writing, and roll back or pause the campaign if a
* multi-entity update cannot be completed safely.
* Cancellation now makes an active campaign non-serving before removal and waits
* for Google to return terminal removed-campaign history. Accepted but
* unconfirmed removal is returned as a reconciliation error, not a completed
* cancellation. Reporting-only Google campaign surfaces advertise no write
* actions. These capabilities remain pending signed staging evidence and are not
* yet marked Green.
* Seller persona: not applicable. This changes only buyer-directed writes to
* connected Google advertiser accounts; it does not alter a seller storefront or
* anything buyers see about a seller.
* Fixed an existing Meta server-side conversion workflow that could stop when a
* request named a tracking source but not an ad account. Scope3 now uses the
* ownership learned by the existing tracking-source sync, rechecks access before
* every send, and stops safely when that access cannot be proven.
* If you use event-source-only conversion requests, continue to sync the Meta
* tracking sources for that ad account once first. Existing requests that already
* name an account are unchanged. This buyer-side fix does not change seller
* storefronts, ranking, or reporting.
* Existing Meta creative calls are unchanged. Buyers enrolled in seller-managed campaign writes can now attach one image-feed creative to one existing paused package with `sync_creatives.assignments`; Scope3 durably records the provider ad, reconciles retries without creating another ad, and confirms the paused provider assignment before reporting success. This is a separate post-create operation: the current assisted decision plan does not choose or bind creative and actor fields. Multiple assignments, assignment weights, placement-specific assignments, carousel, and generated formats remain unavailable.
* Buyers enrolled in directed campaign writes can now compare the targeting
* requested for a Meta media buy with Meta's current normalized targeting on
* every read. Invalid or ambiguous geography stops before any provider write,
* and missing audit data fails clearly instead of hiding what changed. The new
* read fields are additive and optional, so existing clients need no changes.
* No setup changes are required. Organization SSO sign-in now keeps each user in the correct account and gives administrators clear guidance when WorkOS membership or organization setup needs attention.
* The Plan & billing Overview tab has a clearer layout. The page now leads with a next-action card that shows where you are in billing setup (accept terms, add billing details, fund your account — whichever applies to your organization) instead of a warning banner, and a new Quick links card puts API keys and the billing docs one click away. Nothing changes about your plan, balances, or billing itself — no action needed.
* Meta campaign plans now show product pricing and budgets in the connected ad
* account's currency. Accounts that use another currency no longer see
* dollar-based minimum prices or forecasts presented as local guidance.
* Interchange checks that the plan and budget use the same currency before
* creating a campaign. Nothing changes for existing campaigns or raw campaign
* creation. If your integration uses assisted plans, send the connected
* account's three-letter currency code in both the request and its total budget.
* Storefront administrators can now manage shared API keys using their existing
* Interchange access without requiring a second WorkOS administrator role. API
* Access also labels personal-key creation explicitly and describes shared keys
* without using “programmatic access.”
* Meta, Snap, TikTok, Pinterest, Reddit, and LinkedIn connectors no longer return active
* demo audiences when provider inventory is empty or unavailable. Empty accounts
* return an empty signal list, while provider and pagination failures return an
* error so agents cannot target fabricated identity. Reddit, TikTok, and LinkedIn
* now exhaust bounded, identity-validated audience pagination before returning a
* successful signal inventory. LinkedIn validates `paging.total` when supplied
* and otherwise proves completion through bounded short-page exhaustion.
* Plan & Billing now presents IU terms as one coherent experience: a concise plan comparison on Plan & pricing, including the effective included-IU rate separately from the overage rate, and a unified balance, forecast, setup-credit, and published activity-price view on Usage & credits.
* Meta connectors now discover Pixels and Datasets from the selected ad account
* instead of substituting the ad account ID. Empty accounts return an empty list,
* and installation guidance and Event Match Quality are shown only for sources
* Meta confirms on that account. Conversion events are not sent when ownership or
* complete inventory cannot be verified. Request/context account mismatches and
* pagination that changes API version, account, or resource also fail before any
* Meta write.

## 4.82.0 — July 19, 2026 at 9:22 AM UTC

* The ad-server product setup path got a substantial clarity pass. Connecting an ad server: the create button now stays disabled until required fields are filled, jargon fields (network code, agency id, namespace, floor price) carry plain-language hints, and the Google Ad Manager steps say how access is verified. Inventory Components: a misleading "Synced" badge is gone, every Ask-Murph hand-off now confirms success or reports failure, load errors are retryable in place, and partial data loads show a notice instead of looking complete. Inventory Selector: "Selection sent to Murph" now appears only when the send actually succeeded (failures show a retry), the selection task closes itself on success, failed branch loads are recoverable per row, and the tree is fully screen-reader navigable. Error text and links meet contrast standards in both themes.
* Meta-connected buyers can keep one JPEG or PNG creative upload inside compatible
* agent hosts instead of leaving the campaign workflow to finish the asset in Ads
* Manager. The Task checks the image in the browser, uploads it to private
* storage, and returns a stable creative reference without exposing image bytes
* or temporary storage URLs to the model. Availability remains gated on private
* ingress setup and successful Claude and ChatGPT validation.
* Approvals and Source Diagnostics got a round of reliability and clarity fixes. Approvals: decisions now write an activity line to the chat, the approve confirmation says the real reason when a pre-screen is still running, failed history or pre-screen lookups no longer masquerade as "nothing here", Ask-Murph failures are surfaced, and screen readers get proper expand/collapse and severity cues. Source Diagnostics: a failed load now retries in place, partially loaded evidence shows a notice instead of looking empty, recommended next steps appear above the evidence tables, and copy buttons report when a copy fails. Error text in both widgets now meets contrast standards in light and dark themes.
* Buyers enrolled in Meta seller-managed campaign writes can now turn a brief
* into a reviewable decision plan, accept it together with the exact future
* create intent, and bind that one-time authorization to campaign creation.
* Pass-through creates remain backward compatible and are recorded as raw, so
* they cannot be mistaken for Scope3-assisted targeting or creative decisions.
* This first assisted contract stays paused and intentionally leaves inline
* creative execution to a future separate creative assignment workflow.
* The accepted Meta plan also binds an immutable product, pricing, objective,
* targeting, and campaign-name execution snapshot. Missing or mutated stored
* products fail before Meta mutation, pre-feature raw idempotency hashes still
* replay, and plan cleanup cannot cascade-delete the durable write journal. Plan
* audit rows remain available for at least 30 days and are then eligible for
* bounded best-effort cleanup on later planning traffic.
* Buyers can now list a campaign's saved creatives from the canonical plural REST
* route and compare each one with the creative created by a connected platform or
* sales agent. Existing creative reads and the legacy singular route keep working;
* no client migration or setup change is required. The optional `platform_links`
* field exposes the agent, provider creative identifier, sync state, approval
* state, and latest sync time when those values are available.
* Claude, ChatGPT, and other generic MCP clients can now inspect the exact AdCP
* request fields for a connected ad-platform storefront before they create or
* update a campaign. Clients should call `get_adcp_tool_schema` and follow its
* bounded nested paths instead of guessing targeting, creative, budget, or
* lifecycle shapes.
* Ad-server refreshes now reliably use the connected source's correct internal identifier after access or permissions are updated.
* Buyers enrolled in directed campaigns can now retrieve their complete LinkedIn
* campaign inventory through Interchange. Campaign status, currency, budgets,
* schedules, revision, available actions, and creative review state come from the
* connected LinkedIn account. If LinkedIn cannot prove the account snapshot is
* complete, Interchange returns an error instead of incomplete campaign data. No
* setup change is required.
* Connected Pinterest accounts now return complete campaign, package, and creative inventory with the account's actual currency. If Pinterest cannot provide a complete, account-safe read, the request reports an error instead of returning partial data. No action is needed.
* Pinterest media-buy updates now verify the selected account and current provider
* state before writing, mutate package budgets and flights at the owning ad-group
* or campaign CBO boundary, and reconcile every success from a fresh provider
* readback. Stale, unsupported, cross-account, partial, or unconfirmed terminal
* updates return a clear error instead of reporting unverified success. No action
* is required.
* Reddit campaigns pulled through your connected account now include the full
* account inventory and its actual currency. When Reddit cannot return a
* complete, account-safe campaign or performance view, the request reports an
* error instead of showing partial data as complete. No action is needed.
* Reddit-connected campaigns now preserve exact bounded budget changes, reject
* stale updates, and confirm cancellation from provider state before reporting
* completion. Existing campaigns and seller workflows are unchanged. No action is
* needed.
* Snap connected-account reads now return complete campaign, creative, media, audience, account, and catalog inventory with the actual account currency, campaign status, package budgets, and requested delivery snapshots. If Snap cannot provide a complete or safe read, the request returns a clear error instead of partial data. No action is required.
* Snap media-buy updates now verify account ownership and current provider state before writing, update the selected package budget, attach creatives atomically, and confirm campaign cancellation from deleted-entity readback. Stale or partial updates return a clear error instead of reporting an unverified success. No action is required.
* Spotify account and creative reads now include every paginated campaign, ad set, and ad instead of silently stopping after the first 50 results. Incomplete provider responses fail safely rather than appearing to be a complete account snapshot.
* Fixed two issues where a media buy's delivered flight dates and reported status could drift from reality: shortening a campaign's end date after it was submitted for storefront approval, but before it was delivered, could be silently dropped so the ad server kept running the original, longer end date; and a media buy that failed once and then succeeded on a later retry could be stuck showing a rejected status even though it was actually running.
* TikTok account reads now return complete campaign, ad-group, ad, creative, and requested reporting inventories or fail clearly instead of silently returning a partial result when provider pagination is incomplete.
* Buyers enrolled in directed campaign writes can now pause or resume TikTok
* campaigns and change package budgets, bids, and end dates through Interchange.
* Cancellation appears complete only after TikTok confirms it. If TikTok applies
* only part of a change, Interchange either restores the prior settings or reports
* clearly that manual review is needed. No setup change is required.
* WorkOS organization API keys now authenticate correctly as Bearer credentials,
* carry the customer context required by buyer and seller route guards, and return
* non-cacheable credential responses. M2M applications return and verify credentials
* through the environment's AuthKit domain.
* Social adapter readiness checks can now verify the same paused, future-start,
* no-spend campaign lifecycle across Meta, TikTok, Pinterest, Reddit, Snap, and
* Spotify. This adds a validation path only; an adapter is not considered live-ready
* until its signed provider canary passes. Seller storefronts and seller workflows are
* not affected. No action is needed.
* Buyers enrolled in directed campaigns can now retrieve their complete current
* Google Ads campaign inventory through Interchange, including active, paused,
* completed, and removed campaigns. Campaign currency, budget, dates, status, and
* package details come from the connected advertiser account. If Google cannot
* prove that the account view is complete and belongs to the selected advertiser,
* Interchange reports the problem instead of showing partial campaign data.
* New Google campaigns also keep the package, product, pricing option, and budget
* selected by the buyer when they are read back. They remain paused until their
* creative is created and Google confirms that the campaign is ready to run. No
* setup or client change is required.
* Buyers enrolled in directed campaign writes can manage LinkedIn campaigns with
* provider-backed conflict detection and readback. LinkedIn media buys now retain
* one stable campaign/package identity, honor paused creation, use account
* currency, and support pause/resume, total-budget, bid, end-date, and terminal
* deletion transitions. Interrupted changes are restored or paused for
* containment instead of being reported as successful.
* Existing read behavior and setup remain unchanged; writes stay limited to
* enrolled accounts.
* Invited staging organizations can now review the exact Intelligence Unit Rate Card available to them, choose a plan, keep an eligible storefront on pass-through at no cost, or decide later. Interchange records the version shown and the administrator's response so pricing can be evaluated before a production rollout. This pilot does not publish production pricing or enable metering, invoicing, or payment collection.
* The storefront Setup checklist now recovers in place when it fails to load: a Try again button retries without reopening the widget, and a failed background refresh keeps your checklist visible instead of replacing it with an error screen. The publisher-domain detail appears only while a domain still needs authorization, the go-live progress bar is announced correctly by screen readers, and error text meets contrast standards in light and dark themes.
* Buyers enrolled in directed campaign writes can now safely pause or resume
* Spotify campaigns and update package budgets, bids, end dates, and delivery
* state through Interchange. Each change checks the current Spotify revision and
* is confirmed by a complete provider readback that rejects unrequested state
* drift. Exact currency micros, strict schedules, provider identities/statuses,
* and a bounded account-operation deadline fail closed. Spotify does not offer a
* true campaign cancellation operation, so cancellation now returns a clear
* unsupported response instead of presenting a reversible pause as canceled.

## 4.81.0 — July 18, 2026 at 8:09 PM UTC

* Storefront marketplace cards and hosted AdCP capability responses now state who bills you for media, using AdCP billing-party vocabulary at the protocol-native slot (`account.supported_billing`): `agent` means Interchange clears the transaction and bills you; `operator`/`advertiser` mean the seller or your connected platform account bills you directly.

## 4.80.0 — July 18, 2026 at 7:39 PM UTC

* Anonymous Agent Registration identities can now verify read-only, zero-spend sandbox access before they are claimed by a customer organization. Claimed agents still require the organization to accept the Terms of Service before customer-bound access.
* Anonymous Agent Registration identities can now use the canonical buyer advertiser read endpoint during their zero-spend sandbox trial. Mutations, nested advertiser routes, MCP, and money-moving endpoints remain denied until claim.
* Storefront Activity now opens reliably from the Operate rail, notification
* polling no longer produces repeated request errors, and the Media Buys, Pending
* Operations, payout-currency, and source-diagnostics states stay coherent in
* Portuguese and Japanese.
* This restores the existing Activity rail action to its already-shipped typed
* Storefront tool; it does not add a new seller capability. Buyers are unaffected,
* and no action is required.
* Murph now returns portable widget launch directives directly and stages report requests as real approval controls instead of making text-only offers.
* Agent Registration requests now carry their database-backed customer role and account type through normal buyer authorization guards, allowing zero-spend advertiser reads while continuing to reject seller-bound and deleted customer identities.
* You can now see your Intelligence Unit (IU) plan, balance, and usage in one place. Plan & Billing shows your plan — pay-as-you-go or committed — plus your signup credit, any IUs carried over from last month, and your included IUs. It also shows how many you've used this cycle, a projection for the rest of the month, and any overage building up. Overage shown here isn't charged yet. There's nothing to change on your side.
* Storefront Activity now follows the seller's selected language when Calls are
* available and when the account uses the Changes fallback. No action is required.
* IU plan selection now presents prices, savings, rollover, and acceptance terms
* in a calmer two-step rate card. Plan & Billing also gives account standing,
* available funds, current intelligence spend, and any required action a clearer
* visual hierarchy without changing prices or billing behavior.
* Today's standard IU Rate Card draft is unpublished. Its displayed 4-IU activated-social-account rate is only the current coarse-denomination planning value: the final denomination and IU count are not set, and the activity is not charged. Once a finalized Rate Card is published for your organization, Plan & Billing will show one organization-wide IU plan for buyer, storefront, Murph, and other IU-rated activity, including exact plan prices, your corporate discount, rollover terms, and activity prices before an authorized administrator accepts it. When the offer becomes available, an eligible new seller billing account can receive one 100-IU credit for storefront setup, valid for 60 days and limited to one per billing organization. No action is required until an effective Rate Card is shown to your organization.

## 4.79.0 — July 18, 2026 at 4:31 PM UTC

* Storefront sellers can now run setup and day-to-day operations in the display
* language selected in Interchange. Portuguese and Japanese sessions keep widget
* labels, dates, numbers, currency, and post-action confirmations consistent with
* the surrounding interface.
* Publisher signup now keeps Storefront intent through account creation and
* leaves optional marketing consent off by default. No action is required.

## 4.77.0 — July 18, 2026 at 11:00 AM UTC

* Meta creative sync now rejects native-localization requests before uploading media instead of silently creating an untranslated ad.

## 4.76.0 — July 18, 2026 at 9:20 AM UTC

* Enrolled buyers can turn an advertiser brief into a read-only Meta campaign plan with explicit objective, audience, creative, measurement, and setup decisions. Ambiguous, excluded, or unsupported targeting returns questions instead of guessed inclusions. This capability remains gated pending signed live evidence; existing product listing and campaign creation calls do not change.
* Meta directed-campaign mirrors now fail safely instead of omitting native exclusions, audiences, locales, behaviors, or placement constraints. When a complete account sync cannot represent an ad set's targeting, the prior complete mirror is retained and the subscription reports an error.
* Meta directed-campaign delivery now returns every ad-set package, including zero-delivery packages, account-currency spend, and the provider's effective campaign status even when optional catalog attribution is unavailable. Invalid package totals, currency precision, or requested device reports fail closed. Provider-suppressed geography attribution remains visibly truncated instead of failing the authoritative campaign total or appearing complete.
* Buyers enrolled in Meta directed campaign writes can now keep one creative ID from upload through paused campaign creation, then read back its assigned ad set and Meta review status. Before syncing an image, provide an authorized Facebook Page ID (and an Instagram account ID when needed) and host the JPEG or PNG at a public HTTPS URL. Campaigns remain paused while Meta reviews the creative.
* Meta account connections now keep the last complete account list when a refresh fails, and buyers can select only active advertiser accounts. Account status, hierarchy, labels, and currency remain consistent across refreshes, including correct financial values for currencies such as JPY and KWD. No setup change is required.
* Managed Google Ad Manager orders now stay pending while forecasting finishes and count as approved only after GAM confirms approval.
* Meta creative sync and inline offering creation now discover Facebook Pages authorized for the selected ad account. When exactly one Page is available it is selected automatically; ambiguous selection returns paged ID-and-name choices, and unauthorized Facebook Page or Instagram identities fail before any provider or ledger write.
* Meta directed campaign creation now verifies the provider campaign, ad set, ad, creative, source media, and configured status before reporting success. Malformed, substituted, cross-account, or partially activated provider hierarchies fail closed and are cleaned up safely.

## 4.75.0 — July 18, 2026 at 12:26 AM UTC

* Buyer teams can now set up credentials for agents, scripts, and backend integrations without contacting Scope3. Organization admins can manage API keys in **API Access** settings, while existing `scope3_` keys keep working. Test a replacement with a successful request before retiring a working key.
* Campaigns can no longer commit more spend than your available Scope3 credit. When you activate a campaign — or raise its budget — in a way that would push your committed spend past what your funding and credit line cover, the API now returns HTTP 402 `CREDIT_LIMIT_EXCEEDED`, with the shortfall and your current balances in `error.details`. Creating a campaign is never blocked: if its budget already exceeds your available credit, the create response carries a non-blocking warning instead. Free up committed budget by pausing or archiving other campaigns, or add funds, to clear the block.
* This is gated by a feature flag and off by default, so nothing changes for your account until it is enabled.
* Before creating a Meta campaign, include an explicit country for every package and every postal-code target. Campaign creation now stops if Meta applies different geography, protecting brand and agency teams from approving spend against the wrong market. Existing campaigns and requests that already include valid geography need no changes.
* Fixed `PayloadTooLargeError` (413) on `update_media_buy` webhook callbacks. Seller-returned `affected_packages` payloads for multi-package updates can exceed the previous 64KB body-size cap; the limit is now 15MB (matching `get_products`) for `update_media_buy` and remains 64KB for all other task types.
* Also fixed async `update_media_buy` requests not being tracked correctly: the task ID a sales agent returns for a still-processing update is now persisted, and the webhook that later confirms completion is now matched against that task ID (in addition to our own buyer reference) when correlating it back to the right media buy.
* Fix stale source health for external sales-agent inventory sources. Source-health diagnoses now offer a read-only discovery recheck that records the actual `get_products` result before returning, and an hourly background recheck clears recovered sources without waiting for buyer traffic.
* Catalog-driven social buys now preserve item-level delivery attribution when
* packages use the canonical AdCP catalogs array. No action is required.
* Seller-managed TikTok campaign writes now accept canonical offering and job catalogs while continuing to reject catalog types the provider cannot apply.
* You can now update a media-buy package's pacing to `front_loaded` (previously rejected only for packages, though products already supported it), sync a catalog feed with `feedFormat: "tiktok_shop"`, `"pinterest_catalog"`, or `"openai_product_feed"`, and set a catalog's `type` to `"app"` — all previously rejected due to hand-maintained enum lists that had silently drifted from the underlying protocol.
* Improves managed-storefront buying by applying channel, market, and format filters consistently; presenting canonical creative formats without legacy media-type leakage; surfacing per-source rejection reasons when a buy fails; and accepting clear natural-language approvals for the exact pending action while failing closed on ambiguous replies.
* Fixed the buyer creative library tool (`list_advertiser_creatives`) so it shows every creative saved on an advertiser by default, matching what buyers already see on the web platform. Previously it only showed creatives explicitly promoted to the reusable library, so a creative uploaded on the web but not yet promoted could be invisible to an agent over MCP and fail to attach to a campaign.
* Fixed a bug where an uploaded creative (for example, an audio ad) could be saved as the wrong media type and left unplayable when its upload reference never resolved to the actual file — most commonly a same-session file reference reused on a later turn. The upload is now rejected with a clear "please re-attach it" notice instead of being silently guessed as an image.
* Storefront delivery polling now retries within the hour when a source returns no usable per-day delivery for the day yet (e.g. its numbers finalize a few hours after midnight), instead of waiting for the next scheduled read. Retries are bounded per slot: after several hourly attempts without data the route defers to its next fixed read and records a diagnostic, so a source that reports no daily breakdown can't be polled indefinitely. Each scheduled read starts a fresh retry cycle, so a day's failures never carry into the next.

## 4.74.0 — July 17, 2026 at 6:39 PM UTC

* Fixed the storefront catalog-change webhook for sellers connected as a direct agent (not a managed/ESA connection): it previously accepted the request but never actually refreshed the cached product or signal catalog, so proactive change notifications were silently ignored.
* `execute_campaign` now returns an error instead of a false success when a campaign has never launched and has no media buys to execute (for example, no product was ever selected). Previously this case reported `success: true` with `mediaBuysExecuted: 0`, leaving the campaign silently stuck in draft while telling the buyer it was activating. Re-executing an already-active or paused campaign with nothing new to dispatch still reports a successful no-op, unchanged.
* Fixed two issues with media buy budget updates on multi-format buys. Budget changes could be applied to the wrong ad format when a seller confirmed packages back in a different order than they were sent, and a budget change for a format without an approved creative yet could be silently dropped instead of reaching the seller.
* Fixed a bug where Murph could show raw placeholder text like "(that field, that field, that field)" in a reply instead of a clean sentence, when it needed to redact more than one internal detail at once.
* You can now target `reach` as a campaign optimization goal (previously rejected due to a stale internal list). Validation errors for an unsupported optimization-goal value now name the specific field and list the accepted values, instead of a bare "Invalid input" message.
* Social delivery reporting now retains catalog-item attribution in durable,
* provider-isolated storage. Aggregate delivery remains available if optional catalog
* enrichment is temporarily unavailable. No action is required.
* Plan & billing tightens up from design review: internal platform usage no longer appears in your intelligence usage, unknown renewal data is hidden instead of labeled "not available", rate rows explain decisioned vs routed in plain language, the payer-of-record card states its scope, and placeholder cards for unshipped features are gone.
* Murph now stays silent when an ordinary human-to-human Slack message is mistaken for an account-specific request, instead of interrupting with a prompt to tag Murph.
* The storefront catalog-change webhook now returns the underlying reason (e.g. "brand.json fetch returned HTTP 404") in the error body when RFC 9421 signature verification fails because your agent's `brand.json` couldn't be fetched, instead of a generic "verification unavailable" message.

## 4.73.0 — July 17, 2026 at 2:01 PM UTC

* If you sync event sources without a `mapping` object, nothing changes. If you do send `mapping`, you must switch its field names to camelCase — the retired snake\_case keys are now rejected with a validation error instead of being silently dropped, so integrators wiring event-source sync should update before their next call. The `mapping` object (a Scope3 extension on `sync_event_sources`) now uses `eventIdField`, `eventTypeField`, `eventTimeField`, `userMatchFields`, `valueField`, `currencyField`, `orderIdField`, `contentIdsField`, `consentField`, and `dedupeStrategy`, matching the shape event-source reads already return — this fixes the opaque "Invalid input" a caller hit when mirroring a read back into a write. The ADCP `sync_event_sources` fields themselves (`event_source_id`, `event_types`, `allowed_domains`, `integration_platform`, `test_event_code`) are unchanged, and there is no seller-facing change.
* Wholesale optimization now rejects unsupported pricing models before pacing or
* profitability calculations instead of silently treating them as CPM, zero, or
* missing revenue.

## 4.72.0 — July 17, 2026 at 12:17 PM UTC

* Agents can now request a payment method: the `add_payment_authority` task returns a single-use secure link the cardholder opens to enter the card directly with the payment processor (no sign-in needed), and the task reports verified once the card is saved. Card details never pass through the agent or the API.
* If a card payment fails, you don't lose access. We retry automatically at 3 and 7 days and email you at each step. If the charge still hasn't gone through after 10 days, we pause new paid actions only — new credit spend, media commitments, and upgrades — while reporting, data export, campaigns already delivering, and your Plan & Billing page keep working. Update your card and pay, and everything resumes the moment the charge succeeds. We'll also email you about 30 days before a saved card expires.
* Creating another account under an existing organization no longer treats the
* organization container as a storefront, and newly created buyer or storefront
* accounts now stay attached to the same canonical organization record.
* Fix routed media buys failing to forward to sales agents that require an explicit buyer confirmation. A storefront-approved routed buy is now forwarded with `buyer_confirmed: true`, so sales agents that gate `create_media_buy` on buyer confirmation accept the buy instead of rejecting it (previously surfaced to the seller as "Forward failed"). The flag is set only on the create forward — the buyer's storefront submission plus the seller's approval are the confirmation — and never on subsequent `update_media_buy` calls.
* Creative-format documentation and API descriptions now consistently label
* `{agent_url, id}` references as legacy-v1 compatibility data. Canonical AdCP
* 3.1 product formats remain URL-free `format_kind` plus `params` declarations.
* Media billing polish from a design review: currency renders as a chip everywhere, loading placeholders reserve the right space, the resolution chain marks the matched step with a check (not color alone), the target picker is screen-reader labeled, and the country field shows its help and errors inline like every other field.
* On phones, the address rows in the billing-entity and payout forms now stack instead of crushing; radio choices and dropdown errors render through the standard controls.
* Embedded sales agents now use URL-free AdCP 3.1 creative declarations, pass
* inline HTML tags and their dimensions through to Google Ad Manager, return
* wire-valid pending statuses, and preserve seller approval tasks when a recovered
* media-buy request is replayed.

## 4.71.2 — July 17, 2026 at 11:58 AM UTC

* Cross-currency storefront buys now convert both package budget and bid price
* back to the seller's settlement currency before forwarding to an inventory
* source. This keeps the CPM and resulting delivery goal consistent with the
* booked FX budget.
* ## slack
* Cross-currency storefront forwarding now keeps source CPM bids and budgets in
* the same settlement currency, preventing incorrect delivery goals.

## 4.71.0 — July 17, 2026 at 9:46 AM UTC

* Upload CSV, XLS, or XLSX modular avails files directly through the storefront API and receive the same normalized, row-level preview used by structured feed inputs before confirming a commit.
* Storefront media-buy delivery reporting now refreshes reliably instead of being skippable for a full day. When an upstream source hasn't finalized a day's delivery at read time, the route is now retried within the hour until the data lands, rather than waiting until the next day. Every delivering media buy is also read twice daily instead of once, so late-finalizing delivery is picked up the same day.
* Meta campaigns created through directed buying now stay paused until they are deliberately activated. Budget changes use the selected Meta account's currency, unsafe increases are blocked during testing, and canceled campaigns return a complete final state. Nothing to change on your side.
* Connected-platform campaign mirrors now preserve campaigns that a provider omits from broad account listings. Interchange verifies omitted campaigns through bounded, resumable reads before treating absence as authoritative, so provider-canceled campaigns and their package history remain available while incomplete reads retain the last valid mirror. Nothing to change on your side.

## 4.70.1 — July 17, 2026 at 6:00 AM UTC

* Ad-server-backed product updates now preserve canonical AdCP 3.1 format options as URL-free `format_kind` and `params` declarations. Full product updates no longer drop these options or reintroduce legacy creative-agent URLs.
* ## slack
* Canonical product format options now survive the ESA full-update flow without
* agent URLs. Legacy creative-format references remain available only for
* explicit v1 compatibility.

## 4.70.0 — July 17, 2026 at 4:03 AM UTC

* Talk to Murph with an MP3, WAV, or M4A attachment. Murph can understand the spoken content for the current conversation while keeping the original file available to creative tools. Nothing to change on your side.
* Buyer integrations now receive canonical creative formats without agent URLs. Existing legacy format IDs remain available in their compatibility field, so no buyer changes are required.
* Storefront operators can now retry an approval that was incorrectly marked as forwarded. The recovery option is available only when every source attempt failed before creating an upstream media buy or task.

## 4.69.0 — July 17, 2026 at 3:08 AM UTC

* Buyers can now discover live, account-specific products in their own currency when a seller prices them in another marketplace-supported currency. Nothing needs to change on either side.

## 4.68.0 — July 17, 2026 at 2:18 AM UTC

* Clarified Intelligence Units (IUs) in the glossary and linked the term to current
* plan and billing details.
* The seller-managed campaigns alpha is now available to an expanded social-adapter test cohort. Enrollment exposes account mirroring and delivery reads; it does not subscribe accounts automatically or authorize upstream writes.
* Meta campaign mirrors now use provider-supported account filters and ad review fields, allowing account-wide reconciliation runs to succeed. Nothing changes in existing requests.
* Fixed wholesale pricing CSV uploads in Murph chat that silently failed to resolve when a seller attached the file without narrating it, and fixed the ad-server source id Murph could pick when pointing a wholesale pricing upload at the wrong source.
* Generating creative from an attached image now grounds the draft directly on your upload — no reference-picker detour — and generation on a bring-your-own provider key no longer requires a connected seller storefront. The reference picker opens only when you ask to pull in more library references.
* Customer release messages now preserve every approved update, use clearer customer-facing language, and state whether action is required. Recipient selection remains based on declared audience and feature relationships rather than generated copy.
* Code examples and tables in Murph answers are now easier to scan. Fenced code shows its language and can be copied in one click, while wide tables stay contained within the conversation. Nothing to change on your side.
* Media billing entities can now be managed end-to-end from the tab: set any entity as the org default, or delete one — with the routing consequences stated before you confirm. Also fixes two labels: the entity form's currency field now reads "Invoice currency" (it previously showed a payout label), and usage cards now show readable feature names instead of raw meter keys.
* Plan & billing no longer shows a "Storefront pricing is unavailable — retry" warning when the viewer simply doesn't have permission to see plan terms; the retry could never succeed for a permission outcome.
* Reject invalid execution types, source and agent statuses, and protocols in v2 storefront source diagnostics responses.
* Fixed the extra line spacing in your sent chat messages so multi-line inputs read at the same comfortable leading as Murph's replies.

## 4.67.0 — July 17, 2026 at 12:02 AM UTC

* Murph now completes long multi-part storefront setup answers and uses the exact documented storefront management connector and authentication steps.
* Campaign creatives now include `storefrontReviewStatus` showing whether a storefront operator has approved, rejected, or is reviewing a creative (`pending`, `approved`, `rejected`, `revoked`). Null when the storefront uses automatic approval or the creative hasn't been synced yet.

## 4.66.1 — July 16, 2026 at 10:07 PM UTC

* Media buys routed to a third-party sales agent no longer fail with a false "source unavailable" when the agent is simply slow to respond — the forward timeout now matches the allowance already given to managed sales-agent sources.

## 4.66.0 — July 16, 2026 at 8:57 PM UTC

* Data Delivery documentation now accurately lists GCS, S3, and Azure Blob as the
* supported destinations. Snowflake and Databricks remain unsupported reserved values.
* Buyers can now use seller-managed campaigns with any active storefront. A campaign appears as soon as the seller accepts a create, while account history, delivery reporting, creates, and updates each report their own support and health.

## 4.65.0 — July 16, 2026 at 7:38 PM UTC

* Tightened the buyer navigation rail so section headers sit flush with their rows and the groups share the same even spacing, and made the "add to chat" affordance appear consistently on Catalogs, Conversions, and Activity alongside Campaigns and Creatives. Also fixed assistant chat messages where a standalone year (e.g. "2026.") was misrendered as a numbered list and where dates could break across lines.
* Buyer and seller account admins now get a diagnostic ID when SSO setup fails,
* and replay-safe setup checks stop after 15 seconds. Retry once if this occurs;
* include the diagnostic ID if you contact support.
* Managed GAM sources now warn when a successful advertiser sync returns zero
* visible advertisers, with guidance to verify the service account's GAM role and
* team access before refreshing. A successful inventory sync no longer masks
* this separate advertiser-access problem.
* Storefront operators can now see whether each recorded booking is
* Interchange-cleared or seller-cleared on the existing Media Buys page.
* Historical bookings remain clearly marked when their method was not recorded;
* buyers do not see a new seller attribute and cannot choose the method per buy.

## 4.64.0 — July 16, 2026 at 7:15 PM UTC

* Fixed duplicated impressions and spend in reporting metrics for media buys whose delivery was ingested both before and after source attribution was added. Such a buy could have two copies of the same day's delivery — one unattributed, one source-attributed — and both survived deduplication and were summed, doubling the totals. Reporting now prefers the source-attributed rows for each media buy and day, and keeps the unattributed copy only when no source-attributed row exists. Applies to both buyer and storefront reporting, in summary and daily timeseries views.
* Organization administrators can schedule a paid storefront plan to end at its
* term boundary and see the exact timestamp the storefront becomes Free. They
* can reinstate automatic renewal before the governing cutoff if the plan can
* renew on the same terms. Every decision remains in renewal history.
* Buyer impact is not applicable to this launch. Buyer pricing and workflows,
* storefront ranking and rendering, and inventory availability do not change. At
* term end, only the seller's commercial plan state becomes Free; this release
* does not add or change Free-plan entitlement or pass-through enforcement.

## 4.62.0 — July 16, 2026 at 5:14 PM UTC

* Fix delivery reporting dropping metrics on single-day reports. When a delivery report covers a single day, its reporting rows now read from the report's root totals and per-package totals (which carry the full metric set, e.g. completed views) instead of the daily-breakdown entry, which a source may leave sparse. Multi-day reports are unchanged. Single-day rows are still stamped at the real delivery day, so this does not affect deduplication.
* The "Add a card" option now appears for organizations that already have a credit line or funded balance — a card can be added alongside existing funding.
* Campaign media-buy status now continues to show completed and other terminal buys after background polling finishes, instead of incorrectly reporting that the campaign has no media buys.
* Settings danger zone now shows buyer-appropriate content. Previously, buyers in the Settings modal saw a seller-scoped archive control; they now see a correctly labeled disabled archive option with buyer-specific copy across all supported locales.
* `get_media_buy_status` now reports `source_rejected_creatives` as a `pendingReason` when all assigned creatives have been rejected by the source. Buyers can see this in one call instead of investigating separately why a buy is stuck. Not applicable to sellers — this surfaces seller-originated rejection verdicts to buyers; no seller behavior changes.
* Campaign creatives now include a `sourceSyncStatus` field showing whether each creative was approved, rejected, or is pending review at each source, with the verbatim rejection reason when rejected.
* Nav avatar now shows two initials (first + last) instead of a single letter. Settings rail groups user-scoped settings (Murph preferences, Notifications) under "Your preferences" separate from account-scoped settings. Murph room share is now a single popover that keeps visibility toggling and link copying as separate, non-entangled actions. Both buyers and sellers see these improvements across the shared navigation and settings surfaces.

## 4.61.0 — July 16, 2026 at 2:55 PM UTC

* The buyer navigation rail now groups sections into two categories: **Discover** (Marketplace, Activity) and **Manage** (Campaigns, Creatives, Catalogs, Conversions, Reporting). The advertiser selector is always visible at the top of the rail. When no advertiser is selected, Manage sections show a prompt to select one.
* Campaigns list widget now uses a chip-filter and card-stack layout instead of a data table, matching the 360px chat surface target. Status filter chips (All, Active, Paused, Draft, Completed, Archived) narrow the list in place. Each campaign card shows the campaign name, status, flight dates, budget, spend, and a pacing bar.
* Adds the reversible operating contract for one-storefront modular inventory
* source pilots and clarifies that removing pilot access preserves held and
* booked capacity, open human work, and pending reporting until their normal
* lifecycle actions resolve them.
* Correct storefront approval webhooks to use the canonical AdCP media-buy task protocol and validate every task payload against the SDK wire schema before delivery.
* Fixed a bug where background polling for async `get_products` responses sent the wrong task ID to the seller. When a seller wraps a `get_products` call as an async task, the background poller was using an internal SDK correlation UUID instead of the seller's actual task ID (e.g. `tsk_get_products_...`), causing all poll attempts to fail with the seller reporting unknown task IDs.
* Fixed `update_campaign` rejecting media-buy bid-price changes with an opaque "Invalid input" error. The per-package and per-product update fields now use camelCase — `bidPrice`, `productId`, `pricingOptionId` — matching the casing campaign reads return and the rest of the buyer API, instead of the snake\_case (`bid_price`, `product_id`, `pricing_option_id`) the update schema previously required. This removes the read/write casing mismatch that let a budget-only update succeed while an otherwise-identical bid-price update failed. Callers sending the old snake\_case names on `mediaBuys[].packages[]` or `mediaBuys[].products[]` must switch to the camelCase field names.
* Feed-backed modular campaigns now preserve their booked package rate when discovery supplies the catalog's camelCase pricing shape or omits an unambiguous single-option pricing ID, so final delivery can enter reporting without a pricing error.
* Modular storefront reports now include the booked package pricing required by report processing, and completed route status reaches the buyer media buy promptly instead of waiting for the hourly reconciliation sweep. Nothing to change on your side.
* Plan & billing gains a Media billing tab: define the legal entities Scope3 invoices for media spend, attach them to advertisers or accounts, and ask "who gets this invoice?" for any advertiser — the resolution chain shows exactly why.
* Modular avails previews now keep valid rows visible while reporting rejected rows and normalization warnings with stable row-level diagnostic codes.
* Sellers can now use Activity to inspect their storefront's tenant-scoped API calls, open safe call detail, and compare those calls with storefront Changes. Buyers keep the same Calls workflow with buyer-specific Changes, now on the shared Activity contract used by portable MCP hosts.
* API Activity remains included in the beta at no incremental charge.
* Murph now uses conversation and connected-room context to resolve informal company and product names before concluding they are unknown, and asks with concrete candidates when the meaning remains ambiguous. Scope3 internal admin and staff operations also stay out of customer-visible Activity history.
* Explain how to choose the supply setup behind a storefront and what sellers need to prepare for a modular source.

## 4.60.0 — July 16, 2026 at 10:13 AM UTC

* Help and support links are now in the "?" header menu (no longer buried in the sidebar footer), the Activity tab is always visible in the sidebar without needing to select an advertiser first, and AI usage and Danger zone sections are now available in buyer settings.
* Fixed several visual bugs in buyer and seller widgets found during the 360px parity audit: campaigns widget is now readable in dark mode (hardcoded white backgrounds replaced with theme tokens); media-buy and creative names in the campaign detail wrap to two lines instead of truncating; buyer widgets (reporting metrics, creative intent, reference picker, catalog mapping, event sources) no longer overflow the 360px width target; stat label acronyms (CTR, CPM, etc.) now render in correct uppercase; meta-line items in the seller media-buys list are separated by visible dots.
* Fixed ESA storefronts rejecting HTML creative format IDs. HTML creatives with detected dimensions (e.g. 728x90 banners) were assigned legacy fixed-size format IDs that the ESA validator rejects. Canonical parameterized refs are now produced at creative creation time and translated at the forward boundary.
* Media buys with inline creatives that don't match a product's format now forward to `pending_creatives` instead of failing with an error. Assign a compatible creative to complete the buy.
* Generative creative now grounds on the references you pick in the reference picker. Library assets and past creatives you select are passed to the model as style references — matching their look, color, and treatment — instead of being noted but ignored. A locked product you add alongside is preserved as a product reference, and references you add mid-session while refining are picked up too. Previously these selections reached the session but never the generator, so output could come back off-brand.
* Organizations can now define media billing entities — the legal entities Scope3 invoices for media spend. Most specific wins: an advertiser's entity beats its account's, which beats the organization default. The `/resolve` endpoint answers "who gets this invoice" for any advertiser or account. No entity is created automatically — add your organization's first one to start routing.

## 4.59.0 — July 16, 2026 at 1:21 AM UTC

* Ask Murph to put your logo on a generated creative and it now sources the logo straight from your brand — no more being asked for a logo URL you don't have. If your brand has no logo on file, the creative is generated without one rather than stalling.
* Generative creative sessions now flag when the number of concepts you get back
* doesn't match the number you asked for. If the generator returns fewer (a draft
* failed) or more directions than requested, the session carries a clear notice
* alongside the drafts instead of silently dropping or adding them — and the
* plan's reported concept count reflects what was actually requested.
* Buyer Activity links now stay on Activity instead of reloading into an empty Murph conversation. Calls and their debugging details remain available in place, with nothing to change for API integrations.
* Buyer reporting now labels spend, eCPM, and CPC with their actual currency across the dashboard, in-chat reporting, time-series responses, and CSV exports. Mixed-currency time-series totals leave money blank instead of adding unlike currencies, and summary requests fail rather than relabel unconverted spend when no FX rate exists. Modular storefront final reports also enter buyer reporting when they include reconciled per-day delivery and an explicit currency. The new CSV currency field is appended so existing column positions do not move. Nothing to change on your side.
* External AdCP buyers can now update or cancel an endpoint-directed campaign through
* the addressed storefront while Interchange preserves governance caps, durable
* idempotency evidence, SCD2 budget lineage, dual-key identity, dark usage metering, and
* campaign commitment reconciliation.
* After you pick a creative direction and it builds across your placements, you can now go back to the directions and switch to a different one without starting over. A "← Back to directions" control returns you to the picker with your current direction highlighted and the other already-generated directions still one click away — no re-running a fresh set of generations.
* You can now pick a draft creative direction just by naming it in chat — "let's use the zine/DIY one", "go with the surreal option", or "direction 3" all fan out that direction's placements. Previously only the "Use this direction" button worked; typing the choice made Murph ask you to copy a session ID and variant ID off the card.
* When you tune a generated creative across placements, each preview now shows at its real shape — a leaderboard reads wide-and-short, a half-page tall-and-narrow — instead of every placement rendering as the same uniform box. The tiles pack into a masonry grid and keep their pixel-dimension label, so a 728×90 is instantly distinguishable from a 300×600 while you decide which ones to keep.
* The reference picker now always shows all three source tabs — Sourced materials, Past creatives, and Catalog — even when a source is empty. Previously the tab bar disappeared whenever only one source had items, collapsing the picker to a single flat list and hiding the fact that references can come from any of the three. Empty tabs now carry a proper empty state (attach assets, connect catalog) so you always see every source and how to fill it. The item list is also capped and scrolls, so the picker no longer grows unbounded on large libraries.
* Wide and tall placements now generate at their real shape. When a required placement has an extreme aspect ratio — a leaderboard banner or a skyscraper — and your OpenAI-connected session would otherwise crop it to fit, the render is routed to a connected generator that composes that shape natively (Gemini or FAL). It runs on your own connected key for that provider and is billed to that vendor account, the same as any generation on it. If you haven't connected a native-ratio generator, the placement still renders on your session provider with a heads-up that it may crop — nothing changes for you until you connect one.
* Starting a generative creative session without naming a concept count now generates three draft directions by default, instead of a single draft. Give a number to get exactly that many; ask for one and you still get one. Behind the buyer-creative-v2 + buyer-generative-creative flags.

## 4.58.0 — July 15, 2026 at 11:13 PM UTC

* Generated creative now reflects your brand — colors, tone, and tagline from your brand profile reach the image generator on every render, including after you pick a direction and fan out to placements. Previously the brand reference was dropped when a creative session was saved, so reloaded refine and placement renders generated from the brief alone and ignored the brand.

## 4.57.0 — July 15, 2026 at 10:35 PM UTC

* No action is needed: this release does not publish a paid storefront Rate Card,
* move any storefront to a paid plan, start storefront-plan charges, or change
* buyer pricing. A new-storefront signup can review Free or paid choices once an
* effective Rate Card is separately published. An authorized administrator of an
* existing storefront instead uses Plan & Billing to review the exact version,
* corporate discount, prices, setup grant, committed-IU rollover policy, and term
* before accepting; the page also shows current Free or paid status and immutable
* plan history.
* Buyer Catalogs widget: uploaded (file-based) feeds now show a **Reupload** action instead of a disabled "Sync now" — syncing only applies to hosted URL feeds — and their status reads "Uploaded" rather than "Synced". The activation action is now **"Save plan"** (it persists the activation plan; live execution across campaigns, syndication, and creative is not yet available), and the plan preview no longer advertises a creative-asset count — catalog-driven creative generation stays gated until brand identity and per-format output are in place.
* Storefront operators can now upload their wholesale pricing feed for ad-server-backed inventory sources directly in Murph chat, with a full preview of accepted and rejected rows before anything is committed.
* Managed ad-server sources on adapters without an automatic pricing sync (today, everything except Google Ad Manager) no longer show a false "degraded / contact support" pricing status or retry a sync that cannot run. Instead the source stays healthy and surfaces an actionable prompt to upload wholesale pricing, which is how these sources are priced today.
* Fixed the Campaigns widget lingering in a chat it wasn't opened in. Opening a recent chat now clears any Campaigns widget from the previous view, so widgets only appear where they belong.
* Creative library and reference-picker widgets now show each image creative's thumbnail. Uploaded and generated image creatives previously fell back to a generic format-type icon because a preview was only derived from a processed-HTML asset; the creative's own image is now used when no HTML preview exists.
* Fix: when you upload creative into chat and Murph asks which campaign to attach it to, answering in a later message now attaches the files you already uploaded — instead of Murph saying it can't see any files and asking you to re-attach them.
* Fix duplicate Slack approval callbacks so one click cannot both file a request and ask for approval again, and give request-tracking guidance that matches the current chat host.
* Generative creative now grounds on your actual inputs and lets you choose a direction before it builds. When you generate creative, Murph presents a few on-brief concept directions to pick from (instead of auto-selecting one), and the direction you pick is rendered across every placement — carrying that concept, your brief, and your uploaded reference images through to each render. Uploaded references now also carry across turns, and placement renders generate in parallel so results come back faster.
* Buyers enrolled in directed campaigns can now send a buy to any active storefront
* while Interchange keeps the campaign, contract, billing context, and delivery
* reporting around that seller-managed buy. Campaign responses identify whether
* execution uses a connected account or the storefront endpoint.
* Fixed under-booking of realized media spend on storefront buys fulfilled by more than one seller. Each seller's delivery is now recorded as its own ledger entry, so a buy's booked spend is the sum of every seller's realized media instead of collapsing to a single seller's figure. Buys served by a single seller and buyer-direct buys are unaffected. In-flight multi-seller buys are corrected automatically as their deliveries next report.
* When you tell Murph which references to ground a generated creative on ("use the ones I just uploaded", or name specific creatives), the reference picker now opens with those already checked. Murph passes the named creative ids to the picker, which pre-selects them on the matching tab — you confirm or adjust instead of re-finding and re-selecting them, which matters as your library grows.
* Slack Product Updates now include an **Unsubscribe** button. Use it to stop future Product Updates in that channel without changing your account's release history or other connected channels.
* Campaigns created by an external AdCP buyer through one storefront now report
* `mode: directed`, matching the storefront-managed execution model. Inbound direction
* remains provenance and does not create a separate campaign mode.
* Re-adding an event source that was previously removed via `sync_event_sources` with `delete_missing` now restores it instead of failing with a duplicate-identifier error. The revived source keeps its identity and any sales-agent syndication links; its configuration comes from the re-add payload, and its ingestion health resets to `not_seen` until new events arrive.
* Choose whether source outage alerts appear in your primary Slack channel and how long an outage must last before an alert is sent: 10, 30, or 60 minutes. Use the buttons on an alert or ask Murph to change the setting. Immediate in-app and email health notifications remain on.

## 4.56.0 — July 15, 2026 at 3:55 PM UTC

* When adding your first child account triggers an automatic account structure change, you now see a notification explaining that your billing and contracts have moved to the new parent account.
* Sales Agent Diagnostics can now run its no-spend discovery test, refresh capabilities, and reload durable test results from the in-product widget. **Run discovery test** now reaches the selected external sales agent instead of returning “MCP app tool call denied,” while capability refresh and prior diagnostic results use the same tightly scoped widget bridge.
* Registering event sources now returns setup guidance in the sync response. Each live source (created, updated, or unchanged) includes a `setup` object with `snippet_type` and `instructions`, so the same call that registers a source also tells you where to send its events. Interchange ingests events server-to-server via `log_event`, so `snippet_type` is `server_only` and no client-side tag is returned; `instructions` names the ingestion endpoint and links the setup guide. Failed and deleted results omit `setup`.
* Generated creative renders now crop toward the most visually salient part of the image when a placement's shape forces a crop (for example a wide leaderboard or tall skyscraper). Previously the render was cropped to the dead center, which could cut the subject in half; it now keeps the region most likely to hold your subject.
* Media buys no longer fail to forward when assigned creatives are format-incompatible with the selected products. The buy forwards with the compatible subset (or an empty set when none match), and every dropped creative is reported with its creative ID, format ID, and the reason it was excluded.
* Buyers can now ask Murph a plain question such as “Is OptOut available?” from
* any Slack channel. Murph answers from the public listing without requiring a
* connected account or an exact domain. When signed in, buyers can also search by
* the seller or company name they already know.
* For agency teams working in a buyer–seller deal room, a Scope3-declared shared
* channel now keeps that seller visible automatically in the buyer's \*\*Supply I
* would buy\*\* view.
* For sellers, a clear marketplace-listed brand, storefront name, and domain now
* make the storefront easier for buyers to find and track. Keep that public
* identity current; buyer identity remains private, and no seller action is
* needed unless the listing itself needs an update.
* Only human-reviewed listed storefronts can appear in public answers, and
* relationship tracking begins only after a Scope3 admin declares the
* buyer–seller channel shared.

## 4.55.0 — July 15, 2026 at 1:24 PM UTC

* You can now declare, update, and remove the publisher domains your storefront covers directly from your agent using `storefront_api_call`. The four operations — `list_publisher_domains`, `add_publisher_domain`, `replace_publisher_domains`, and `delete_publisher_domain` — were previously unreachable through the agentic dispatch layer. Declared domains go through adagents.json verification; authorized domains appear on your buyer-visible storefront profile and count toward the verified domain total buyers see when evaluating reach.
* The organization admin page no longer shows its own Billing tab — billing lives on Plan & billing, and old links to the admin billing tab forward there automatically.
* External agents can now self-register with Interchange using WorkOS credentials. A new endpoint — `POST /api/v2/agent-registrations` — lets any agent discover, register, and obtain a credential without Scope3 involvement. Registered agents are provisioned into an UNBOUND sandbox environment with endpoint and spend limits until they are verified and promoted.
* Save a card once on Plan & Billing and paid features turn on right away, with nothing charged until your first billing cycle — no invoicing setup required.
* Sellers can now test a connected sales agent's product discovery directly, see exactly which operations passed or failed, and open the supporting request, response, and trace evidence. The test creates no media buy and spends nothing. Diagnostics also distinguishes a source failure from a storefront composition attempt that stopped before the source was called.
* Third-party sales agents start in finished-product pass-through, so they do not need ingredients. Interchange composition remains a separately provisioned paid add-on and uses only wholesale products the source advertises through AdCP 3.1 or later. Active managed ad-server sources continue to require composition.
* Buyer impact: none. This release does not change buyer protocol behavior or existing product results; it makes the seller's operating mode and failure evidence explicit.
* Packaging: source diagnostics and the no-spend discovery test are included for sellers at no additional charge. Product composition remains separately packaged.
* Rollout: this is an ungated atomic launch for authenticated storefront operators. Rollback removes the diagnostics launcher and direct-test route without changing buying or selling configuration; disabling the registered launcher is the kill switch.
* Measurement: adoption is the first successful `open_source_diagnostics` call per storefront. Usage is a `run_inventory_source_discovery_test` result, segmented by passed, empty, failed, and not reached. Initial acceptance is that every direct test records one durable result and exposes available trace identifiers.
* Existing v2 campaign calls keep their current behavior. Enrolled alpha buyers can connect and subscribe an account with a registered AdCP sales agent, then see its seller-managed campaigns in the same campaign list as their other activity. The mirror is read-only by default; separately approved accounts can create and update those media buys through the same campaign API.
* Embedded sales agents are on v1.25.1. The ESA now strict-validates every inbound creative-format reference at the request boundary: legacy string ids, fixed-size ids like `display_300x250`, and malformed references are rejected with a descriptive error that names the offending reference and suggests the canonical replacement — completing the canonical format contract's enforcement half, so a bad reference can no longer slip in and surface later as a mismatched creative. Also included: GAM order-approval permission errors now correctly mark the order pending approval instead of failing the buy, guaranteed impression goals in size auctions are sized off the buyer's bid rather than the list rate, embedded principals no longer receive fabricated placeholder GAM advertiser ids, and HTML/JS tag creatives now sync without requiring a preview URL. Buyer-visible surfaces are unaffected: buyers see the same product format references and media-buy responses as before; only the seller-side validation and GAM trafficking internals changed.
* Asking Murph to open billing now lands on the Plan & billing page — the same billing home as everywhere else — instead of the retired settings view.
* Murph now gives Slack users a secure, source-focused link to Sales Agent Diagnostics instead of implying that Slack opened an unsupported inline app.
* Failed Murph sandbox tests now open diagnostics on the exact recorded run, with an Open diagnostics handoff in Slack.
* Buyer teams enrolled in the Activity Console beta can now review Calls and Changes inside MCP clients that support MCP Apps. They can filter captured API calls, inspect redacted request fields and available response or error details, and send a selected activity ID to Murph for debugging without leaving the conversation. Existing integrations do not need to change.
* Navigating in a tab opened before a deploy no longer breaks with "Something went wrong" — the app reloads itself once to pick up the new version.
* Failed GAM order cleanup now appears in seller Pending Operations. Sellers get guided permission, reconnect, safe-archive, and manual-cleanup paths when GAM creates an order but trafficking fails; buyers do not get a new action or status change from this release.
* Choosing Billing in settings now takes you straight to Plan & billing — the intermediate summary page with its extra "Manage billing" hop is gone.

## 4.54.1 — July 15, 2026 at 10:02 AM UTC

* Murph now completes sandbox campaign checks reliably, keeps package CPMs separate from campaign-budget currency, and uses the connected account's buyer or storefront role in Slack.

## 4.54.0 — July 15, 2026 at 8:58 AM UTC

* Org API keys for automation: create scoped API keys for your organization to authenticate programmatic workflows against the Buyer API. Keys carry exactly the permissions you choose at creation (`buyer:read`, `buyer:write`, `buyer:admin`, or `account:admin`) and work anywhere a bearer token is accepted.
* Manage keys via `GET/POST/DELETE /api/v2/org-api-keys`, or embed the WorkOS API Keys widget in your own UI using `GET /api/v2/org-api-keys/widget-token`. Org API key management requires `buyer:admin`. Included in existing Buyer API access, no separate entitlement needed.
* Seller impact: none. Org API keys are a buyer authentication mechanism only. An automated workflow using an org API key carries the same buyer permissions (buyer:read/write/admin, account:admin) as the human who created the key — no new access to seller surfaces is granted, and sellers see no change in how buyer requests arrive or what they can request.
* Monetization: included in existing Buyer API access. No new billing surface.
* Adoption metric: org API key creation rate (`POST /api/v2/org-api-keys` calls) tracked via API metrics within 30 days of release.
* Kill switch: revoke individual keys via `DELETE /api/v2/org-api-keys/:id` or bulk-revoke via the WorkOS dashboard. WorkOS D4 permission registration also gates feature availability at the infrastructure level.
* Expansion: GA at merge for all buyers. Requires WorkOS D4 permissions (buyer:read/write/admin, account:admin) registered in the WorkOS dashboard before creation calls succeed in production. Staged rollout not needed — the feature is additive and does not change existing auth flows.
* Buyer Activity now captures authenticated MCP calls durably before execution.
* Failed tool results, including `isError: true` responses transported over HTTP
* 200, include schema-declared redacted arguments, typed result detail, workload
* identity, and copyable activity correlation for debugging in Activity or with
* Murph. MCP protocol traffic remains separately classified and does not inflate
* customer activity.
* External AdCP buyers can create a governed Interchange campaign through an enrolled storefront while the seller remains behind the standard AdCP interface.
* The alpha pins zero-fee buyer-edge entitlement terms, enforces buyer/storefront budget caps, journals idempotent writes, preserves buyer and seller media-buy identities, records campaign commitments and delivery usage, and reads delivery through to managed seller agents.

## 4.53.0 — July 15, 2026 at 4:20 AM UTC

* The V2 billing API now provides a version-locked contract for storefront plan
* selection. Once pricing is published, administrators will see the exact Rate
* Card revision, eligible plans, corporate discount, governing agreement, and
* final price before accepting. Any term change requires a fresh review.
* No storefront Rate Card is published yet. Storefront operators do not need to
* act, no account can move to a paid plan or incur a new charge, and buyer pricing
* and behavior are unchanged.

## 4.52.0 — July 15, 2026 at 3:32 AM UTC

* Buyer teams enrolled in the Activity Console beta can now inspect safe,
* schema-validated request JSON, public error responses, selected non-secret
* headers, and validation steps for an API call. Call detail also links directly
* to Murph for evidence-based troubleshooting without exposing credentials, raw
* headers, invalid raw fields, or internal stack traces.
* Diagnostic detail expires after 90 days while slim call metadata remains
* available for 13 months.
* Scope3 support receives the same retained safe REST detail in the cross-tenant
* admin console, plus customer-visible call volume, problem-rate, latency
* percentiles, incomplete-call counts, and top operation/error metadata. Internal,
* protocol, and diagnostic reads are excluded from customer-activity engagement
* rollups so opening Activity or asking Murph does not manufacture API usage.
* Refining a generated creative by typing feedback in chat now works right after the session renders — Murph no longer asks for the session or variant id. The active session carries forward automatically, the same way the widget's own refine button already did.
* Parent organizations whose storefronts live in child accounts now see the Payouts tab on Plan & billing — capability is derived from the whole organization, not just the parent's own roles.
* Refining generated creative is now per-placement isolated: add a note to a placement to regenerate only that one from the hero, and leave a placement alone to keep it exactly as-is (never regenerated, never dropped). "Add to campaign" is always available and commits whatever is currently shown. The per-placement "Looks good" toggle and the approve-all gate are gone. Behind the buyer-creative-v2 + buyer-generative-creative flags.
* Generated creative is now produced per campaign placement: the chosen direction is rendered at each required size — grounded on one hero image for a consistent look — so the generation-refine grid shows a tile per placement instead of a single format. Behind the buyer-creative-v2 + buyer-generative-creative flags.

## 4.51.0 — July 14, 2026 at 10:52 PM UTC

* Customer backend services can now authenticate to the Interchange API using WorkOS M2M tokens (client\_credentials grant) instead of long-lived API keys. Tokens are short-lived, automatically expire, and support rotation and immediate revocation without service downtime or redeployment.
* Fix a bug where a seller feed reporting a fractional delivery metric (e.g. `impressions: 1346.5`) caused the whole package/media-buy delivery-metrics batch update to fail with a Postgres bigint syntax error, silently blocking delivery-metric updates for unrelated healthy packages in the same batch. Fractional counts are now rounded to the nearest integer before being written.
* Seller accounts now receive their storefront reliably across signup and admin provisioning, while automatic reconciliation repairs older accounts that were created without one. The Business profile page also provides an onboarding action instead of a load error while recovery completes.
* Murph's generative creative flow is more reliable and more conversational. Opting into references now consistently opens the reference picker to choose from — Murph no longer sometimes grounds silently and narrates it in prose instead. And Murph's messages through the flow stay short and chat-first, letting the widgets carry the session, variants, and next steps rather than restating them as a numbered status report. Behind the buyer-creative-v2 + buyer-generative-creative flags.
* Plan & billing is now the one home for your organization's money. Plan & pricing gains a "How you're charged" card that states your pricing model plainly — % of media rates, plan terms, or both. Payment & invoices separates what you pay us from what you pay for media: Interchange fees (your plan) and media billing (the media itself). The old billing locations in organization settings and account settings redirect here.
* Payout activity now shows setup history: when payout details were changed and by whom, so finance teams can verify bank-detail changes without contacting support.
* Payouts now live inside Plan & billing as their own tab — payout entities, the setup wizard, and payout activity in the same place as the rest of your billing, no more jumping to a separate settings page.
* You can now navigate back from the Plan & billing page, and the Payouts setup card states when payout runs happen (monthly, at month-end close).
* Explicit storefront refreshes now sync every enabled catalog stream, including pricing availability and signal coverage, while routine inventory polling stays lightweight. Existing in-progress syncs are reused safely, and no force-recovery credentials are needed.
* Reporting for a storefront media buy that fans out to multiple upstream sellers now sums delivery across every seller instead of showing only one. Each seller's leg is tracked by its source, so `GET /api/v2/buyer/reporting/metrics` and `GET /api/v2/storefront/reporting/metrics` report the full buy total (and correct per-package figures) rather than collapsing to a single leg. Single-seller buys are unaffected.

## 4.50.0 — July 14, 2026 at 5:12 PM UTC

* Catalogs now has its own place in the buyer chat rail: open it to see your catalog feeds — health, sync status, and item counts — right in the conversation, drill into a feed for its detail, and sync, preview, or run its activation plan without leaving chat. Data sources is now Conversions only, so connecting event sources gets its own focused view too. You can also just ask Murph to open your catalogs.
* The creative confirmation card now flags any brought creative whose format no product on the campaign accepts — the mismatch shows directly on that creative with the accepted formats, instead of the creative looking mapped and being silently dropped at execute. The check re-derives as products and placements change, so it appears or clears on its own. An incompatible creative offers only Remove (no "map it anyway" placement picker, since nothing would take it), and Remove now takes the creative off the campaign in place, without a chat round-trip.
* The deprecated `brand_agent_id` response field on creative manifests and creative collections has been removed. Integrations should read `advertiser_id`, which carries the same advertiser identifier. The field was deprecated and announced in the prior release; the affected surface is flag-gated to pilot customers. Targets API-integrating buyer personas (scrappy builder, large agency); no seller-visible surface changes, so the seller pass is explicitly not applicable.
* Fixed a crash that could occur when attaching a creative asset supplied as an inline (data URL) value without an explicit content type. Very large values could previously fail the request; they are now processed reliably.
* Seller agents now receive a `time_budget` in real-time discovery requests that accurately reflects how long they have to respond. Previously the budget was stamped before an internal account synchronization step (up to 5 seconds) and did not subtract the 2-second fallback reserve, so the advertised budget was up to 7 seconds larger than the actual timeout. Agents that responded near the stated deadline would be cut off early.
* Murph now keeps creative uploads in the in-chat creative flow instead of sending you out to the Creative Assets dashboard. Bringing, attaching, mapping, or reviewing creatives happens on the in-chat card, which owns advertiser, campaign, and placement selection. A dashboard link is only offered when you explicitly ask for it, or for files larger than 50 MB where VAST/webhook or a public CDN link is the right path.
* The "Needs attention" card in the seller dashboard now explains how to use the trace ID to investigate failing calls: it is sent as the `x-scope3-debug-id` HTTP header on every request to your agent, so you can search your own logs for it. The card also includes a copy button for the trace ID and clearer next-step guidance for timeout and failure cases.
* When grounding a Murph creative generation on references, an advertiser with no references yet now sees the reference picker in an empty state — with an "Attach assets" affordance and a generate-without-references action — instead of a plain-text "library is empty" fallback. Buyers can add references from zero. Behind the buyer-creative-v2 + buyer-generative-creative flags.
* Ad-server-backed storefronts now preserve eligible ad-server pricing and use uploaded wholesale pricing only for individual products that still need a price. Products without usable pricing stay out of buyer catalogs until separate pricing is provided.

## 4.49.0 — July 14, 2026 at 2:31 PM UTC

* Realized delivered spend now books correctly even when its campaign was archived after the delivery occurred. Previously, archiving a campaign while a media buy still had delivery reports in flight left that spend unbooked, understating buyer balances, seller payables, and fee revenue until it was manually reconciled. The spend-booking resolver now treats an archived campaign as a valid provenance and advertiser source (preferring a live campaign when one exists) instead of refusing to book.
* Buyer teams enrolled in the Activity Console beta can now inspect authenticated
* API calls by workload, operation, outcome, latency, and public correlation ID.
* The Calls view and activity endpoints make agent behavior and failures traceable
* without exposing request payloads or credentials.
* Creative update responses now include a `warnings` field when the assigned `format_id` does not match any format accepted by the campaign's products. Executing a media buy now returns a clear error if no assigned creatives match the product's accepted formats, or if no video creative satisfies the product's required duration. Previously these mismatches were silent or surfaced only at the publisher side.
* Google Drive file imports now open directly from Murph and creative uploads. Choose files each time without managing a separate Google Drive connection.
* AAO compliance tracks that have some passing scenarios alongside coverage gaps now correctly display as partial or passing instead of "no coverage". This fixes storefront compliance checks showing "no coverage" for tracks where the agent did respond and some scenarios ran, matching what AAO's own compliance summary reports.
* TikTok directed campaigns now validate package geography before dispatch and create ad groups with explicit TikTok placement, avoiding provider-side cleanup after an invalid automatic-placement request.
* FX-terminated media buys now surface a specific error code (`fx_snapshot_missing` or `fx_quote_expired`) in the pending-operations view instead of `unknown_failure`.
* When helping sellers fix their `adagents.json`, Murph now recommends the correct agent URL for their connection type and accurately describes a missing authorization as an advisory warning (not a blocker), including its effect on buyer-visible coverage disclosure.
* Account admins can now set an org-level default for Murph conversation sharing. New conversations inherit the default when no explicit value is provided. Individual users can still override the default per conversation using the existing sharing toggle.
* Per-route browser tab titles in the buyer app so multiple open tabs are distinguishable.
* Adding a creative labeled `video_vast` whose asset is a raw video file (for example an `.mp4`) instead of a real VAST tag now fails immediately, at the point you add it to a media buy, with a clear reason — instead of being accepted and then rejected downstream by the publisher. The message tells you how to fix it: relabel the creative to `video_hosted` for raw hosted video, or attach a real VAST tag. This closes a gap where such creatives passed our format check and only failed when the buy reached the publisher.
* Canceled directed campaign shells now report `CANCELED` instead of falling back to `DRAFT`.
* TikTok directed campaign cancellation now reconciles deletion from either native campaign status field instead of leaving an accepted cancel operation pending.
* TikTok Reach directed campaigns now validate and apply an explicit buyer-selected frequency cap before creating native campaign objects.
* Settings → Plan & Billing now shows your plan, pricing, usage, funded balance, credit line, agreements, and the single next action to stay in good standing — one page, for every organization. Agents get the same data through `get_billing_account` and `open_plan_and_billing`.
* Fix media buys failing to forward when the creative uses a base video format (video\_standard) but the product only declares a duration-specific variant (video\_standard\_15s/30s). The correct variant is now matched and sent to the source.
* Directed campaign cancellations now settle when a connected platform omits the deleted campaign from its next complete account snapshot.
* When generating creative in Murph, buyers are now asked whether to ground generation on references from their library — choosing "yes" surfaces the reference picker (which previously could not render inside Murph at all). Also fixes a generation crash on a fresh session with no prior assets. Behind the buyer-creative-v2 + buyer-generative-creative flags.
* Structural media-buy forward failures (for example, a source that cannot traffic the requested creative format) now fail fast with an actionable reason instead of silently retrying for hours. Sellers get a "forward failed — needs correction" signal immediately, pointing at the creative-format or product-catalog mismatch to correct, instead of a buy that quietly never delivers. Buyers see a "needs correction" pending reason rather than an indefinite "retrying" state.
* Added the TMP prebid setup runbook: step-by-step install for the Scope3 module in Prebid.js or Prebid Server (config, credentials, and the auction-timing requirement), the Google Ad Manager half (segment targeting keys, automated line items, the tracker-domain authorization), and how to verify TMP is serving end-to-end — plus a troubleshooting table for the most common silent failures. The TMP overview now links directly to it.

## 4.48.1 — July 13, 2026 at 8:55 PM UTC

* The Approvals widget now keeps approval routing visible when its settings cannot load. Admins can retry the read, while other operators see that a customer admin must manage routing instead of an unexplained blank section.

## 4.48.0 — July 13, 2026 at 6:25 PM UTC

* Buyer API responses now distinguish a stable agent workload from the credential used to authenticate it, giving audit and governance systems a durable identity without changing existing integrations. Seller behavior and seller presentation are unaffected.
* Storefronts now expose their publisher domain lists. Sellers can declare which publisher domains their storefront covers via the REST API; buyers can query the full list, filter storefronts by publisher domain, and see a verified/declared breakdown on storefront detail.
* Buyers can open an in-chat Activity log showing who changed what on their advertisers and campaigns — whether it was a person, the agent, or automation, and whether each action succeeded, was denied, or failed.
* Buyer agents can now call `list_storefront_publishers` by operation name via `api_call` to retrieve the full paginated publisher domain list for a storefront. Previously the endpoint was only reachable via raw HTTP; this completes the api\_call operation surface for the publisher coverage feature shipped in AI-2796.
* Buyers can now edit an existing campaign creative's placement mapping directly from the campaign view, and each creative row shows the placements it maps to.
* Creative manifests and collections now return `advertiser_id` identifying the owning advertiser. The `brand_agent_id` response field is deprecated — it now only appears on rows created before the advertiser re-key and will be removed after a migration window; switch integrations to `advertiser_id`.
* The ad-server connection flow now consistently uses Epsilon's current product name, **Epsilon Retail Media**, while existing CitrusAd connections and API identifiers remain unchanged.
* Keep the ad server source setup form open after sellers click "Add another ad server," even when source data refreshes in the background.
* Google Drive file selection now opens in a Google-owned window, so importing creatives and Murph attachments works in browsers that block third-party cookies. Access remains limited to files you explicitly select.
* Buyer agents can connect through MCP 2026-07-28 hosts without changing their
* setup, while existing agent connections continue working unchanged. Storefront
* agents get the same compatibility on the standard storefront MCP endpoint, with
* no change to inventory, media-buy, or authorization behavior. No OAuth
* reconnection or customer action is required.
* You can now rename a Murph chat thread directly from the sidebar. Click the `...` menu on any conversation row and choose Rename to give it a name you'll recognize.
* Optimization suggestions returned by `get_optimization_suggestion` now include a `pacing_recommendation` field describing whether a media buy is under- or over-spending and the recommended daily spend to stay on pace. Purely informational — no change to how suggestions are computed or applied.

## 4.47.0 — July 13, 2026 at 2:02 PM UTC

* CitrusAd can now back sponsored-product inventory in seller storefronts. Buyer agents keep using the existing storefront product and media-buy contracts; product metadata identifies CitrusAd as the backing ad server, without requiring a CitrusAd adapter or credentials.
* Buyer-persona applicability: buyer agents encounter CitrusAd inventory through the existing MCP and REST discovery and media-buy operations. Their request shape, authentication, and workflow do not change; only additive product metadata identifies the seller's backing ad server.
* Monetization: this alpha adds no new buyer fee, seller fee, take rate, or billable usage unit because CitrusAd is another implementation of the existing ad-server-backed storefront capability. Packaging and provider-specific operating costs must be evaluated before any broader paid-tier or GA decision.
* Billing now has a home for payout and invoice activity — new sections at the top of the Payouts and Invoices tabs on your org Billing page, and matching `GET /api/v2/billing/payout-activity` / `GET /api/v2/billing/invoice-activity` endpoints (agents: `get_payout_activity`, `get_invoice_activity`). The sections are empty until your first payout run or billing period, then populate automatically — no setup needed.
* Murph now correctly scopes campaign reads to the selected advertiser when the chat is opened from an advertiser context. Previously, asking "how are my campaigns performing?" while scoped to a specific advertiser returned campaigns across the entire account.
* Murph now treats ordinary human-to-human Slack replies as ambient channel conversation, even when they include account-specific troubleshooting details, instead of nudging the author to tag Murph.
* Fixed a visual glitch in the Murph sidebar where clicking an existing conversation would jump it to the top of the recents list instead of keeping it in place.
* Buyers can attach selected Google Drive files directly in Murph and request support for OneDrive, Dropbox, or Box from Connections.
* You can now rename a Murph chat thread at any time — the new title replaces the auto-generated one everywhere it appears. If you're calling the API directly, send `PATCH /v2/murph/conversations/:conversationUid/title` with `{ "title": "..." }`.
* Automated release notifications to shared customer Slack channels now fail closed: routine release tier or authored Slack copy no longer creates a message, existing machine approvals cannot send, and unresolved targeting is skipped rather than widened. A targeted affected follow-up sends only when its exact message has human approval and a source-backed resolver proves reachable recipients at execute time.
* Optimization suggestions now include `campaignExternalId`, `campaignName`, `mediaBuyExternalId`, and `mediaBuyName` in the response, enabling downstream enrichment to resolve campaign and media buy details without an extra lookup.
* Your primary payout entity can now receive different currencies into different accounts, like any other entity.

## 4.46.0 — July 13, 2026 at 11:14 AM UTC

* Keep the buyer assistant available when an operation has an unusually large request definition. Large operations remain accessible through the named-operation fallback instead of disabling every assistant action.
* `ask_murph` responses now include `confirmationToken` on the `pendingConfirmation` structured field when an action requires approval. Previously the token was only present in the text answer, requiring clients to parse it from prose. MCP clients can now read `structuredContent.pendingConfirmation.confirmationToken` directly to get the exact phrase the user must reply with.
* FreeWheel sources now stop retrying unprovisioned reporting or forecasting access and offer a direct re-check after FreeWheel enables the permission.

## 4.45.0 — July 13, 2026 at 9:49 AM UTC

* Separately enrolled directed-campaign customers can list provider products and create or update one seller-managed media buy through the existing campaign API, with durable idempotency, currency-specific budget caps, and upstream reconciliation.
* The AXE setup doc and Murph now teach what the GAM keys are actually for and the required publisher-side install. After Murph clears the "AXE Segment Keys" setup task, it prompts you to confirm the `scope3RtdProvider` module is installed in your Prebid.js — without it, the GAM keys stay inert and every Scope3-signalled buy misses. The `mintlify/v2/storefront/esa/axe-keys` doc gains a new "How the keys connect to your ad stack" section (publisher-side RTD writes, ad-server-side reads) plus concrete `scope3RtdProvider` install guidance and an explicit note that Prebid Server support isn't complete yet (naming disagreement + missing exclude signal, tracked internally). Two new troubleshooting entries cover "task cleared but no Scope3 targeting is happening" and "I run Prebid Server."
* Source diagnostics now open from the source you are looking at instead of a standing Diagnostics entry in the seller navigation rail. The ad-server and sales-agent source view gains an "Open full diagnostics" button that opens diagnostics scoped to the selected connection, asking Murph about a named source opens diagnostics focused on that source, and the pending-operations view (`GET /api/v2/storefront/pending-operations`) gains a `sourceDegradations` group listing seller-owned degraded sources with severity and a one-line summary — issues Scope3 or a vendor must fix never appear as your task.
* TikTok directed campaigns now validate package geography before dispatch and create ad groups with explicit TikTok placement, avoiding provider-side cleanup after an invalid automatic-placement request.
* The `api_call` MCP tool (buyer and storefront) now requires a named `operation`. Raw `method` + `endpoint` calls are rejected with a self-healing error that points agents at the operation catalog. Named operations carry validated schemas — the tool derives the HTTP method and endpoint for you and rejects misplaced path params up front — so agents stop guessing URLs and request shapes. Every raw call we observed was either a read that already has a named operation or a hallucinated URL; if you were still sending `method`+`endpoint`, switch to the matching `operation` (use `ask_about_capability` to find it by intent).
* Murph shared links now open in a new browser tab so customers can keep the chat visible while reviewing linked content.
* Fix the Plan & Billing page failing to open in Murph chat with "MCP app failed to load." The `plan-billing` widget was registered everywhere server-side but was missing from the chat client's widget registry, so the widget directive couldn't resolve to its resource. Registering it lets the Plan & Billing widget mount and hydrate in chat.
* FreeWheel sources now remember missing reporting or forecasting permissions, stop retrying that capability, and resume it after an explicit permission re-check.

## 4.44.0 — July 12, 2026 at 6:46 PM UTC

* Enrolled buyers can subscribe a connected ad-platform account and see its campaigns in Interchange as read-only directed-campaign mirrors, with up to a year of campaign metadata and delivery read through live from the source.
* Managed storefronts can assign one approval owner, choose an optional escalation audience, and use Murph's guided setup without broadcasting approval work account-wide.
* Inventory source health is now diagnosed per-capability instead of as one
* combined status. A missing ad-server reporting permission (for example a
* FreeWheel reporting-scope denial) now shows as its own "reporting access
* missing" item — with the exact permission to grant — instead of a generic
* "reconnect your ad server" and no longer blocks selling or setup while
* inventory keeps syncing fine.
* Setup surfaces now tell you when your ad server has no products published yet, instead of showing a confusing cache warning. A connected ad server whose syncs succeed but return zero products gets a clear, actionable diagnosis — "No products are published for your ad server yet, so buyers can't transact — build products to go live" — with a Build products action and a troubleshooting guide, and you're notified when it appears. Stale-catalog warnings now appear only when a refresh can actually fix them.
* Media-buy version history now rejects any write that would leave a non-empty buy lineage without a current version, preventing buys from silently disappearing after an incomplete transition or direct database edit.
* You can now go from a feature announcement straight to its guide, product surface, or an authored guided lesson.
* Storefront source health now recognizes current manually uploaded wholesale pricing without asking sellers to reconnect an unused ad-server pricing integration. Sandbox source tests can create their canonical no-spend account even when other sandbox accounts already exist, and storefront readiness now recommends assigning a dedicated sandbox advertiser or granting Interchange permission to create one before smoke testing.
* Media-buy version reads now preserve async-accepted buys, mutations target exact version rows, transitions serialize by tenant lineage, and integrity ambiguity is monitored and handled safely.
* Agents can now read your plan, usage, balance, and agreements — and open a Plan & Billing view in chat — via two new MCP tools, `open_plan_and_billing` and `get_billing_account`.
* Media-buy updates now keep the correct current version through approvals, cancellations, and archive transitions, preventing buys from disappearing or selecting an in-flight update.
* The storefront API reference now documents `PATCH /api/v2/storefront` (updateStorefrontCapabilities), which patches individual storefront capability flags. The endpoint was live and served correctly, but a code-generation path collision left it out of the published OpenAPI spec.
* Creating or updating a performance campaign now rejects an optimization goal whose `eventSources[].eventSourceId` does not resolve to a live event source on the advertiser, and the error names the offending id. Previously a dangling reference was stored as-is and the goal silently received no conversions. The check is advertiser-scoped, so a source from another account can never satisfy a reference. On update it is delta-validated: only references you add or change are checked, so edits to campaigns that already carry a legacy reference are not blocked.

## 4.43.2 — July 12, 2026 at 3:49 AM UTC

* Hide unpriced source products from buyer discovery instead of returning an invalid wholesale catalog.

## 4.43.1 — July 12, 2026 at 2:57 AM UTC

* Refresh storefront products automatically after wholesale pricing is uploaded.

## 4.43.0 — July 12, 2026 at 1:45 AM UTC

* Sellers can now change their storefront's merchandising mode. The creative-review, campaign-approval, and product-composition toggles returned an error whenever you tried to save them, because the update they called had no matching endpoint — so the setting never actually changed. That endpoint now exists, and toggling merchandising mode saves correctly. Ad-server-backed storefronts continue to keep all three capabilities on, as before.
* GAM-connected storefronts now include descendant ad-unit delivery in pricing
* guidance and expose a usable CPM floor for wholesale products.
* Storefront admins can now assign primary and fallback role or user audiences separately for media buys and creative review, choose email and Slack delivery for each stage, set reminder and escalation timing, and reassign open work. Approval work moves to the fallback audience if its owner leaves or misses the deadline; it never auto-approves on expiry.

## 4.42.0 — July 11, 2026 at 11:59 PM UTC

* Diagnose any media buy end to end. Every media buy on Scope3 now explains itself: a buyer's agent answers "why isn't my buy live?" in one call — what it's waiting on, whose side owns the wait, and what to do next — instead of polling for a black-box status. Sellers work every buy from chat: Media buys shows what's pending and urgency-sorted, Timeline shows the exact payload sent to a source for any single buy, and Pending operations groups everything waiting on someone with a retry action only where retrying can work. Existing calls are unchanged. Guide: [https://docs.scope3.com/v2/guides/diagnosing-stuck-media-buys](https://docs.scope3.com/v2/guides/diagnosing-stuck-media-buys)
* Organizations now have one Plan & Billing page at Settings → Plan & Billing: plan and rate card, funded balance and credit line, intelligence usage, agreements, and the one next step (if any) to stay in good standing. It's rolling out to a first group of customers now.
* Your storefront now carries a publisher domain as its identity key — the domain buyers and demand requests look you up by. You can supply `publisherDomain` when creating a storefront (recommended), and managed ad-server storefronts must have their publisher domains configured and authorized before setup can complete and the storefront goes live. Third-party sales agents are unaffected: your domains keep arriving through the product pass-through as usual. Nothing is required at creation time and no existing integration changes behavior.

## 4.40.0 — July 11, 2026 at 7:56 PM UTC

* Sellers can inspect and author source-scoped property and property-tag mappings to key-value, ad-unit, and placement targets through the v2 API or Murph, with validated dry-run coverage, provenance, audit evidence, and explicit confirmation before bulk replacement.
* Fixed the media-buy policy evaluator's Gemini second-opinion check, which was still 404ing in production after an earlier fix attempt — the code-level model default had been corrected, but the production Helm configuration still pinned the unprovisioned model and took precedence over it, so buys kept silently escalating to manual review instead of getting an automated verdict. The evaluator, its underlying default, and Murph's (currently inactive) Gemini fallback now all consistently resolve to `gemini-2.5-flash`, the model actually provisioned in the production Vertex AI project.
* Network storefronts can now synchronize publisher authorization from large, multi-thousand-property adagents.json documents.

## 4.39.0 — July 11, 2026 at 6:51 PM UTC

* Reduce noisy managed ad-server setup diagnostics. Soft-expired catalog caches now refresh automatically without creating seller action items, default naming conventions no longer appear as setup warnings, and AXE segment-key setup routes to a guided create-or-map flow instead of a generic checklist warning.
* The organization Billing page is now one clear page for how your organization gets paid and pays. Sellers set up payouts entity-first on a Payouts tab: each legal entity appears as a card with its country, per-currency bank accounts (masked to the last 4 digits), and a Primary tag, and adding or editing an entity walks through a 2-step wizard that adapts the bank fields to the entity's country (US routing number, UK sort code, SWIFT/BIC elsewhere) and prefills the legal name from your business profile. Buyers manage billing details on an Invoices tab. Orgs with both a storefront and a buyer account see both tabs.
* Managed GAM setup diagnostics now treat default naming templates as already configured, so sellers are not prompted to customize naming just to clear setup health.

## 4.38.0 — July 11, 2026 at 5:09 PM UTC

* You can now catch up on product changes without leaving Interchange. Ask “What changed since I was last here?” for a summary tailored to your account, or open Help → Release notes to browse changes for your setup and features worth exploring. No setup is required.
* Signal components now distinguish targeting already present in a connected ad server from the components a seller creates and offers through their storefront.
* Enrolled buyers can connect or disconnect a personal Google Drive account from Connections, then select Drive files from campaign creative bulk upload. Scope3 can only use files the user selects and cannot browse the rest of Drive or write files back.
* Ask and supply-action statuses are now served from a single disclosure-aware read model: the same facts power the internal customer monitor and what Murph shares with you, with customer-visible fields formally annotated and enforced server-side.
* People invited into an eligible single-account Slack channel can now ask Murph general product questions and request access from the account's admins without re-entering their email. Murph also keeps nearby channel context when a follow-up starts a new thread.
* Corrects the July 11 release note for embedded sales agents: the current pinned release is v1.22.4, not v1.22.1. No customer action is required; the release-safety checks now block stale version announcements and backwards version deploys.
* Storefront setup now shows every configured publisher domain with its authorization status and resolved property count. Managed storefronts remain incomplete until they configure at least one publisher domain and every configured domain is authorized, helping sellers present verified property coverage that buyers can trust.

## 4.37.0 — July 11, 2026 at 1:32 PM UTC

* Managed ad-server source status can now include recent sync runs on request, making failed sync diagnostics available from the existing status call.
* A new endpoint, `GET /api/v2/billing/account`, returns one consolidated view of your account's plan, usage, credit/prepay balance, and agreements — plus the single next step, if any, needed to become or remain paid.
* Embedded sales agents roll to v1.22.1. Sellers' persisted creative-format references are canonicalized in one migration (fixed-size ids like `display_300x250` become canonical ids with explicit width/height), completing the canonical format contract's seller-side data half — media buys and creative assignments now match on one format identity end to end. Also included: GAM custom-targeting and AXE key management endpoints for tenant setup, authoritative publisher-domain sync, delivery reports carrying per-day clicks and completed views, and a publisher-property discovery throttle that keeps busy tenants responsive. Buyer-visible surfaces are unaffected: buyers see the same product format references and delivery reporting fields as before; only the seller-side representation and matching internals changed.

## 4.36.0 — July 11, 2026 at 12:14 PM UTC

* Murph no longer sends an invocation prompt when you upload a file without a caption in a connected Slack channel. Captionless ambient files stay silent; tag @Murph or send the file in a direct message when you want it reviewed.
* Saving publisher domains during storefront setup now automatically registers the full current domain set with the managed sales agent, clears removed domains from its authorization projection, and syncs current domains without a separate manual step.
* Storefronts with managed ad-server inventory now recover stuck pricing and availability syncs even if an earlier recovery attempt already closed. Products no longer stay blocked by the "pricing/availability sync has never run" readiness issue, with nothing for sellers to change.
* Sellers using the embedded sales agent now see pricing and availability sync status for wholesale products that are backed by standalone inventory profiles, so readiness no longer reports those successful GAM syncs as never run.

## 4.35.1 — July 11, 2026 at 1:59 AM UTC

* Managed sales agent storefronts can recover GAM pricing and availability syncs that never started, so wholesale product pricing guidance no longer stays blocked behind a stuck "never run" sync.
* Managed sales agent sync recovery now carries the protected force-recovery key, so GAM pricing and availability syncs that never started can be auto-started after deployment.

## 4.35.0 — July 10, 2026 at 11:30 PM UTC

* Force-start never-run ad-server pricing availability syncs through the ESA recovery endpoint instead of the generic refresh fan-out.
* `GET /api/v2/storefront/media-buys` now filters, urgency-sorts, and paginates in the database, so large storefronts get fast, consistent pages instead of an in-memory scan of every buy — and page boundaries are stable under the default urgency sort. The Media Buys widget gained a "Load more" pager, so buys past the first 50 are now reachable in chat.

## 4.34.0 — July 10, 2026 at 8:27 PM UTC

* When generating a creative from a brief, you can now ground the look in what you already have. Before Murph builds concepts, it can open a reference picker over your creative library — pick from sourced materials (anything you've saved as a generation reference, in any media type) or browse every past creative you've made, filterable by campaign — and Murph carries your picks into the draft directions it generates.

## 4.33.0 — July 10, 2026 at 5:56 PM UTC

* Murph can now create the three GAM custom-targeting keys (`axei` / `axex` / `axem`) for you when they're missing. Previously, if the keys didn't exist in your GAM network yet, Murph would tell you to open GAM Admin → Custom Targeting and create them yourself before it could save the mapping. Now Murph offers to mint them with Scope3's recommended names and display names — you confirm in chat, Murph calls a new `POST /api/v2/storefront/esa/:esaId/gam-custom-targeting-keys/ensure` endpoint, and finishes the setup on the same turn. Endpoint is idempotent (names already in your GAM come back in `alreadyExisted`, no duplicate creation), and shaped generically so the next signal protocol we ship (TMP) reuses the same call with different key names. The manual GAM path stays as a fallback for storefronts whose Scope3 service account lacks the `CustomTargetingKey.write` scope on the network — Murph explains that clearly when it happens.
* Bring your own creative straight from chat. Upload an image, video, audio file, or tag in a Murph conversation, and Murph asks the one question that matters: which campaign is this for? It then routes the creative to an existing campaign, a brand-new campaign you describe in plain language, or the advertiser itself to hold until you're ready. You can drop a file before you've named an advertiser; Murph stashes it and picks it back up once you do. Once the creative lands on a campaign, Murph maps it to the campaign's placements and lets you remap any that landed wrong. Full walkthrough: Buyer → Creatives → Bring your own creative.
* Embedded sales-agent storefronts now keep publisher-domain mappings authoritative. Adding a publisher domain still publishes it into ESA, and removing or clearing publisher domains now removes the stale ESA authorized-property projection instead of leaving old domains available.

## 4.32.1 — July 10, 2026 at 12:37 PM UTC

* Fix canceling a storefront buy that was never forwarded to the source. Previously, canceling a buy that was approved but not yet forwarded (e.g. stuck in forward\_failed\_needs\_correction) would fail because the ESA would return "not found" and cancel.ts would treat that as an error. Now MEDIA\_BUY\_NOT\_FOUND is treated as idempotent success. Also stops the forward worker from retrying a canceled buy by stamping forwarded\_at on the storefront\_pending\_media\_buys and storefront\_pending\_media\_buy\_updates rows.
* Fixed a display issue where storefronts using manual wholesale pricing upload showed a persistent "pricing availability: failed critical" health indicator even after pricing had been successfully uploaded.
* Fixed HTML5 creatives failing to be created in GAM after syncing. HTML5 creatives use click-beacon injection for click tracking, which meant the outbound payload had no destination URL. GAM requires a destination URL on all HTML5 creative objects, so affected creatives were silently rejected by the ad server. They will now sync and create correctly in GAM.
* Fixed the media-buy policy evaluator's Gemini second-opinion check. The model path was resolving to a retired Vertex AI alias, causing every auto-approve candidate to silently escalate to manual review instead of receiving an automated verdict. The evaluator now uses `gemini-2.5-flash` by default, matching what the production Vertex AI project provisions. A startup probe was also added so a misconfigured model path surfaces as an error immediately rather than silently degrading per request.

## 4.32.0 — July 10, 2026 at 10:11 AM UTC

* Treat ad-server pricing availability syncs with zero run evidence as never-run even when the upstream status defaults to success.

## 4.31.0 — July 10, 2026 at 8:53 AM UTC

* Managed ad-server sources now automatically start a pricing/availability refresh when the health sweep finds an ad-server-sync source whose pricing sync has never run.
* Fixed the wholesale avails and pricing guide so sellers can copy the CSV template directly from the page instead of following a static download link that was not served in production.
* The storefront create-account dialog no longer implies your domain is fully verified just because we found it in the AAO registry — the badge now reads as a neutral "found" signal, and a new note tells sellers upfront that domain-ownership verification happens after the account is created, so a "Pending verification" status on the setup checklist isn't a surprise.
* Buyers with Marketplace access can add sellers and channels they want to buy from directly in the Marketplace widget. The request stays buyer-side, so sellers do not need to do anything and campaigns do not change.
* Sellers with multiple legal entities can now register a payout bank account per entity and currency. Each payout entity carries its own beneficiary name and address, account number (masked to the last 4 characters on every read), and bank identifier, keyed by entity name and payout currency. Manage them via `PUT`/`GET /api/v2/storefront/billing/payees`, the `set_payout_payee` / `list_payout_payees` agent operations, or Settings → Billing → Payout entities. Existing payout details keep working unchanged as the default payee.
* Wholesale avails & pricing uploads now reject fake currency codes and obvious CPM or monthly-impression outliers during preview, so sellers catch unit mistakes before committing a feed.

## 4.30.0 — July 10, 2026 at 1:08 AM UTC

* Views and Completion rate are now columns in the campaign performance table, letting you compare video metrics directly across advertisers, campaigns, and media buys.
* Storefronts on Google Ad Manager can now finish AXE segment key setup directly in chat. Murph reads the include, exclude, and emissions custom-targeting keys from your GAM network, presents the three candidates for you to confirm, and saves the mapping — no more trip to the embedded sales agent admin. One rule the save enforces: the emissions macro key must be named literally `axem` in GAM, because the creative macro that carries the emissions token only resolves against that exact name. Full setup guide: Storefront → Embedded sales agents → AXE key setup.
* Fixed the creative picker labeling a placement with its bare media kind (e.g. "Image") instead of its format. When a format agent returns a generic media-kind name, the picker now shows the canonical format id (e.g. `display_300x250`) so every placement stays distinct and identifiable.
* Discovery no longer silently drops storefronts whose channel capabilities are stored in legacy alias form (`audio`, `video`). Channel normalization is now applied to both the request and the capability side at compare time, so a storefront declaring `audio` is correctly matched against a `channels: ["audio"]` request.
* When creative sync fails for a sync-capable seller and your assigned creatives don't match the required product format, execute now returns a clear error naming the mismatched product(s) and required formats — instead of a cryptic per-package rejection from the seller.

## 4.29.0 — July 9, 2026 at 5:08 PM UTC

* Cancelling a committed, guaranteed media buy now routes to a dedicated seller
* cancellation approval instead of stopping immediately. The buy keeps delivering
* until the operator approves the cancellation (approving terminates the buy;
* rejecting keeps it active). Cancelling a non-guaranteed buy, or a buy that has
* not yet been reserved with the source, still cancels directly with no approval.
* Delivery spend in cross-currency media buys is now correctly denominated in the advertiser's primary currency. Previously, buyers transacting in ZAR (or any non-USD currency) against USD-settling storefronts would see spend labeled in their currency but showing the raw USD amount. The API now converts source-reported spend using the FX rate booked at buy time, with a historical-snapshot fallback for older buys. The response includes a `deliveryFxConversion` field on each affected media buy disclosing the rate applied.
* Fixed an error causing the reporting metrics endpoint to return HTTP 500 in certain environments. Buyer reporting data was inaccessible when BigQuery did not support the `ANY_VALUE(IGNORE NULLS)` syntax. The endpoint now returns correctly.
* Buyers and sellers are now notified when an approved media buy's forward retry window lapses. Previously the platform stopped retrying after 6 hours without telling anyone — the `forward_failed_needs_correction` state was only visible by checking media-buy status or Pending operations. Buyers receive the existing `media_buy.forward_failed` notification carrying `pendingReason: forward_failed_needs_correction` and the buyer-safe error code; sellers receive the storefront forward-failed alert marked terminal, pointing at Pending operations. Fires exactly once per media buy, at the moment retries stop.
* Every budget you set — campaign `budget.total`, media buy product budgets, package budgets — is now gross: the all-in amount you pay, fees included, in one consistent denomination, with delivered spend on buyer surfaces reported the same way. Existing budgets were restated in place at the fee terms locked when each media buy was created, so their financial meaning is unchanged; the values you read back are now the numbers you're billed. Media buy reads gain a `budget_breakdown` (media budget, fee amount, fee rate, effective gross CPM) and a `budget_denomination` marker so the split stays visible. One behavior change: campaign budget ceilings now count the fee on ended buys' delivered spend, so a campaign that was silently over-allocated may ask for more budget before accepting new buys. Legacy media buys created before fee terms were locked are exempt: their spend stays net as the seller reports it, and they carry neither new field. Sellers continue to receive net media demand exactly as before.
* The storefront Dashboard rail item now opens the current seller analytics widget, so sellers return to the same analytics home Murph opens by default instead of the retired storefront dashboard view. The old in-page seller dashboard implementation and unused UI data wrappers were removed.
* Embedded sales agent 1.20.0: adds a tenant-management endpoint (`PUT /api/v1/tenant-management/tenants/{tenant_id}/adapter-config/axe-keys`) for declaring a GAM tenant's AXE include, exclude, and macro key names, and unblocks the `axe_segment_keys` setup-checklist task so it can be cleared once the three keys are confirmed against the tenant's synced GAM custom-targeting catalog. The macro key stays pinned to `axem` (the value the GAM creative macro `%%PATTERN:axem%%` resolves against); include/exclude names are configurable.
* Removed the raw AdCP wire-format payload from the `GET /api/v2/buyer/storefronts/:storefrontId/capabilities` response. All fields from the raw payload were already surfaced as normalized fields (`sandboxSupported`, `requireOperatorAuth`, `supportedBillings`, etc.) — the raw blob served no additional purpose for buyers and could be misread by agents.

## 4.27.0 — July 9, 2026 at 10:22 AM UTC

* Source-health alerts now come from one pipeline. An unreachable inventory source raises a single action-required notification (and a single all-clear when it recovers) instead of overlapping legacy and diagnosis alerts, Storefront Brain routes source problems by the same typed diagnosis every surface shows, admin views carry the identical owner/severity/action, and Murph can run a diagnosis's recheck for you on request.
* Interchange no longer sends wholesale product or signal catalog requests to third-party sales agents unless product composition is on and the agent reports AdCP 3.1+ support. Pass-through agents keep using normal live buyer requests.
* Fix creative sync not being reachable via the api\_call MCP tool: register the sync\_creatives operation in the buyer service route table and coverage allowlist.
* Scope3 now pays sellers by direct bank transfer and invoices buyers directly; billing no longer goes through Stripe. Sellers enter payout bank details once — beneficiary name and address, account number or IBAN, one bank identifier, and payout currency — in Settings → Billing or via `set_payout_details` (`PUT /api/v2/storefront/billing/payout-details`), and Scope3 pays by bank transfer in that currency. If you previously connected Stripe, re-enter your bank details once: Stripe-held data cannot be migrated, and until your details are on file your media buys settle on direct billing (you invoice the buyer yourself). Buyers are invoiced by Scope3 directly, with the bank remittance details to pay against printed on each invoice; keep your billing contact and address current in Settings → Billing or via `PUT /api/v2/billing/info`.
* See and work every media buy on your storefront. `GET /media-buys` lists every buy — routed and ESA-managed — urgency-sorted (buys still waiting on someone whose flight starts within 48h first), each carrying the shared `pendingReason` vocabulary, the structured error code of the latest failed exchange, and the forward outcome. `GET /media-buys/{mediaBuyId}/timeline` traces one buy end to end — received → decided → forwarded / forward-failed → submitted → source moderation → accepted / rejected → delivering — with the exact payload sent to each source (platform-internal webhook and signing fields removed), a trafficker-grade summary, and the references to quote per state: the source's own media-buy/task ids as *their* reference, and the `sf:` idempotency key paired with the request timestamp as the platform reference. `GET /pending-operations` unions everything waiting on someone — approvals, creative reviews, failed forwards grouped by error code with a recovery-class-gated action (retry for transient failures, fix-and-resubmit for correctable ones, escalate-to-Scope3 for structural or terminalized ones — those never get a retry button), and buys waiting on source moderation since a timestamp. The same surfaces open in chat (Media buys, Media buy timeline, Pending operations, and a one-decision Retry task) from the rail's Operate section or by asking Murph. Forward failures and aged-out moderation waits now push a transition notification to your storefront's notification stream.

## 4.26.0 — July 9, 2026 at 7:58 AM UTC

* The approvals widget now shows eligible products and GAM ad units for each pending media buy. When an operator expands a buy, a new "Eligible products" section lists the matched storefront products by name, description, and ad unit — replacing the previous raw package IDs. The Ask Murph prompt also includes inferred creative format hints so Murph can answer inventory eligibility questions without extra round-trips.
* Fix: human-approved optimization-suggestion budget reallocations now correctly apply the new per-product allocation. Previously the apply-suggestion flow read a `scaling_factor` field that was never present in real suggestion payloads, so approved budget changes silently no-op'd (only bid-price changes took effect). The apply path now uses `to_allocation` directly, matching the auto-apply worker.
* Source-health Murph alerts now include a direct link to the affected inventory source's diagnostics in Interchange, so sellers can open the exact evidence for the outage from the alert.

## 4.25.0 — July 8, 2026 at 10:42 PM UTC

* Added a modular inventory source setup app and guide for creating feed-backed sources, previewing and committing avails feeds, inspecting readiness, completing source-side setup tasks, and preparing pilot sellers with row-level avails requirements.
* Video and audio creatives now auto-map to their campaign placements even when the publisher's spec service is temporarily unreachable. The fallback matcher now understands resolution-style placement ids (`video_1080p`, `ctv_720p`), duration ids (`ctv_15s`, `audio_30s`), and aspect-ratio ids (`video_vertical_9x16`) — previously only `WxH` ids like `display_300x250` could be matched without a live spec, so a perfectly matching video or audio file would sit unmapped whenever the sales agent was slow or down.
* Buyers can now supply a tag's size as a file instead of typing it. Drop a CSV where each row is a creative — tag markup in one column, size in another (Google Ads Editor shape) — and each row becomes its own mapped creative. Or drop a CSV/manifest alongside your tag files (or inside a zip) that references them by filename; it fills each file's missing size and then dissolves. A CSV dropped on a "needs input" tag row also re-runs mapping for tags already on the campaign. Headers are matched case- and space-insensitively, and sizes read from a `WxH` cell, a comma-separated list, or split width/height columns. A plain data CSV with no tag or filename column is still read as a document, not a creative.
* Fixed the buyer storefront list and detail endpoints returning the storefront `id` as a string instead of the documented integer, which caused the marketplace browse surface to fail to load storefronts.
* Delivery reports for non-video inventory (display, audio-only, DOOH-without-video) now ingest correctly. Sellers on these formats legitimately report `null` for the video-only metrics `completion_rate` and `quartile_data`; the reporting webhook previously rejected these payloads, so the affected delivery data never reached buyer reporting. Bumping `@adcp/sdk` to 11.1.0 (AdCP spec 3.1.2) loosens these fields to accept `null` as the "not applicable" signal, while still enforcing the `[0,1]` bound on any non-null `completion_rate`.
* Murph plain product discovery now uses progressive quick discovery by default, so storefront results can appear as sellers answer instead of waiting for the slowest seller. Explicit `progressive`, `waitMode`, and `waitSeconds` choices are still honored, refine calls still wait for the final answer, and elevated support responses include trace diagnostics for auditing slow runs.
* Sizes supplied via a CSV/manifest sidecar now survive to a later turn. Previously, if you dropped a sizeless tag with its sidecar CSV *before* picking a campaign, the declared size was lost — the tag landed on the campaign unmapped and asked for its size again. The declared sizes are now stored on the saved creative (a dedicated `declared_sizes` field on its asset, distinct from probed dimensions) and used when the creative is assigned to a campaign in a later turn, so the tag auto-maps to every placement its declared sizes fill — same as a same-turn upload.
* Agents now receive the exact request format for every buyer and storefront operation that takes a request body, instead of only some of them. Previously an agent calling an operation whose shape wasn't published had to guess the request body and often failed several times before succeeding. Every body-taking operation that has a defined request shape now exposes it up front.
* Adding products to a discovery session no longer requires `salesAgentId`, `groupId`, and `groupName` on every selection. When omitted, the server resolves them from the session's saved selections or the discovery result cache, and a budget-only re-add of an already-selected product preserves its stored seller/group provenance. This removes the visible first-turn delay where chat agents had to run product discovery twice — once for products, and again just to reconstruct group metadata before selections could be saved.
* Tidied the storefront left rail: your chat history now takes only the room it needs — and scrolls once it gets long — instead of leaving a large empty block, so the rest of the navigation stays in view.

## 4.24.0 — July 8, 2026 at 12:22 PM UTC

* Approvals widget now surfaces flight dates (including end-only and ASAP starts), CPM bid price, and product names from package payloads on media-buy approvals. Creative reviews show explicit brand and size fields parsed from the submitted payload, so operators don't have to query Murph for basic metadata. Advertiser/brand name resolution also handles BrandReference objects and nested account paths.
* Answer "why isn't my media buy live?" in one call. Media buys now carry a `pendingReason` (e.g. `awaiting_storefront_approval`, `awaiting_source_moderation`, `scheduled_not_started`) that says what the buy is waiting on and whose side owns the wait, a buyer-safe `errorCode` with ownership (`buyer_input` / `platform` / `seller`) plus the source's sanitized rejection or moderation message when forwarding fails, `forwardedAt`, and a `buyerReference` support handle to quote to the seller or Scope3. The fields appear on the nested media buys in `GET /campaigns/:id`, on the media-buy status poll, and on the new `GET /media-buys/:mediaBuyId` (`get_media_buy`) single-buy lookup. Transition events (`media_buy.forward_failed`, `media_buy.awaiting_source_moderation`, `media_buy.source_rejected`, `media_buy.stuck`) now ride the buyer notification stream, fired once per state change with the same fields in the payload. Existing calls are unchanged — the new fields are optional and appear only on storefront-routed buys.
* Fixes a bug where creatives added across turns did not auto-map to the correct ad format, causing format\_id to remain unset and blocking campaign assignment.
* Fixed a false "AAO compliance pending" status on the storefront readiness panel for agents whose endpoint URL includes a transport suffix (e.g. `/mcp`, `/a2a`). The compliance check now queries the verbatim stored URL first; it falls back to the bare-root URL only when the verbatim lookup returns unknown.
* Fixed: updating the budget on a media buy created before the July 2026 pricing-terms migration no longer fails with "pricing terms could not be determined." The system now resolves and pins fresh pricing terms for those buys at update time, so the campaign ceiling check can proceed.
* Fixed: creatives synced to storefront sources now correctly complete the acknowledgment flow. Previously, the webhook callback used the storefront's customer ID to look up buyer-owned creatives, causing a silent mismatch that left creative syncs permanently in-progress on the buyer's side.
* Added `status_refresh_source` to media-buy status responses so buyers and agents can distinguish direct status polls from storefront route rollups. This prevents `agents_queried: 0` or `updated: false` from being mistaken for stale delivery state when a storefront-routed buy is already current.
* Storefront approval-requested email alerts now use the configured notification address as the explicit recipient instead of also emailing every active user on the storefront account; when that address is missing, they temporarily fall back to active users and raise an internal setup alert.
* Fixed storefront agent debug call traces so transport payloads are scoped to the matching ADCP task instead of occasionally showing an adjacent call.
* Storefronts now tell you when they need something from you. When a source problem only you can fix appears — expired ad-server credentials, a source that stopped responding, a stale pricing feed — you get a notification in the app and by email naming the problem and the fix, and a follow-up when it's resolved. To receive these in Slack too, add the new source-action alert types to your Slack notification settings. Problems on our side never become your tasks.
* Storefront media buys delivered by poll-based or source-push sources now populate their media-buy summary metrics (impressions, spend, clicks, and last-updated) from the storefront delivery feed, so `GET /media-buys/:id` reflects real delivery instead of zeros.

## 4.23.0 — July 7, 2026 at 8:35 PM UTC

* Brought video and audio creatives now auto-map to their campaign placements, not just images. Murph matches a video by the placement's size (fixed, multi-size, or responsive range) and its duration window (e.g. pre-roll :15/:30), and an audio spot by its duration — plus bitrate/codec where the placement declares them. On a match the creative lands `mapped`, credits format coverage, and the confirmation card shows "Maps to: …"; anything that fits no placement stays `recognized`. This also repairs cross-turn auto-map (attaching creatives saved in an earlier turn), which previously left every creative — including images — `recognized` because the saved creatives were looked up under the wrong advertiser id.
* Product `format_ids` now carry the inline params the seller's format definition pins (`width`, `height`, `duration_ms`) instead of being stripped to bare `{agent_url, id}` references. Buyers see fully-parameterized format references in `get_products` and media-buy responses, and echoing them back on `create_media_buy` no longer risks rejection by duration-pinned seller products. Existing composed catalog products are backfilled from the seller's own product definitions; other stored products pick the params up on their next catalog re-sync.

## 4.22.0 — July 7, 2026 at 6:50 PM UTC

* A fluid or multi-size ad tag now maps to every campaign placement its declared sizes can serve, not just one. When a buyer brings a tag that declares multiple sizes (e.g. 300×250 and 728×90), Murph auto-maps it to each matching required placement and the confirmation card shows all of them ("Serves N placements"). Tags with no declared size still ask which placements they run on.
* The buyer rail's Campaigns and Creatives items now match the storefront rail: once a conversation is underway they drop their selected highlight and show a "+" on hover, and clicking one opens its widget into the current chat. On a fresh chat, opening one is a clean start point that replaces the other; once chatting, opening another keeps the prior widget and both stay in the conversation. Rail-launched widgets — on both the buyer and storefront rails — now render in chronological order at the point they were opened, so the transcript reads top to bottom as it happened.
* Connecting an ad platform now tells you whether it's actually buyable. When a
* connect surfaces ad accounts but none of your advertisers are mapped to them,
* Interchange sends a "connected, but 0 advertisers mapped" notification with a
* path to the Advertiser mapping tab — before the first buy fails. Murph
* narrates completed connects (what was linked — a Business Manager, MCC, or a
* single ad account — how many accounts it surfaced, and the mapping state) and
* answers agency-access questions from the new per-platform agency runbooks in
* the connecting guide, which cover how a client grants your agency access on
* Meta, Google Ads, TikTok, Snap, LinkedIn, Pinterest, Reddit, and Amazon Ads.
* Fixed: updating the budget on an active media buy now works even when other buys on the same campaign were created before per-buy pricing terms were required. Previously, any campaign with legacy (unpriced) sibling buys would block all budget changes on any buy in the campaign. The validation now uses the available raw-media allocation as a conservative lower bound and still enforces the campaign ceiling.
* Budget headroom (`unallocatedBudget`) now reflects pending budget-reduction requests immediately, before storefront acceptance. Buyers who submit a budget cut will see the freed amount available for other buys right away.
* The creative upgrade endpoint (`POST /campaigns/:campaignId/creatives/:creativeId/upgrade`) is now reachable via the `api_call` MCP tool, allowing agents to set `format_kind` on a creative that has `requires_upgrade: true`.
* Fix Murph in-chat Approve control not completing durable writes. Clicking Approve now correctly executes the pending action instead of issuing a fresh confirmation request.
* Agent-driven catalog sync, event-source sync, and signal updates are more reliable. Some endpoints require the same identifier in both the URL path and the request body; an agent that supplied it in only one place previously got a "missing path parameter" or validation error. The API now backfills the missing side from the one you provided, so the id need only be stated once. A genuine mismatch between the two is still rejected, and the request contract is otherwise unchanged.
* Sellers now have public docs for publisher coverage, network `adagents.json`, GAM key-value site lists, and buyer property-list briefs.
* The "storefront adapter connection — mapping required" alert is now delivered always-on, alongside its credential-action sibling, instead of appearing as a mutable notification preference. Like the other storefront readiness signals ("your storefront is offline / not traffickable"), an operator can't mute a buys-are-blocked-until-mapped alert, so it no longer shows as an opt-in category for sellers.

## 4.21.1 — July 7, 2026 at 1:47 PM UTC

* Fix Murph approval flow so attaching a chat-uploaded creative (`create_creative_manifest`) executes when you click Approve. Previously the pending record kept the upload as a placeholder, so by the time the click landed on a later turn the buyer API rejected the write and Murph looped on a fresh approval instead.

## 4.21.0 — July 7, 2026 at 12:57 PM UTC

* Property lists now apply to active media buys automatically. Creating a new property list pushes it to all active media buys for that advertiser. You can also push an existing list to a specific campaign at any time -- no need to recreate media buys that were already running when the list was created.
* Fixed an issue where product discovery returned zero results against AdCP 3.0 sellers (e.g. Ozone) when a currency filter was active. The `pricing_currencies` field is only supported in AdCP 3.1; 3.0 sellers responded with `UNSUPPORTED_FEATURE` and no products. The SDK adapter now strips this field before the request reaches 3.0 sellers.
* Fixed two channel-filtering bugs in storefront discovery:
* 1. Audio storefronts (e.g. Talpa Media / Triton) were excluded from product discovery when buyers filtered by `channel: audio`. Agents advertising `primary_channels: ['audio']` now have that alias normalized to the canonical `streaming_audio` value before storage, matching how buyer-requested channels are normalized.
* 2. Storefronts with no declared channels or regions (most storefronts) were invisible in the marketplace browser when a channel or region filter was active. The filter now treats undeclared metadata as unknown and includes those storefronts, consistent with how product discovery handles agents with unknown capabilities.
* Show the buyer account name for requested supply when an internal customer link is missing, instead of showing an internal account identifier.
* Fixed a bug where deleting the last inventory source left the `products_available` readiness check showing `complete` instead of `missing`. The storefront now correctly reports zero products available after all sources are removed.
* Manual wholesale pricing issues now surface as pricing-upload tasks instead of generic ad-server sync failures.
* Murph: surface every pending confirmation from a multi-write turn so all Approve widgets render, not just the first. When Murph queues N writes in one turn (e.g. six `delete_campaign` calls), the orchestrator previously collapsed the pending\_confirmations to a single artifact via `.find(...)` — matched by the client hydration/state model which stored only one artifact per messageId, silently dropping N-1. The buyer chat surface promised "N Approve controls below" and rendered one. `MurphChatResponse` now carries a plural `pendingConfirmations: T[]` alongside the singular `pendingConfirmation` (retained for back-compat with older clients and the Slack handler), and the buyer runner renders one panel per element.
* The progressive discovery experience is now complete end to end. The opt-in
* API (`progressive: true` on `discover_products`, with `revision`,
* `resultsComplete`, `pendingAgents`, and a `guidance` field naming the exact
* next call), the server-sent event stream
* (`GET /api/v2/buyer/discovery/:id/events`), and progressive rendering in the
* buyer chat — results populate as sellers answer, with a waiting affordance
* naming who is still working — are all live. Calls without the flag behave
* exactly as before.
* Progressive product discovery now serializes first-wave cache snapshots behind earlier seller revision writes so `sinceRevision` polling cannot observe a lower revision than the initial response.
* Creatives that pin a `format_option_ref` with `scope: "product"` are now validated at assignment time — the referenced `format_option_id` must appear in at least one product's declared `format_options`. At execute time, the pinned option's canonical params (e.g. `duration_ms_exact`) are forwarded to the seller instead of the full option set.

## 4.20.0 — July 7, 2026 at 3:33 AM UTC

* Local MCP clients that use loopback OAuth callbacks, such as Codex, can now complete browser authorization instead of being blocked by hosted-client origin approval checks.
* Buyer agents can now inspect storefront capability diagnostics per active source. Managed ad-server-backed sources are counted as `probeable: false` instead of disappearing from the response, and external AdCP rows report credential requirements from the latest non-synthetic capability payload when available.
* For buyers and agent builders, this makes product-discovery troubleshooting clearer: a storefront with managed inventory no longer looks empty, and agents can tell when a buyer-owned credential is required. Sellers do not get new setup controls or need to take action; their managed storefront rows may now be shown to buyers as managed and not probeable rather than omitted. No pricing, packaging, billing, or margin changes.

## 4.19.0 — July 7, 2026 at 2:54 AM UTC

* Fixed cancel and delete failing for storefront media buys where the source accepted the buy asynchronously (returning a pending task instead of a confirmed upstream ID). The error "No media buy on this storefront" no longer occurs when cancelling or deleting a buy that is still awaiting source confirmation.
* The API now says `advertiser_id` everywhere it previously said `seat_id`, completing the seat→advertiser naming migration. The published buyer and storefront OpenAPI specs already used advertiser naming — this change renames the remaining internal request/response fields (the internal signal provider mapping API and unused input schemas) so no `seat_id` field name survives anywhere. No action needed: v2 buyer and storefront requests that send a stray `seat_id` key are automatically corrected to the advertiser field, so existing integrations keep working. Use `advertiser_id` in new integrations.

## 4.18.0 — July 6, 2026 at 11:07 PM UTC

* Creative manifest validation now accepts `format_kind`-only creatives (AdCP 3.1 canonical path). Creatives that carry `format_kind` without a `format_id` are now validated against the format kind catalog instead of failing with a format-not-found error.
* Bring-your-own-creative now handles ad tags. When a buyer pastes or uploads a display, rich-media, or VAST tag (standalone, or inside a zip bundle), Murph recognizes the tag type and its declared size and shows it on the confirmation card (e.g. "300×250 display tag", "VAST 4.0"). Tags with no declared size are flagged so Murph can ask which placements they run on, and tags mangled on paste (HTML-escaped, curly quotes, truncated, or garbled encoding) are flagged as malformed with a prompt to re-paste or upload the tag as a file.
* Activate a buyer catalog directly from the UI. The **Data sources → Catalogs** view now has three distinct actions — **Refresh**, **Preview**, and **Activate** — instead of a combined "Refresh and activate". Activation no longer depends on a feed refresh, so you can activate an inline/uploaded catalog (not just URL-backed feeds) and re-run activation on an unchanged feed on demand. Refresh now applies only to URL feeds.
* Fixed the buyer left rail rendering the "Recents" heading twice.
* `get_campaign` now returns `packages[]` (and its `packageId` values) before `products[]` and `creatives[]` in each media buy, so it survives LLM context truncation on large responses. Previously, `packages` appeared last in the object and was silently dropped when the response was too large, blocking budget edits on active buys with many creatives.
* Also fixes a silent no-op bug where submitting a package budget update with an unrecognized `packageId` returned success without changing anything. An unrecognized `packageId` now returns a validation error with an actionable message.
* Fix Approve button not rendering in Murph when the model made multiple failing tool calls in the same turn before proposing a gated action.
* Fixed an issue where spec-compliant external sales agents declaring `media_buy.portfolio.primary_channels` were stored with empty channel lists. The SDK reads the wrong key (`portfolio.channels`), so channels are now extracted directly from the raw capabilities response with fallback to the SDK-parsed value.
* Fixed a bug where `browse_discovery` always bypassed the discovery result cache on the first page of results (offset 0), causing every browse call to trigger a new live query to the seller. This produced non-deterministic product counts across consecutive calls to the same discoveryId and made the discovery cache effectively useless for initial page loads.
* One campaign can now mix routed and decisioned media buys. Routing (`ROUTED` vs `DECISIONED`) and pricing terms are now properties of the media buy, not the campaign: each buy takes its routing type from its storefront at create — derived server-side, never a client input — and locks its own pricing terms for that routing type. Each buy's fee is calculated at its own rate, so a campaign's fee is the sum of its buys' fees, and the campaign carries a single all-in `budget_total` that caps every buy's media plus its fee.
* **Breaking:** `campaignType` is now ignored on `create_campaign`/`update_campaign` and no longer returned on campaign responses (detail or summary) — routing and pricing are determined per media buy. On storefront and discovery responses (`list_storefronts`/`get_storefront`, product and proposal discovery), `supportedCampaignTypes` is renamed `supportedRoutingTypes` (same `DECISIONED`/`ROUTED` values).
* Pricing is unchanged: each buy still prices from the same contract rate card, now selected per buy's routing type instead of once per campaign. Nothing changes on seller-facing surfaces, and sellers still never see buyer margins.
* Murph: fix the "click Approve below but nothing renders" failure mode observed in the buyer chat surface. Root cause traced in the transcript: on a "re-offer" / "retry" request, Murph was text-narrating the corrected proposal ("This will set the budget to \$X…") without actually invoking the write tool — so no `pending_confirmation` was issued server-side and no widget could ever render, no matter how many times she said "click the Approve control below". The prompt now:
* 1. **Requires a tool call on re-offer/retry.** New section makes explicit that any retry request MUST invoke the write tool in that turn; a text-only reply describing the offer produces zero widgets. Called out as the single most common failure mode.
* 2. **Softens the "widget will render" language.** Previous fix (#5749) said "A fresh Approve control now sits under THIS turn" — reworded to "SHOULD render, tell me if it doesn't", with an explicit ban on asserting the widget WILL appear.
* 3. **Handles the "no widget rendered" report.** On first report — after a real tool invocation — Murph offers `report_issue` with the pending `confirmationUid` instead of looping back to "click the Approve control below".
* Storefront left-rail nav items now read as "add to chat" once a conversation is underway: they drop their selected highlight and reveal a "+" on hover, signaling that clicking them drops the widget into the current chat rather than navigating away. New chat and Dashboard keep their normal navigation behavior.
* Ad-server source setup now shows the real credential or vendor error when a create or credential update fails, warns about copied credential characters that can be mistaken for ASCII, and makes source creation and disabling available from the secure setup form.
* This is a seller setup change only; buyers do not see new controls or different catalog copy.
* Fixed creative assignment silently dropping all creatives when a product declares its accepted formats only via `format_kind` in `format_options` (no v1 `format_option_id`). Creatives whose format ID resolves to the declared canonical kind are now correctly assigned on both create and update paths.

## 4.17.0 — July 6, 2026 at 6:59 PM UTC

* You can now register a webhook to receive push events instead of polling. This is opt-in — nothing changes if you don't register one. Register a URL and secret once, and we'll `POST` matching events to it as they happen — starting with `discovery.revision`, which fires the moment a new seller result lands in a progressive discovery session, the same event the [discovery event stream](https://docs.scope3.com/v2/buyer/discovery/tasks/events) already pushes over a live connection. Deliveries are HMAC-signed so you can verify they came from us. See [Webhooks](https://docs.scope3.com/v2/buyer/webhooks) for setup and the full event catalog.
* Fixed: HTML/CM360 tag creatives (`display_300x250_html`) now pass format validation for products that declare image-only format IDs (`display_300x250_image`). Many seller product catalogs list only `_image` variants for display banner slots even though their ad servers accept HTML tags. Display banner slots of the same size now accept both HTML and image creative formats.
* Storefront operator-domain verification now recognizes trusted `brand.json` house portfolio website properties as alias evidence, so approved sellers are not left pending when their account and operator domains are linked through `brands[].properties`.
* Fix media buy failure when a MANAGED\_SALES\_AGENT product's internal inventory source identifier was mistaken for the sales agent ID, causing "agent reference broken" errors on product execution.
* MCP authorization failures now show the specific reason (for example, "An account admin must add this browser origin before authorizing this MCP client") instead of a generic "Failed to complete MCP authorization" message, and internal server errors on this route are now captured in Sentry.
* Murph: when a confirm-gated write's post-approval retry returns `pending_confirmation` again (the approval didn't propagate — `writeExecuted: false`, `plainAffirmativeAccepted: false`), Murph no longer points at the already-spent Approve widget. She now tells the user plainly that the approval didn't land and asks them to click the fresh Approve control that renders under the new turn. Also spells out concrete past-tense openers that are forbidden while a write is unconfirmed (`"Set — …"`, `"Updated — …"`, `"Bumped — …"`, `"Your budget is now …"`, etc.) so the specific narrative violation seen on the buyer chat surface can't slip past the generic "no past tense" rule.

## 4.16.0 — July 6, 2026 at 4:46 PM UTC

* Wholesale catalog products now carry a `pricingScope` field (`"public"` or `"account"`) so your agent can tell whether a cached price is the seller's public rate card or specific to your account. No action needed — the field is additive.
* Setup surfaces now show only the tasks you can actually do, each with a one-click recheck where the platform can verify the fix for you. The ad-server setup surface has a clear binary posture — "Connected and syncing, nothing needed from you" or a short list of exactly what we need — with our own background work shown as a passive status line instead of alarms. `GET /api/v2/storefront/esa/{esaId}/status` now returns the same typed `diagnoses` as readiness, scoped to the ad-server failure modes, and every seller-owned diagnosis links its troubleshooting guide.
* Supply requests you tracked before this week's update are visible again in `list_requested_supply`. Asks recorded under the previous storage model are now automatically carried into the new demand store on a recurring sweep, so nothing you requested is lost — and new asks continue to appear immediately.
* Finalizing a proposal on a storefront now returns a structured expiration timestamp, so buyer agents can tell exactly when they need to complete the purchase without parsing a text note.
* Storefronts with product composition now support the full AdCP proposal
* lifecycle with third-party buyer agents. A draft proposal returned by
* `get_products` can be finalized via
* `refine[{scope: "proposal", action: "finalize"}]` — the storefront
* re-validates that every product in the plan is still available at current
* pricing and commits the proposal with an `expires_at` deadline — and a
* committed proposal can be executed in one step by passing its `proposal_id`
* and a `total_budget` to `create_media_buy`, which expands the proposal's
* allocations into packages server-side. Each committed proposal executes at
* most once; unknown, expired, still-draft, and already-used proposals are
* rejected with specific ADCP errors. A committed proposal is a price and
* composition commitment bounded by its expiry, not an inventory reservation.
* Scope3 buyers are unaffected — their agents already execute composed plans
* directly; this closes the loop for third-party AdCP buyers.
* Settings → Connections is now two purpose-driven screens. The Connections tab
* is the accounts you've linked — each row is one grant showing who authorized
* it, credential health, and how many advertisers it maps — with link and unlink
* as the only actions. The new Advertiser mapping tab groups platform ad
* accounts under their manager container (Business Manager, MCC), maps or
* unmaps each to your advertisers, filters to unmapped or unreachable, and
* shows preserved unreachable mappings with a relink-to-restore path. A
* "connected, but 0 advertisers mapped" banner links straight to the unmapped
* view before a buy can fail.

## 4.15.0 — July 6, 2026 at 2:35 PM UTC

* MCP OAuth now accepts dynamically registered loopback callback subpaths, allowing local clients like Codex to complete authentication.
* Ad-server source status now shows manual wholesale pricing uploads as the required fix when a source is configured for uploaded pricing, instead of telling sellers to reconnect pricing access to their ad server.
* Murph no longer tells you to click Approve again when a confirm-gated write fails after you've already approved it. Instead, Murph now surfaces the underlying error (e.g. "your campaign's remaining budget is short") and proposes a concrete fix — the previously-approved control has been consumed and can't be clicked twice.
* Reporting polls to sales agents now carry the same `account` reference the seller received on `create_media_buy`. Previously, if the buyer had no linked account for the seller (the common shape for implicit-auth sellers like pubx), the poll worker dropped the `account` field entirely — even when `create_media_buy` had sent a natural-key `{brand, operator}` account and the seller had accepted the buy on that basis. The asymmetry caused strict seller handlers to null-deref on `ctx.account.id`, which surfaced as `INGESTION_FAILED` on every daily poll with no observable data ever landing in reporting.
* In deliberately shared Slack channels, the data owner can now approve sharing a specific campaign with the counterparty: Murph asks for explicit confirmation, only owner-side users can approve or revoke, the approval covers settings-level details only and lasts until revoked, and every grant and revocation is audit-logged.
* Allow multiple publisher organizations to connect the same third-party sales-agent endpoint with separate inventory-source credentials.
* Storefront readiness now returns typed source-health diagnoses. `GET /api/v2/storefront/readiness` includes a `diagnoses` array with one entry per source problem, each carrying who owns the fix (`seller`, `scope3`, or `vendor`), an impact-based severity (`blocking`, `attention`, or `advisory`), plain-language copy, and an inline typed action — including a ready-to-call recheck endpoint where the platform can re-verify on demand. Setup surfaces and agents can now show sellers only the tasks they can actually complete: problems Scope3 owns (like a stale catalog cache) no longer appear as seller to-dos or block readiness, and a stale signal catalog that nothing depends on yet is advisory instead of critical.
* Slack confirmation prompts now include Approve and Cancel buttons, so pending write actions can be completed without copying a confirmation code back into the chat.

## 4.14.0 — July 6, 2026 at 9:44 AM UTC

* Interchange now posts release notes to your shared Slack channel after production releases — a few bullets covering only the changes relevant to your role and setup, with the assistant on hand to explain any of them.
* Notification settings now include browser notification controls for shared Murph mentions, so users can explicitly enable live desktop alerts from the app.
* Wholesale product and signal catalogs for managed ad-server sources now refresh automatically when their cache goes stale, so newly created or edited products reach buyer discovery even if a catalog-change notification is missed. Previously a missed notification could leave a source's catalog stale indefinitely.
* Added `GET /api/v2/buyer/discovery/{discoveryId}/events`, a Server-Sent Events
* stream for progressive discovery. Instead of polling `browse_discovery` with
* `sinceRevision`, callers can open this stream to have each newly landed
* seller group pushed as it lands, with a terminal event once every seller has
* settled. Same continuation contract as polling, delivered as a stream.
* Managed ad-server sources can now distinguish ad-server-synced wholesale pricing from manually uploaded wholesale pricing, so pricing health prompts sellers to upload current pricing instead of reconnecting pricing access when the source is intentionally manual.
* Shared Murph room mentions now refresh faster in the app and can surface browser notifications when users have already granted notification permission.
* The provider account mapping list now carries the platform hierarchy
* (`accountType`, `parentExternalId`, `parentName`) for grouping accounts under
* their manager container, includes preserved unreachable mappings (accounts
* whose connection was unlinked) with a `mappingStatus=unreachable` filter, and
* each mapping entry exposes `linkId` and `unreachableAt`. A new
* `DELETE /advertisers/{advertiserId}/accounts/{linkId}` endpoint unmaps an
* account from an advertiser.
* `discover_products` over MCP now emits `notifications/progress` messages as sellers answer during the discovery fan-out. Pass the MCP protocol's `_meta.progressToken` on the `api_call` tool call and your client receives one progress notification per settled seller — e.g. "Magnite answered — 11 products (3 of 14)" — before the tool result returns. Works on both progressive and non-progressive discovery calls; clients that don't send a progress token are unaffected.
* Resolve typed Murph room @mentions server-side so valid same-customer handles still invite and notify teammates when the client omits mention IDs.
* Add same-customer @user mention suggestions and durable room invite events for shared Murph conversations.
* Activate OAuth-backed storefront agents after a successful credential callback, backfill already-authorized pending sources, capture the customer action blocked by each escalation, count customer-blocking storefront escalations in health, and auto-verify storefront operator-domain aliases when an approved account domain has trusted AAO/brand linkage evidence.
* Polish shared Murph room participant avatars with clearer initials, image-ready rendering, and consistent room presence stacks.
* The product discovery widget now renders progressive discovery results as
* sellers answer instead of waiting for every seller to respond. It shows a
* "Waiting for X, Y… (N of M sellers)" banner while sellers are still
* answering, accretes newly-landed seller groups into the view as they arrive
* (polling automatically), and once results are complete, drops the banner and
* flags any sellers that timed out.
* Rename the buyer "seat" concept to "advertiser" across the entire wire surface (hard cutover, no aliases — the platform is in beta). What changed for integrations:
* **MCP tool names**: `customer_get_seats` → `customer_get_advertisers`, `seat_details_list`/`seat_details_get` → `advertiser_details_list`/`advertiser_details_get`, `seat_create`/`seat_update`/`seat_delete` → `advertiser_create`/`advertiser_update`/`advertiser_delete`, `select_seat`/`switch_seat` → `select_advertiser`/`switch_advertiser`. Old names now return unknown-tool errors; MCP clients that cache the tool list must reconnect.
* **Tool scope value**: `seat` → `advertiser`.
* **Response keys**: `seats`/`seat`/`seatId` → `advertisers`/`advertiser`/`advertiserId` (e.g. `GET /api/customers/:id/seats` now returns `advertisers`; syndication, signals, audit-log, media-buy and campaign payloads return `advertiserId`).
* **Request fields**: service-token creation `scope: "SEAT"` → `scope: "ADVERTISER"`, `seatName` → `advertiserName`; signals/audit-logs `seatId` query param → `advertiserId` (a legacy `seatId` param is now ignored); UTM `source: "seat"` enum value → `"advertiser"`.
* **Unchanged**: the `x-scope3-seat-id` request header (stable wire contract; carries the advertiser ID), all SQL/DB column names, and the `/api/customers/:id/seats` path (response keys renamed, path kept).
* This aligns the public API with the terminology used everywhere else in the product.
* Render selected Murph user mentions as recognized people chips in the composer.
* MCP OAuth clients can now self-register callback redirects during dynamic client registration, and account admins can self-serve exact browser origins for non-credentialed MCP/OAuth CORS access.
* Murph now audits who can read each connected Slack channel. When a channel's members span more than one customer account, Murph pauses account-specific answers there — explaining why and pointing to DMs — until a Scope3 admin reviews the channel, so one company's data is never shown to another.
* In Slack channels deliberately shared between two customers, Murph now scopes itself to the relationship: it discusses supply tracked for the named counterparty and general product questions, keeps every other account detail out of the channel (redirecting to a DM), and limits supply tracking there to the counterparty's own domains.
* Shared Murph rooms now create in-app notifications when a teammate mentions you.
* Shared Murph rooms can now be started and linked before the first Murph prompt is sent.
* Shared Murph room lists now update from a live stream instead of repeated browser polling.
* Unlinking an ad-platform connection now preserves your advertiser mappings
* instead of leaving them orphaned. Mappings whose account is still reachable
* through another connection of the same platform keep working; mappings only
* the unlinked connection reached are marked unreachable (`unreachableAt` on
* the linked-account resource), never resolve at buy time, and recover
* automatically when you reconnect the platform or re-map the account — a
* temporary disconnect/reconnect never loses mapping work.
* Products with an FX-converted price (a rate-of-the-day quote into a currency
* the storefront doesn't natively price in) now carry an `expiresAt` timestamp
* through `discover_products`, `browse_discovery`, and product details — the
* hold expires at the next UTC midnight. Buyer-side caches (the discovery
* snapshot and the per-query fan-out cache) now treat any cached quote past its
* `expiresAt` as stale and transparently re-fetch a fresh price instead of
* serving the expired one. Natively-priced products are unaffected and continue
* to cache freely.
* Added a downloadable wholesale avails and pricing CSV template and clarified how sellers should prepare manual wholesale pricing uploads for ad-server-backed sources.

## 4.13.0 — July 5, 2026 at 6:31 AM UTC

* Adapter connections are now keyed by grant identity — who actually authorized
* the platform grant (the authenticating user, and organization for org-scoped
* grants; captured from the platform's identity endpoint on Meta and Snap, and
* derived from the reachable account set elsewhere). Reconnecting the same
* account updates its existing connection instead of duplicating it, a reconnect
* can no longer attach a fresh credential to a different grant's connection, and
* intentionally distinct grants (an agency manager account alongside a client's
* directly-shared account) coexist as separate connections.
* Progressive discovery documentation: end-to-end worked example (request, first-wave response, sinceRevision polling loop, stop conditions) across the discover-products and browse-products task pages and the discovery guide. The `guidance` field — the human-readable next-step hint returned on progressive responses and campaign-unbound sessions — is now declared in the DiscoverProductsResponse schema and OpenAPI spec.
* Hosted managed ad-server sources no longer receive sustained source-outage Slack or Pylon notices that ask sellers to restore infrastructure operated by Interchange. Reconnect-labeled ESA timeout failures are now treated as Interchange runtime issues instead of seller credential-repair tasks.
* Validate FreeWheel ad-server credentials before accepting the managed source, so invalid credentials are rejected during setup instead of creating a broken source. The source dashboard now also separates first-sync progress from action-required failures.

## 4.12.0 — July 4, 2026 at 10:09 AM UTC

* Murph now treats supply-tracker phrasing as requested-supply intent and gives the correct account-connection path when it cannot record the request from the current channel.
* Product discovery supports progressive responses. Pass `progressive: true` to `discover_products` and the first response returns already-answered sellers within seconds — with `resultsComplete`, a monotonic `revision`, and `pendingAgents` naming who is still working — while remaining sellers keep landing in the background. Poll `browse_discovery` with `sinceRevision` to receive only newly landed seller groups until `resultsComplete` is true. Sellers' answers arrive one at a time, flight-search style, instead of everyone waiting for the slowest storefront.
* Murph conversations can now be feature-flagged into same-customer shared rooms with shareable room links, live room presence, participant-authored room messages, @Murph/@room composer routing, same-customer @mention suggestions, per-person chat avatars, and a room-level stream that refreshes viewers when new messages are persisted.

## 4.11.0 — July 3, 2026 at 7:17 PM UTC

* Clarify how `adagents.json` hosting modes relate to publisher-origin verification and AAO-hosted records.

## 4.10.0 — July 3, 2026 at 5:17 PM UTC

* Buyer reporting now handles multiple advertiser currencies honestly and can consolidate across them. Each advertiser block names its native currency; cross-advertiser totals carry a `totalsCurrency` and their money metrics are null (never a mixed-currency sum) when advertisers span currencies. A new `displayCurrency` parameter — defaulting to your home currency when your advertisers share one — returns a `consolidated` block: each advertiser's spend converted at the current rate-of-the-day and then summed, with a per-advertiser audit trail and `conversionInfo` metadata (rates, as-of day, anything unconverted, `estimate: true`). Consolidated figures are display estimates only and never affect billing or settlement.
* Adapter connection summaries now report `mappedAdvertiserCount` — how many of
* your advertisers have an active mapping to one of the connection's currently
* active accounts. A connected storefront with 0 mapped advertisers is not yet
* buyable (a media buy for an unmapped advertiser fails with
* `account_mapping_required`), and this field lets buyers and agents surface
* that gap right after connecting instead of at the first failed buy.
* Media buys on ad platform storefronts now resolve their external account
* through the advertiser mapping — the account mapped to the campaign's
* advertiser under Settings → Connections — instead of the connection-level
* default account. An unmapped advertiser fails fast with a structured
* `account_mapping_required` blocker carrying the Connections link, rather
* than silently buying on a shared default account. Existing selected
* accounts are backfilled into mappings automatically where exactly one
* advertiser has transacted through the connection; ambiguous connections
* are left unmapped and surface the blocker instead. Buy account resolution
* (connection, credential, and how the account was chosen) is now logged for
* audit.
* Reporting metrics documentation now correctly describes spend as denominated in the advertiser's primary currency rather than claiming USD (which was only true for USD advertisers).
* Add storefront adapter credential health writeback, a nightly expiry/refresh sweep, and lifecycle docs for reconnecting or rotating unhealthy credentials.
* Fix two defects that could leave a storefront-routed media buy's package budgets out of sync with what was approved. Approved budget updates now locate the buy under either media-buy id space, so an operator approval actually persists the new budgets instead of failing silently; and package backfill from a resolved source route no longer overwrites newer, locally-staged budgets with the create-time snapshot.
* A creative that fails to sync to a sales agent is no longer reported as successfully synced, and sync failures now carry the agent's rejection reason instead of a bare agent name — so buyers see when a creative did not reach the sales agent and why.

## 4.9.0 — July 3, 2026 at 12:05 PM UTC

* Brief requests to composition storefronts now return only composed products and proposals — the raw wholesale catalog is no longer merged into brief responses, and a discovery deadline no longer substitutes the catalog for a composed answer. Ask with a brief and every product you get back was composed for it; ask in wholesale mode for the full catalog. Source pass-through still serves as the fallback when composition fails.
* Add an in-chat campaigns widget for buyers. Ask Murph (or use the Campaigns
* rail item) to see an advertiser's campaigns as a table with status, flight,
* and budget, then drill into a single campaign for its delivery metrics, media
* buys, and creatives. Gated behind the buyer creative v2 rollout.
* Storefronts with product composition can now return ADCP proposals from `get_products`. When a brief gives a basis for a multi-product plan, the composition engine emits draft proposals — named plans with budget allocations across the composed products, per-allocation rationale, and brief alignment — with deterministic proposal IDs that stay stable across re-discovery. Buyers see these as recommended plans in discovery and can execute them via `apply_proposal`.
* Murph approval prompts now use clearer wording when an action was suggested after reading external or uploaded content.
* Connecting an adapter account (Reddit, Snap, Meta, TikTok, and other
* provider storefronts) is now one click: the `connectionUrl` returned by
* `connect_storefront` sends the buyer straight to the provider's OAuth
* consent screen instead of the Connections page, and every adapter has a
* permanent shareable link at `/connect/{provider}` (for example
* `/connect/reddit`) that works without a pre-minted customer URL.
* External-agent pass-through storefronts now keep Interchange-owned merchandising features off, including Chef composition and Storefront approval queues.
* Product discovery results now refresh immediately after a seller updates their catalog. Seller catalog-change webhooks retire cached discovery fan-out results, so buyers no longer see a pre-change product set for up to 10 minutes after a seller publishes changes.
* Retrying a discovery with a longer wait (`waitSeconds` / `waitMode: long`) now actually re-queries the sales agents that missed the shorter window. Previously the retry could return the cached partial result from the quick pass, leaving `incompleteAgents` unchanged no matter how long you offered to wait.
* Fix two storefront currency setup issues. (1) The setup checklist did not update after saving — the embedded setup widget cached read responses and never refreshed them after a write, so confirming your settlement currency left the step showing as incomplete until a full page reload, even though the change had saved. Writes now invalidate cached reads so the checklist reflects the change immediately. (2) The currency picker in the create-account flow rendered its label on top of the placeholder text; the label now floats correctly so the two no longer overlap.
* Cross-currency buys are no longer blocked by a temporary FX rate-feed outage: the most recent locked rate-of-the-day (up to 7 days) is carried forward as the day's rate, with operations alerted. When no recent rate exists, cross-currency requests now fail with an explicit `FX_RATE_UNAVAILABLE` error instead of a generic pricing error, and stale FX quotes are rejected with `FX_QUOTE_EXPIRED` on every create path.
* Clarify MCP customer-switching errors so agents use the dedicated `customer_switch` tool, then retry the original API operation without per-call customer scoping.
* Documented response bodies for eleven API operations that previously showed
* no response schema — creative preview, discovery product details,
* optimization suggestions (list/get/approve/reject), notification read and
* acknowledge, advertiser account, storefront connection archive, and the
* adapter-storefront connect handoff (including its `connectionUrl` browser
* link). Also corrected the ad-server source refresh docs: it returns the sync
* run status and ids with 200, not an empty 204.
* Sellers whose ad server can execute but can't expose commercial data (e.g. GAM publishers who won't let us run the pricing query) can now supply wholesale price and availability by uploading a percentile-CPM feed keyed on their ad-server selectors. The platform validates it deterministically, prices the seller's products from it (floor derived from p25; p50/p75 as guidance), and exposes per-country availability and expected CPM as a product forecast rather than splitting the catalog per country. Inventory too thin to clear the storefront's minimum line item is held back, and a source that has enabled the module can't go live until it has a current, non-stale feed.
* Priced wholesale products can now be purchased end-to-end. Previously a wholesale product was shown and priced during discovery but failed at execution, because media-buy pricing was resolved only from the internal products table where wholesale products have no row. Execution now resolves a wholesale product's price from the wholesale catalog — the same source discovery reads — so a priced wholesale product completes a buy. Wholesale buys are supported in the source's settlement currency; selecting a converted (FX) currency returns a clear, specific error rather than failing obscurely.
* Wholesale products can now be purchased in a converted (FX) currency, not just the source's settlement currency. At execution the buyer's converted-currency selection is priced by re-minting the same buyer-currency option discovery served (converted at the rate quoted when the product was selected); a stale quote or an unavailable rate fails with a clear error rather than a wrong price. Re-reconciling an open wholesale buy now keys it to its native settlement currency, so it matches the existing buy instead of creating a duplicate.

## 4.8.0 — July 2, 2026 at 10:10 PM UTC

* Buyer Creative v2: creative evaluators now run through an extensible registry that declares each evaluator's default gate posture (blocking vs advisory), and the creative-session evaluate boundary accepts the full buyer-creative workflow stages (generation, selection, refinement, finalization, adaptation, approval, live\_learning) alongside the legacy draft/final values. Draft variants are scored 0-100 from their evaluator results and the highest-scoring variant is recommended.
* Discovery responses no longer block on LLM-generated group descriptions and product relevance copy in long-wait mode. `waitSeconds`/`waitMode: long` now only extend the time upstream sales agents get to answer; descriptive copy is served deterministically inline and upgraded in the background, cutting up to 15 seconds from long-wait discovery latency.

## 4.7.0 — July 2, 2026 at 9:45 PM UTC

* Flighted media buys no longer fail when part of the pacing schedule has already elapsed. Fully-elapsed pacing periods are skipped across campaign execution, per-buy pacing changes, and campaign pacing cascades — only still-live flights are sent to the seller — and executing a buy whose entire schedule has elapsed now returns a clear, fixable error instead of a seller rejection.
* Documented 21 previously-undocumented storefront API operations in the
* OpenAPI reference — storefront compliance, agent capability refresh, the
* embedded sales agent connection lifecycle (list, get, test, refresh,
* deactivate, reactivate, status, service account), the ESA catalog surfaces
* (products, signals, signal candidates, adapter capabilities, publisher
* properties, ad-server selectors, creative formats), and the storefront
* product catalogue. The `refresh_esa` MCP operation now returns the refresh
* result body (`status` + `syncRunIds`) instead of an empty response,
* matching the REST endpoint.

## 4.6.0 — July 2, 2026 at 8:24 PM UTC

* Managed ad-server source health now reflects the booking write path: a source
* whose last media-buy forward failed at the infrastructure level shows as
* degraded until a booking succeeds or the evidence ages out, and successful
* bookings count as positive health evidence.
* Polished the buyer Marketplace widget so buyers can open and manage supply they would buy, including editing buyer ask details and removing tracked supply from the widget.
* Documented 18 previously-undocumented buyer API operations in the OpenAPI
* reference — advertiser restore, discovery product details, creative
* list/preview/duplicate, creative sessions, optimization suggestions,
* advertiser accounts, storefront connections, notifications, and campaign
* property lists. The notification endpoints (list, read, acknowledge) are
* also documented for the storefront API.

## 4.5.0 — July 2, 2026 at 7:24 PM UTC

* Murph inventory-source test campaigns can now select wholesale buyer products by the source product IDs shown in the test plan.
* Fixed a pair of bugs where a package/budget update to a storefront-routed media buy could either silently self-activate without operator approval and without ever reaching the seller, or (the inverse) have a legitimate, already-approved update wrongly rejected. Both were caused by an internal check that assumed a live media buy always has an activation timestamp recorded, which isn't true for buys accepted asynchronously.

## 4.4.0 — July 2, 2026 at 6:26 PM UTC

* Brief-based product discovery on ESA-backed storefronts is faster: products
* are served directly from the managed catalog instead of waiting on a live
* sales-agent call. A storefront whose catalog is still being set up now returns
* quickly with no products instead of timing out.
* Storefront operators are now notified (in-app and email always, plus Slack once they've enabled that event type in their Slack settings) as soon as a new approval work item — a media buy, creative, ad-server approval, or inventory-shortfall review — is waiting for them, instead of only being discoverable by checking the Approvals page.
* `update_campaign` now rejects `mediaBuys[].products[].budget`/`pacing`/`bidPrice` on a media buy that already has deployed packages (ACTIVE, PAUSED, COMPLETED, INPUT\_REQUIRED, or a PENDING\_APPROVAL version staged on top of one of these) instead of silently accepting the request with no effect. Once packages exist, the product-level field is informational only: update `packages[].packageId` + `budget`/`pacing`/`bidPrice` instead (fetch `packageId` via `get_campaign` with `includeProductDetails=false` to avoid response truncation on buys with many creatives).

## 4.3.0 — July 2, 2026 at 5:58 PM UTC

* Adapter connection accounts now carry account hierarchy: each discovered account
* reports an `accountType` (`advertiser`, `organization`, or a platform subtype such
* as Amazon `sponsored_ads`/`dsp` or TikTok `publisher_identity`) plus
* `parentExternalId`/`parentName` for its parent business or manager account. Google
* connections now expand manager (MCC) accounts into their client accounts, so
* agency users whose access flows through an MCC see the buyable child accounts.
* Organization (manager) accounts are listed for context but cannot be selected,
* mapped, or used for buys.
* Clickthrough URLs on media-buy creatives are now automatically wrapped in the Scope3 click tracker across all outbound paths (sync\_creatives, create\_media\_buy, and update\_media\_buy inline creatives), so per-media-buy click attribution works regardless of which path a creative ships on and without the format having to declare a tracker slot. No action needed: existing tracker URLs and creatives without a clickthrough are left untouched.
* Avoid unnecessary Redis scans during product discovery enrichment cache invalidation.
* The storefront MCP `api_call` tool can now fetch the seller-analytics rollup
* — as the named operation `get_seller_analytics` or as raw
* `GET /api/v2/storefront/seller-analytics`. This fixes the seller dashboard
* widget failing to load its analytics view over MCP.
* Fixed a `create_media_buy` failure classification bug: a fixable, non-refusal source failure (for example, a stale or invalid product reference) was being reported as a seller rejection. These failures are now categorized separately from a deliberate rejection.
* Detect ADCP sandbox support from raw account capability metadata as well as normalized sandbox extensions.
* The Source Health workbench now shows a source's TRANSACT axis — the outcome of the last `create_media_buy` forward to it — as its own cell, distinct from discovery/reachability health. When a storefront forwards a buy, the source's transact cell records the outcome (`succeeded`, `pending` for an async acceptance still awaiting confirmation, `business_rejected`, `not_authorized`, `invalid_request`, `source_unavailable`, or `failed`) plus the media-buy reference and a `masked` flag. This is recording-only: it never changes a source's health status and raises no work items or alerts — interpretation is deferred to the diagnosis layer, mirroring the conformance-vs-health separation. A curated (linked) source records with `masked: true`, because its buyer-facing failure category is identity-masked and therefore not yet trustworthy for diagnosis.
* Use warmed managed sales agent products directly when cached wholesale data is sufficient, avoiding unnecessary live upstream discovery calls.
* Managed ad-server source health now reflects the managed pipeline (sync
* status, catalog freshness, connector reachability), refreshed by the platform
* every 15 minutes. Sellers are notified with the specific cause when a failure
* needs their action (for example, reconnecting ad-server credentials);
* platform-side failures alert Scope3 operations instead of asking the seller
* to fix them.
* Realign the signal `keyType` enum to the AdCP context-match spec: added context signals (`country`, `region`, `metro`, `topic`, `eidr`, `gracenote`, `isrc`, `gtin`, `rss_guid`, `isbn`, `custom`) and identity signals (`rampid_derived`, `hashed_email`); removed values Scope3 does not resolve end-to-end (`coreid`, `yahoo_connect`, `property`, `postal_code`, `uk_postal_district`, `lat_long_radius`). A new privacy-boundary validator rejects any signal (or custom-signal targeting profile) that mixes context and identity key types.
* Fixed linking or unlinking a creative on a campaign sending a no-op `update_media_buy` to every media buy in the campaign, including legs whose contracted format has nothing to do with the changed creative.
* Chat composer now tells you when a file can't be attached instead of silently dropping it. Files that are too large, an unsupported type, or over the per-turn attachment limit surface a dismissible warning naming the file and the reason, so an oversized upload never disappears without a trace.
* Creative uploads that hit a size or file-count limit now tell you exactly which files were skipped and why (e.g. "chime-video.mp4 wasn't added — the upload went over the 100 MB limit.") instead of dropping them silently. The creative-intent and creative-confirmation responses carry a `skipped_files_notice` and the full `skipped_files` list; the in-chat card shows the ratio ("3 of 4 saved") and lists every dropped file so you can re-add exactly those without re-uploading the whole batch; and Murph relays it in one line rather than telling you to re-upload everything.
* Storefront onboarding now judges the Walk → Run step by how much of your committed inventory you are actually expressing, rather than a fixed coverage checklist. Once your plan's target model has enough substance, "Run" means you are fully expressing the inventory you have committed to — channels or properties you have declined lower the bar rather than counting against you; until then the previous coverage heuristic still applies. This makes the phase Murph coaches you toward reflect real expression progress.

## 4.2.0 — July 2, 2026 at 9:52 AM UTC

* Advertise sandbox support on storefront wrapper agents when their active backing inventory sources support sandbox tests, so sandbox advertisers are not skipped during buyer discovery.

## 4.1.0 — July 2, 2026 at 8:36 AM UTC

* Allow buyers to include the exact supply, package, audience, placement, or capability they would buy when tracking requested supply.
* Inventory source diagnostics now include a structured issue breakdown so sellers can see every active source-health signal, not only the top cause.
* External sales-agent storefronts with merchandising off now skip Chef
* composition and answer buyer briefs through live source passthrough, while
* composition ingredient loading reads only cached components and does not
* synchronously warm upstream sources. Public and internal docs now explain
* component-cache success, passthrough behavior, and Murph diagnostics language.
* Sandbox advertiser discovery now force-refreshes seller capabilities before
* checking sandbox eligibility, and storefront sandbox filtering no longer drops
* agents from stale cached capability rows before that refresh can run.
* ADCP account credential registration and rotation also trigger a scoped
* background account-inventory refresh, while unregistering a credential
* immediately cancels its locally cached discovered accounts.
* Storefront readiness now carries a persisted onboarding plan — the durable, shared record of what your storefront could sell. It includes a target model (seeded cheapest-first from your connected agents' declared capabilities and your business profile), which setup steps are complete, and how your storefront has moved through the Crawl → Walk → Run phases over time. The phase is still derived live from your setup; the plan records the transitions for history so any surface can answer "where is this seller?" from one source of truth.
* Buyer integration account mapping tables are clearer, with less repeated platform/source text and a precise default-account label.
* Connection handoff links now preserve the full destination through login and can resolve provider-style targets before starting adapter OAuth.
* Sellers may now receive a **supply nudge** notification (`storefront.supply_nudge`)
* in their notification feed — a human-reviewed heads-up from the Scope3 team when
* something on their storefront needs attention (e.g. a sales agent that's stopped
* responding, or an unconfirmed settlement currency). It's delivered like the other
* operational alerts (in-app + email, plus Slack if enabled) and is always-on. The
* value is additive to the notification `type` enum in the v2 API.
* A storefront media-buy leg that a source never accepts no longer polls forever. A never-resolved route (one that never received an upstream media-buy id — e.g. its source became unreachable) still un-accepted past a 14-day age backstop is now force-terminalized to `canceled` (an operational terminal, not a seller rejection), so the buy stops showing an indefinite pending status. Buys that DID resolve upstream are never affected — a legitimately future-dated flight sitting `pending_start` until its start, a buy awaiting creative upload, and live `active`/`paused` buys are all exempt. Operationally, a pending `update_media_buy` that misses its resolution deadline now also alerts on-call, matching the existing acceptance-timeout alert.
* Supply requests now resolve the requesting customer strictly by authenticated account, closing a cross-tenant data exposure where customers sharing a company name or domain could see or modify each other's requested supply.

## 4.0.0 — July 2, 2026 at 4:39 AM UTC

* Adapter storefront connection links now open the selected provider's OAuth flow directly instead of only landing on the Connections page.
* `get_campaign`/`list_campaigns` responses no longer include `mediaBudget` or `fees` — these were derived campaign-level values that no longer reflect how the Scope3 fee is tracked. The Scope3 fee is now recorded per media buy in the platform ledger (previously it was a single campaign-wide figure), so a campaign-level `mediaBudget`/`fees` split is no longer meaningful. Use `budget.total`, `feeType`, `allocatedBudget`, and `unallocatedBudget` (all unchanged) to reason about a campaign's budget.
* Clarify that creative manifest validation is an optional diagnostic, not a launch prerequisite, send upgraded creative manifests to sync\_creatives with canonical format\_kind, and return a clear unsupported-capability error when an agent does not support ADCP validate\_input.
* Clarify setup documentation around AdCP, AAO, and publisher authorization: external sales-agent sources authorize the external agent URL, ad-server sources using Interchange's hosted storefront agent authorize `https://interchange.io`, AAO registration blocks source connection, AAO compliance is advisory for activation, and publisher `adagents.json` authorization is surfaced as an advisory setup/product signal today.
* Adapter connection deep links now preserve storefront context when launched with tool-style snake\_case query parameters.
* Discovery sessions can now hold the same product selected more than once. Each selection carries its own `selection_id` and becomes an independent media-buy line item (distinct budget, pacing, and flight), matching what `create_media_buy` / `update_media_buy` already support. Omit `selection_id` for a product's single default selection; supply a distinct value to add a repeat. Re-sending an existing `selection_id` updates that instance instead of creating a duplicate.
* **Breaking:** the `selected_products` field on the `start_product_discovery` and `update_discovery_session_products` outputs changed from an object keyed by product id to an array of selection instances (to represent repeats). Consumers that indexed it as `selected_products[productId]` must iterate the array and read each element's `product_id` / `selection_id`.
* Creatives with `target_format_ids` set now count toward campaign format coverage and are synced to the sales agents whose formats they cover, so one creative can satisfy multiple publishers' format IDs instead of needing a separate duplicated creative per publisher.
* Fix `discover_products`, `auto_select_products`, and product detail responses (REST and MCP) always prefixing CPM/budget amounts with `$` regardless of the product's or campaign's actual currency. A non-USD product (e.g. a ZAR-priced Ozone package at 450.23) rendered as `$450.23`, misrepresenting the price by the FX rate. Prices now carry and display their real currency (e.g. `ZAR 450.23`), falling back to `$` only when currency is genuinely unknown or when a price range mixes multiple currencies.
* Fix storefront discovery under a tight deadline: when the buyer-discovery budget
* is nearly exhausted by the time a source's live get\_products would run, serve the
* source's warmed catalog instead of issuing a doomed sub-viable live call. Prior
* behavior floored the timeout to \~1ms, which failed instantly ("timed out after
* 1ms") and wrongly marked the source unhealthy — so a live-only third-party source
* briefly dropped out of discovery. A budget-exhaustion skip is no longer treated
* as a source-health failure.
* Murph sandbox inventory source and buyer-infra test campaigns now execute through the normal buyer campaign, discovery, product-selection, and execute\_campaign tools instead of constructing direct upstream ADCP media-buy probes.
* ESA managed ad-server sources now expose explicit sandbox-account readiness and ensure endpoints so no-spend buyer tests can verify or create the tenant-managed sandbox account instead of inferring sandbox setup from the source type.
* Require confirmation before Murph records or removes requested supply, let buyers remove specific seller/channel supply they no longer want to buy, block requested-supply writes during admin simulation dry-runs, and have Murph share the public seller signup link instead of creating seller-outreach workflows when buyers ask what to send sellers.
* Fix Murph confirmation token replies so they continue the original conversation before executing the approved action.
* Murph's confirmation prompts now explain exactly why a follow-up confirmation was rejected (for example, a dropped conversation thread id) instead of a generic "expired or didn't match" message, and consistently remind the calling client to keep passing the same conversation thread id when confirming a gated action.
* Normalize embedded sales agent sandbox account domains before provisioning managed storefront sources.
* Adaptive onboarding phase (Crawl → Walk → Run, plus Pass-Through). The storefront readiness response now includes a derived `phase`, and Murph frames onboarding conversationally by phase — orienting a seller ("you're in the Crawl phase; your next step is …") instead of reading a flat checklist. `pass_through` (a finished-products sales agent) has no rungs; composition storefronts progress Crawl → Walk → Run. Derived live from setup-mode + readiness — no new persistence.
* Open the Marketplace widget for filtered storefront browse questions and keep supply requests focused on named sellers.
* Operational source failures on a storefront media buy no longer surface as a seller rejection. When a source fails to resolve a previously-accepted buy — its task `failed`/`canceled`/`aborted`, or it went silent past the acceptance deadline — the leg now settles as `canceled` (a terminal fault) rather than `rejected` (a seller "no, don't retry"). Only a genuine merits refusal (`rejected`/`governance-denied`) settles as `rejected`, and it now carries the seller's reason through to `get_media_buys.rejection_reason` (redacted per source kind). A source that reports `rejected` on its delivery feed also surfaces a rejection reason.
* Remove the standalone creative `validate` pre-flight (POST /api/v2/buyer/campaigns/{campaignId}/creatives/validate and the validate\_creative diagnostic). It provided no value over submitting a creative directly — attach/create the manifest and deliver it through sync\_creatives / campaign execution, which runs the necessary manifest checks and surfaces any issues.
* Deleting a media buy that is still awaiting approval is now treated as a retraction: it withdraws the pending request instead of adding a spurious "approve media buy" task to the seller's operator approval queue. Cancelling a buy the seller has already committed to is unchanged.
* Separate ready supply from waiting supply in the Marketplace widget and return buyer-safe ready dates for supply requests that are now available.

## 3.31.3 — July 1, 2026 at 10:35 PM UTC

* Coerce forwarded ADCP product-discovery time budgets to integer seconds so seller agents reject fewer valid discovery requests.

## 3.31.2 — July 1, 2026 at 7:17 PM UTC

* Polish the Marketplace widget so requested supply uses the public status contract and remains visible from the storefront discovery surface.
* Fix creative upload dropping duplicate-named files: when a zip bundle contained the same filename in different folders (e.g. two versions of a video), only one was saved. Every uploaded file is now kept as its own creative, with folder-qualified names to tell same-named versions apart.
* Direct sales adapter storefronts run by our expert agents no longer require seller settlement currency readiness checks, and adapter media buys preserve the buyer-declared currency without requiring an Interchange payout currency.
* Tighten Marketplace supply-list copy so the widget avoids repeating the same label across the header, rail, and panel.

## 3.31.1 — July 1, 2026 at 6:18 PM UTC

* Clarify the seller readiness nudge for settlement currency setup, including multiple payment currencies and Interchange's automatic currency conversion.
* `update_campaign` with `mediaBuys[].products[].budget` on a pacing buy now propagates the new budget to the corresponding packages proportionally, preserving the existing period split. Previously the write landed only on the informational `budget_amount` field and left spend authority unchanged.
* `update_campaign` no longer targets archived media buy versions when a buy with the same ID has both an archived and an active row with `valid_to IS NULL`, which could cause budget updates to silently write to the wrong version.

## 3.31.0 — July 1, 2026 at 5:30 PM UTC

* Add shelf filters to the advertiser creative library listing (`GET /api/v2/buyer/advertisers/:advertiserId/creatives`): filter by `role` (evergreen/reference), `source` (uploaded/generated/connected), `format_kind`, `asset_type`, and `dimensions` (e.g. `300x250`), alongside the existing `search` and `promoted` filters.
* Storefront media buys accepted asynchronously by a source (including ESA / managed-sales-agent buys) now create their packages when the hourly status poll activates them, matching the synchronous and push/poll acceptance paths. Previously these buys could go active with no packages, which blocked package-level delivery reporting and optimization.
* Fixed a race condition where adding creatives to a campaign in quick succession could silently fail to sync some media buys, instead of the intended "a pending version already exists" error.
* Fix `POST /api/v2/buyer/campaigns/{campaignId}/creatives/validate` (and the `validate_creative` MCP tool) silently dropping VAST/DAAST-specific fields (`delivery_type`, `vast_version`, `vpaid_enabled`, `companion_ads`) from a creative manifest before validation. A correctly-formed VAST or DAAST asset was matched against an earlier, looser asset schema in the manifest's asset-type union and had its distinguishing fields stripped, causing the downstream ADCP agent to reject the manifest as missing `delivery_type` even though the buyer had supplied it.
* Also accept the standard AdCP `asset_type` discriminator (e.g. `asset_type: "image"`) on every asset shape, including inside `image_carousel` cards. Previously an asset carrying it would be rejected outright (for carousel card media, which has no lenient fallback) or silently downgraded to unvalidated passthrough (for top-level manifest assets).
* `get_media_buys` now returns `rejection_reason` on a storefront media buy whose rolled-up status is `rejected`, so a buyer can see WHY a source refused the buy without a separate delivery call. The reason is the source's merits-refusal message (already redacted, carrying no seller identity); operational failures (unreachable source, credential fault) map to a non-rejected status and so never surface a rejection reason. The field is present only when the buy is rejected and a reason was reported — never fabricated.
* Hide internal Linear ticket identifiers from buyer-facing requested supply responses.
* Limit buyer-facing requested supply responses to customer-safe tracking status instead of internal workflow details.
* Make the buyer Marketplace nav item open the storefront discovery widget directly instead of redirecting through Murph, and hide it when supply browsing is not enabled.
* Media buys now support the same product as multiple distinct line items, and multiple media buys per storefront in the same currency. A buyer can add a product more than once to one media buy (each line item carries its own budget, pacing, and flight — e.g. parallel optimization arms or pacing periods) and run several media buys on the same storefront and currency. Each line item has a stable `buyer_ref` returned on reads; pass it to `update_media_buy` to update or remove one specific line item when a product appears more than once.

## 3.29.0 — July 1, 2026 at 2:59 PM UTC

* `get_campaign` now accepts `includeProductDetails=false` to strip `formatOptions` from `mediaBuys[].products[]`, exposing `packages[]` without response truncation for media buys with many creatives. This unblocks callers that need `packageId` values to submit package-level budget updates via `packages[].budget`.

## 3.28.0 — July 1, 2026 at 1:55 PM UTC

* Fix buyer-side errors hit when setting up cross-currency campaigns:
* `POST /api/v2/buyer/campaigns/{campaignId}/creatives/validate` no longer returns a 500. Creative-manifest validation now invokes the ADCP `validate_input` task through the supported SDK entry point.
* Adding a product to a discovery session now FX-converts the product's pricing options during validation. A buyer whose advertiser transacts in a marketplace-FX currency (e.g. ZAR) can now select inventory that settles in another currency (e.g. USD) using the cross-currency pricing option they were quoted at discovery, instead of being rejected as a currency mismatch.
* Adding a product that was never in your discovery results (a stale or invalid id) is now rejected at selection with a clear message, instead of being silently accepted and failing later at execution. The execution-time "no pricing options" error is likewise clearer, pointing you to re-run discovery.

## 3.27.2 — July 1, 2026 at 1:08 PM UTC

* Capture A2A server task handles when storefront source forwarding receives async media-buy responses.

## 3.27.1 — July 1, 2026 at 12:02 PM UTC

* Fix Murph sandbox inventory-source test diagnostics so async `create_media_buy` responses preserve the returned task id for follow-up status checks.
* Clarified that GAM key-value targeting is supported through ESA signals, and labeled key-value-based property targeting as coming soon.

## 3.27.0 — July 1, 2026 at 11:15 AM UTC

* Storefront creation now captures settlement currencies up front, suggests an obvious storefront currency from the entered domain, lets the provided operator domain use normal auto-verification instead of forcing it back to unverified, and shows pending domain approval as an explicit readiness state.

## 3.26.1 — July 1, 2026 at 7:54 AM UTC

* A media-buy leg that fails to forward to a source is now recorded as a terminal route, so it appears in the media-buy status rollup (`get_media_buys` / status polling) instead of silently vanishing — a partial forward no longer under-represents its failed source(s). The stored leg status reflects the cause: a source that refused the buy on its merits reads as `rejected`, while an operational failure (unreachable source, credential fault, forward-chain error) reads as an unobservable leg — so an operational blip is never mislabeled to the buyer as a seller refusal and never terminally demotes a still-delivering partial buy. Failed legs carry no delivery and are never re-polled.

## 3.26.0 — July 1, 2026 at 7:07 AM UTC

* Fix managed (embedded sales agent) inventory sources that could strand at `PENDING` after provisioning — leaving their products and signals invisible to buyer discovery even though the ad server was fully connected and synced. Provisioning no longer ties a source's active status to a sandbox test account; the ESA sync-health pass now advances a connected managed source to `ACTIVE` and warms its buyer-discovery catalog; and a connected, inventory-synced source whose product catalog never populated is now surfaced as a critical health alert instead of failing silently.
* Add timeline buckets to inventory source diagnostics so source call failures, rejections, timeouts, and latency movement are visible inside the selected window.
* Reddit and TikTok discovery and community mirror catalogs now avoid advertising creative formats that their current media-buy creation paths cannot fulfill.
* All campaigns now use GROSS budgets: the budget you supply is the all-in total and the Scope3 fee is carved out of it (media budget = budget − fee). The `feeType` (GROSS/NET) choice has been removed from campaign creation — NET (fee added on top) is no longer selectable. Existing campaigns keep their recorded fee type, and the campaign response still returns `feeType`.
* The `campaignBudgetType` field has been removed from advertiser create, update, and detail responses. It was a single-value setting that did not affect behavior.
* Buyers can now select products that settle in different currencies within a single campaign — across storefronts and within a single multi-currency storefront. Previously a discovery session was restricted to one currency. The buyer always transacts and is billed in their own primary currency; products are split into one media buy per storefront and settlement currency, each denominated in the buyer's primary currency with its own locked FX rate.
* Move storefront marketplace browsing out of Connections into a buyer storefront discovery MCP app widget, keeping Connections focused on provider credentials, accounts, and integration feature policy. The widget now also exposes customer supply-wishlist requests through the existing supply-request API.
* Campaign creative template responses now include V2 product format options alongside legacy format IDs.
* Fix mapping a connected ad-platform account (Reddit, Meta, Snap, and other adapter integrations) to an advertiser — the discovered account now appears in "External account mappings" and can be linked to an advertiser as expected.
* Fix cross-currency product discovery for foreign-currency advertisers. Buyer
* `discover_products` stamps the advertiser's primary currency onto the request as
* `filters.pricing_currencies`, which drives the FX overlay's convert-to-buyer-
* currency in the storefront `get_products` handler. The in-process ESA dispatch
* was dropping those filters, so a storefront routed through an in-process sales
* agent returned products in the source currency (e.g. USD) to a foreign-currency
* advertiser (e.g. ZAR) — the FX overlay never fired. The dispatch now threads the
* request filters through, matching the MCP seam, so discovery quotes are converted
* to the advertiser's currency.
* Keep buyer Connections focused on adapter/provider integrations instead of listing every marketplace storefront.
* Make Marketplace easier to reach and make requested supply statuses read as supply the buyer would buy when it is live.
* Read publisher domains from nested embedded-sales-agent inventory metadata so wholesale products expose their declared publisher properties in discovery and storefront product identity.
* Product discovery API responses now include live storefront timeout retry hints at the top level whenever the discovery service detects incomplete agents.
* Source diagnostics now compare each source's current lookback window with the prior window, making newly worse, improved, and recovered call-health patterns visible in the diagnostics overview.
* Source diagnostics now show whether a reliability issue is owned by the seller's source operator or Scope3's managed runtime, so teams can route call, latency, timeout, and callback problems faster.
* Product discovery responses now surface live storefront timeout signals in `incompleteAgents` even when the upstream agent reports the timeout as an error reason rather than a structured timeout flag.
* Upgrade Sonnet-tier AI defaults to Claude Sonnet 5, including Murph, chat, cost tracking, and supporting tools.

## 3.25.0 — June 30, 2026 at 7:29 PM UTC

* The advertiser creative library now distinguishes its two durable roles. Creatives can be promoted with a `creative_role` of `evergreen` (serve-ready, reusable across campaigns) or `reference` (a generation input, not served) via `POST /advertisers/:id/creatives/save-to-library` (identify the creatives by `creative_ids` or by `collection_id`; no campaign required).
* Brought creative now persists the instant it's uploaded, even before an advertiser is chosen: `POST /buyer/creatives/stash` saves the upload customer-scoped and returns ids, and `get_creative_intent` accepts those `creative_ids` to adopt them into an advertiser later — so naming the advertiser in a later turn no longer loses the upload. The creative-intent widget now owns advertiser selection via an in-widget dropdown (defaulted to a named advertiser, switchable) that re-surfaces that advertiser's campaigns, and the saved creatives route to whichever advertiser is selected on commit. Uploads that are never claimed (no advertiser, no campaign) are automatically reaped after 7 days so abandoned stashes can't accumulate. Promoting creatives now renders the advertiser's creative-library shelf with the newly-saved item in it, and the shelf can be opened on demand (`GET /advertisers/:id/creatives`) — so a buyer can see and confirm their library in chat. The library list (`GET /advertisers/:id/creatives`) returns each creative's `creative_role`, its `creative_source` (provenance — uploaded/generated/connected), and its `reuse_count` (campaigns it is actively attached to), and accepts `?promoted=true` to return only library creatives — flight-specific creatives stay attached to their campaign.
* Fix media buys placed through a manual-approval storefront getting stuck in PENDING\_APPROVAL with a `status_refresh_failed` error after the operator approved them. The storefront's submitted-task envelope now returns the storefront-minted media buy id as `task_id` (the id every routing, status-sync, and settlement rail joins on) instead of the internal operator-queue record id, so the buy's status reconciles to active once the source accepts.

## 3.24.0 — June 30, 2026 at 7:23 PM UTC

* Cross-currency buys now work end to end from discovery to media-buy creation. When a buyer transacting in a marketplace-FX currency selects a product priced in a storefront's settlement currency, the buy is created at the FX rate the buyer was quoted at `get_products` and the buyer-facing budget is recorded in the buyer's (campaign) currency — instead of being rejected as "not sold in that currency" or stamped in the seller's currency. The quote is honored for the UTC day it was issued (the rate-of-the-day lock); a selection from a prior day is rejected so the buyer can re-discover at the current rate.
* Storefront media buys accepted asynchronously by a source (e.g. behind manual moderation) now have their packages created when the acceptance resolves, instead of going live with no packages. This restores package-grain delivery, reporting, and optimization for those buys.

## 3.23.0 — June 30, 2026 at 6:00 PM UTC

* Product discovery now surfaces inventory priced in any currency, not just the advertiser's primary currency. Buyers with a ZAR advertiser can see and select GBP or USD products; FX conversion is handled at booking time.

## 3.22.1 — June 30, 2026 at 4:46 PM UTC

* Improved quick product discovery latency for storefronts with non-guaranteed managed wholesale products by returning warmed storefront products immediately and moving uncached LLM relevance enrichment out of the quick response path.
* Signing up again when you already have access to an organization no longer triggers new-member side effects. Previously, a repeat signup for an existing member (e.g. an OAuth re-auth, a retried request, or a stale signup tab) could send a false "new user signed up" notification to the organization's admins and overwrite the organization's recorded email domain. The signup flow now detects that no new access was granted and routes the user to log in instead, leaving the organization untouched.

## 3.22.0 — June 30, 2026 at 3:03 PM UTC

* Use adapter-declared sandbox support and channel metadata when routing discovery through Scope3-hosted adapter storefronts.
* Fixed product discovery so deadline-bound storefront searches can return available storefront products instead of timing out while additional product composition is still running.
* The launchable seller Dashboard now renders the learned default posture and learned auto-approve suggestions, matching what the agent shows inline — the REST analytics path previously omitted them (a shared enrichment helper now backs both). Docs also explain how a held or rejected media buy maps to the seller's acceptance policy, for both sellers (the pre-screen verdict) and buyers (why a buy was held/rejected).

## 3.21.0 — June 30, 2026 at 2:22 PM UTC

* Advertise sandbox support from v6 storefront adapter capabilities so sandbox advertisers can discover connected adapter inventory.
* Disabled inventory sources no longer affect storefront readiness checks or source diagnostics.
* Route-polled storefront deliveries now record per-package delivery onto the buyer's packages, so package-grain pacing and optimization reflect real delivery on poll-based sources, not only sources that push the delivery webhook.

## 3.20.0 — June 30, 2026 at 1:21 PM UTC

* Provider account mappings are now recorded in buyer activity so teams can audit when an integration account was mapped to an advertiser.
* Add an in-chat "Per-buyer auto-approve" view. Ask Murph to open it to see which trusted buyers skip your media-buy review queue and how many of each buyer's buys auto-forwarded that your acceptance policy would have held — the would-have-held count surfaces the carve-outs worth revisiting first. Opt a buyer in or remove one inline (handed to Murph). Read-only and media-buy-only.
* When the bounded discovery setup-phase capabilities probe times out (or fails), product discovery now falls back to the agent's last-known capabilities instead of treating it as "unknown". A previously-probed but momentarily slow agent keeps routing correctly rather than being mis-handled on its first cold discovery; only a never-probed agent is treated as unknown. Warm cache hits are unaffected.
* Update `@adcp/sdk` to 9.4.0 so outbound AdCP requests carrying push notification authentication are signed by the SDK before seller capability-based signing decisions.

## 3.19.0 — June 30, 2026 at 12:25 PM UTC

* Buyer-direct adapter media buys on providers that don't yet report buy status (those that expose campaign creation but no status read) no longer show a perpetual "status refresh failed". The status sweep now recognizes a provider that can't report status as a capability gap rather than a failure, and leaves the buy at its last-known status — no false error, no alert — until status reporting is available for that provider.
* Publishers can now connect an AdsWizz source (streaming audio + podcast) as a managed ad server, alongside Google Ad Manager, FreeWheel, and SpringServe. The connection takes an AdsWizz agency API key; inventory, products, and delivery surface to buyers through the storefront like any other managed source.
* TikTok adapter media buys now support live status polling through `get_media_buys`, so buyer campaign status refresh can read back TikTok campaigns created through delegated adapter auth.
* Fix the reporting `completionRate` to be completions per **paid impression** (`completedViews / impressions`) instead of `completedViews / views`. The previous denominator (viewable impressions) was non-standard for a completion rate and could exceed 100%; the corrected rate is bounded at ≤ 1 and is now consistent across buyer, seller, and tactic reporting. For CPM video the paid unit is the served impression; CPV/TrueView buys (billed per view) will track the billed view as the denominator when that inventory is supported.
* Product discovery no longer hangs when a single sales agent's endpoint accepts the connection but never responds. The per-agent capabilities pre-load is now bounded by a short deadline, so a non-responsive agent is skipped and the remaining agents' products return quickly instead of stalling the whole discovery up to the client's request ceiling.
* Add external account mappings from buyer integrations to advertisers.
* Storefront catalogs now recover wholesale products from upstream sales agents that reject the platform's AdCP version. When a source returns `VERSION_UNSUPPORTED` for a release it should have accepted within the same major version, the catalog warmer retries once at the highest release that source advertises, so a source on an older build no longer empties its catalog.

## 3.18.0 — June 30, 2026 at 8:18 AM UTC

* Keep seller-authored wholesale products discoverable during quick product discovery when a live storefront product query is slow, without dropping live managed ESA avails.
* Stop reporting successful pending media-buy status polls as status refresh failures.
* Fixed OAuth callback handling so successful logins do not get stuck on the signing-in screen when the callback route restarts mid-exchange.
* Fix Meta adapter media-buy status refresh for buyer-direct adapter buys. Status
* polling now uses the storefront delegated adapter credential for route-less
* adapter buys, so `get_adcp_status` and background polling can refresh
* `get_media_buys` status without incorrectly falling back to direct ADCP agent
* auth. Missing delegated credentials now surface a specific
* `adapter_credential_unavailable` blocker instead of a generic status refresh
* failure.
* Harden seller settlement-currency validation. `create_media_buy` now re-validates
* the storefront's resolved settlement currency against the marketplace-supported
* set: a storefront whose `defaultCurrency`/`paymentCurrencies` holds an off-list
* code (persisted before the write-side guard) now gets a clear
* `settlement_currency_unsupported` error instead of an opaque spread-ledger CHECK
* failure deep in booking. The storefront update API also now enforces that
* `defaultCurrency` is part of `paymentCurrencies` when both are provided (the
* primary settlement currency is always part of the payout set).
* Internally, seller-settlement validation now runs against a dedicated
* `SETTLEMENT_CURRENCIES` set (the seller-payout axis), separate from the
* buyer-side `MARKETPLACE_FX_CURRENCIES` FX-admission set, with the invariant
* `MARKETPLACE_FX_CURRENCIES ⊆ SETTLEMENT_CURRENCIES` enforced by test — so a future
* change to the FX-admission set can never wrongly reject a legitimate
* direct-settlement currency.
* Storefront media buys now record per-package delivery from source push notifications, so package-grain pacing and optimization reflect each package's real delivery instead of staying at zero.
* Fix the Buyer Discounts widget, which couldn't load — the host had no REST allow-list row for it, so every API call it made was denied. A new CI gate keeps each widget's directory, build list, both resource registries, README index, host REST-policy, and reachability in sync, so this class of drift (dead or unreachable widgets) can't ship again.

## 3.17.0 — June 30, 2026 at 4:21 AM UTC

* Stop abandoned adapter-connection OAuth attempts from piling up on the
* Connections page. Starting a fresh connect now supersedes prior expired,
* credential-less attempts for the same provider, so you no longer see duplicate
* "saved connection but no usable credential" cards. Completed connections and
* in-flight connects (including a second account being connected) are preserved.
* Fix a 500 when disconnecting an adapter storefront connection (Settings →
* Connections). Disconnecting now succeeds and terminalizes the connection, its
* credentials, and its mirrored accounts.
* Murph now infers catalog purpose from context (feed type, existing setup, conversation) and confirms with the buyer instead of presenting a menu of internal concepts during catalog setup.
* Fixed `probe_sales_agent` returning a false "unreachable" verdict when called with a numeric database id instead of the agent's external string slug. The tool now returns an actionable error in that case. Also improved the error message from the capabilities-refresh endpoint to include the failure kind and HTTP status, making it easier to diagnose transport or auth issues.
* Cross-currency (FX) media buys are now supported on storefronts that require operator approval. The quoted rate-of-the-day is snapshotted when the buy is submitted and held for 24h pending review; on approval the held rate is replayed exactly, so the buyer is billed at the rate they were quoted. If approval lands after the hold window expires, the buy is rejected (`fx_quote_expired`) and the buyer must re-discover and re-buy at the current rate.
* Cross-currency (FX) media buys can now be updated (re-budgeted) on storefronts. An `update_media_buy` recovers the buy's already-locked rate-of-the-day from when it was created and re-applies it — the source is billed the settlement-currency budget (buyer budget ÷ the locked rate) and the buyer is never re-quoted, so a later update never drifts the rate. Changing a buy's currency is rejected (`currency_change_not_supported`): a buy's currency is fixed for its whole life.
* Polish the seller Test Runs widget: loading and error states now use a card-bordered treatment consistent with other seller MCP app widgets, and the empty state is replaced with a structured card that explains how to get started with sandbox test runs.
* Sellers can now choose any marketplace-supported settlement currency. The
* self-service currency picker offers the full set the marketplace supports
* end-to-end (21 currencies, including launch markets IDR and ZAR plus KRW, INR,
* MXN, PLN and others) instead of a partial list, so a seller in those markets can
* get paid directly in their own currency. The storefront update API now rejects a
* `defaultCurrency` or `paymentCurrencies` entry that is ISO-valid but not
* marketplace-supported (e.g. `AED`), which would otherwise produce a buy the
* ledger cannot record and the FX overlay cannot price. The setup widget also
* explains that buyers paying in other currencies are converted to your primary at
* the daily rate, so you never need to add a currency just to sell into it.
* Fix storefront media buys from a source that PUSHES delivery (a signed source webhook rather than being polled) showing zero in buyer reporting. The push path only ran the seller spread-ledger accrual, so the delivery never reached `GET /reporting/metrics`. It now also feeds the same buyer-reporting sink the poll path uses, scoped to each leg's route under the verified source.

## 3.16.0 — June 29, 2026 at 7:03 PM UTC

* Product budgets can now be updated on active media buys without pausing delivery. Adding or removing products still requires draft status.
* Fix Murph erroring on long Slack answers: the message-splitter used the wrong Slack size limit, so a long answer still posted in one piece and hit `msg_too_long`. Answers are now split to fit Slack's limit, and a very long answer is bounded to a few messages instead of a wall.
* Add `url_hash` to the signal `keyType` enum. Clients that already hold AdCP-canonical URL hashes (44-char std-base64 of blake3-256 over the canonicalized URL) can register signals against `url_hash` directly. The pre-existing `url` keyType keeps working: writers that project URL signals into the AdCP context-agent's `signal:*` keyspace translate `url` → `url_hash` and canonicalize+hash the value at the wire boundary, so buyers continue to see raw URLs throughout the API while the wire format matches what `adcp-go` expects.

## 3.15.0 — June 29, 2026 at 5:50 PM UTC

* Sign-in no longer shows an error when an OAuth authorization code is exchanged a
* second time (e.g. a redirect re-entry after the first exchange already
* succeeded). The callback now resolves `invalid_grant` idempotently: if a session
* already exists it continues to your destination; otherwise it restarts sign-in.
* Per-buyer auto-approve now keeps trust honest: when a trusted buyer's media buy is auto-forwarded that your acceptance policy *would* have held, the gate records it (it never holds the buy). Each override exposes a `policyBypassCount` and `lastPolicyBypassAt` on `GET /api/v2/storefront/buyer-auto-approvals` (and via Murph), so you can see whether a buyer you opted in is pushing buys you'd otherwise have flagged and revisit the carve-out. The forward decision is unchanged — this is visibility only.
* Complete the in-chat bring-your-own-creative flow. When a brought creative fits no placement on the campaign it's flagged as a misfit with the nearest placement suggested (non-blocking — the creative still attaches), and the buyer can map it to a placement of their choice from a menu on the card: rows go green as you pick, and one **Save** commits the whole batch in a single write (no per-action chat turn) with the card updating in place. Buyers can also reassign a creative to a different placement directly in chat (e.g. "move the 300×250 to the leaderboard") via the new `remap_creative_placement` operation. Size→placement matching now falls back to the size encoded in a canonical format id when the format agent's spec is unavailable, so mapping no longer silently fails; placements that can't be read at all are surfaced honestly on the card instead of leaving creatives unexplained. Mapped creatives now name the placement they cover ("Maps to: …") on the card, and each creative shows its detected specs — image dimensions, video dimensions and duration, audio duration — read from the file at upload (including creatives uploaded inline). The in-chat creative widgets show a loading state instead of a blank frame while results load. Buyer-creative-v2 only.
* Clarify storefront lifecycle and health labels so storefronts that accept buyer transactions are shown as transacting instead of generically active or live.
* The storefront media-buy approval pre-screen now reads your *written* acceptance policy more thoroughly and sorts each buy into three tiers instead of two: clearly on policy (auto-forwarded), needs a look (queued), and clearly against an explicit rule you wrote (surfaced as a strong decision-support signal on the queued item — the buy still queues; nothing is auto-rejected yet). It generalizes past a fixed category list — a rule like "we don't accept fast-food advertisers" is honored even though it isn't a built-in category — by reading what you actually wrote, and an AI second-opinion can flag a conflict the keyword pass missed before a buy auto-forwards. The new `recommendation` value `auto_reject` and `rejectionReason` field appear on the evaluation response. The pre-screen errs toward human review whenever it is unsure or the AI layer is unavailable, and the AI layer can only ever route a buy to human review — never approve or reject one on its own.
* Murph no longer leaves a Slack message frozen on "On it…" when the service restarts mid-answer. An interrupted turn is now replaced with a clear "I got interrupted — please re-ask" message instead of a status that never resolves.
* Guaranteed media buys that exceed the ad server's availability forecast are now held for operator review instead of silently overbooking. The sales agent stamps an inventory-availability signal on the buy; the storefront surfaces it as a "Guaranteed availability review" work item plus a readiness item. This is per-buy (it does not change the storefront's auto-approve setting) and does NOT auto-clear when the order goes live — the operator confirms or adjusts the goal. Non-guaranteed buys are unaffected. Also fixes the discovery-time `bookability` signal, which was inert because it read the ad server's object-shaped forecast availability as a string.
* Murph widget activity lines now persist, so a committed action (e.g. "Approved Acme Motors") stays in the conversation after a page reload, not just for the current session.
* The Murph chat request accepts an optional `modelContext` field — the latest widget activity-line writeback — which is sanitized and fed to the model as a `<widget_activity>` context block on the next turn, so Murph knows what a widget just did without a re-prompt.
* Add customer-scoped requested supply tools backed by Linear customer needs, plus an internal Storefront Brain rollup for requested seller/channel demand.
* Seller analytics now flags buyers whose media buys consistently clear your review and recommends opting them into per-buyer auto-approve. When the buys from one buyer that came to you for review have all cleared and forwarded with no rejections, the agent surfaces a `learned_auto_approve` suggestion in `sellerRecommendations[]` that points you at the per-buyer auto-approve control for that buyer. It looks only at media-buy approvals (not creative review or delivery), and it's suggest-only — the agent recommends and you decide; it never changes an approval gate on its own. Evidence-gated, so a short or mixed approval history yields no suggestion.

## 3.14.0 — June 29, 2026 at 3:31 PM UTC

* The `/auth/token` endpoint now returns `400 invalid_grant` (instead of `500`)
* when an OAuth authorization code is expired, already used, or otherwise invalid
* — for example when a single-use code is exchanged twice. Sign-in clients get a
* clear, actionable signal to restart the flow, and these expected client
* conditions no longer page as server errors.
* Fix cross-currency (FX) accounting and discovery for wholesale passthrough inventory. A ZAR (or other marketplace-FX) buy against a USD-settling storefront's passthrough product now records its FX leg in the spread ledger and currency book — the buyer currency, held rate, settlement amount, and zero break-even spread are captured even when the source's per-unit rate isn't exposed (previously the position was dropped, so the currency book under-reported FX exposure). Separately, wholesale products whose source omits `channels` now pass `get_products` response validation (the field defaults to an empty array) so they remain discoverable and buyable.
* Sponsored-buyer actions (approve / suspend / reactivate) now post a non-prompting activity line to the chat — e.g. "Approved Lakeside Motors" — so what you did stays visible in the transcript without re-prompting Murph.
* Fix storefront media buys accepted asynchronously (the source returns `submitted`) never showing as active or in reporting. The storefront-minted routing id arrived as a task id and was not persisted as the buy's `adcp_media_buy_id`, so the status-sync job and the buyer reporting feed (both keyed on it) could not resolve the buy. It is now persisted on the storefront-parked acceptance path.

## 3.13.0 — June 29, 2026 at 2:05 PM UTC

* `service_token.active_adcp_agent_ids` now contains every `adcp_agent` row in the token's scope, not just `status = 'ACTIVE'`. Downstream consumers (rtdp, rt-audience) treat membership as "this token has access to this agent" rather than "ACTIVE-right-now", so flipping an agent to DISABLED/FAILED/PENDING no longer silently revokes access. The boolean `active_adcp_agents` flag retains its ACTIVE-only semantics.
* Improve the adapter connection OAuth callback (Settings → Connections). A failed
* or timed-out connection now shows a clear page with a "Back to Connections"
* action instead of a raw error-JSON page, and a successful connection returns you
* to the Connections page with that provider preselected instead of the app
* homepage.
* Storefront/managed (GAM) media-buy delivery now flows into buyer reporting. The route-poll worker feeds the delivering leg's per-day metrics into the reporting pipeline under the buyer-facing media-buy id, so `GET /api/v2/buyer/reporting/metrics` shows impressions/spend for managed buys instead of zero. Metrics are attributed to the real delivery day, and only legs carrying a daily breakdown are fed (a breakdown-less snapshot is held back so it can't double-count against later per-day data). Correct per-day attribution depends on the companion sales-agent change that surfaces the daily breakdown.
* Murph no longer presents an ad-server source and its owning Storefront as two peer agents when sellers test products.

## 3.12.0 — June 29, 2026 at 10:50 AM UTC

* Manage buyer discounts in chat. Sellers can now open a **Buyer discounts** widget to see, add, edit, and remove their rate-card discounts grouped by axis — the buyer's advertiser brand and its buying operator. The add form previews where a typed domain keys in its published corporate hierarchy (so you can tell whether a discount covers a whole house or just one subsidiary), and a discount never prices a quote below your wholesale cost.
* Add `GET /api/v2/storefront/house-discounts/resolve?domain=` — a read-only helper
* that resolves a brand or operator domain up its published corporate hierarchy
* (e.g. `converse.com → nike.com`) and reports the chain, the house it rolls up to,
* and whether that hierarchy is known. It lets a discount-authoring surface preview
* where a discount will key — and warn when a domain only covers itself — before
* the row is saved. Creates and matches nothing.

## 3.11.0 — June 29, 2026 at 8:56 AM UTC

* Fix media-buy delivery status incorrectly showing `pending_start` for buys that are actually delivering. When a sales agent's reporting read is temporarily unavailable, the status poller no longer regresses an in-flight buy to `pending_start`; it preserves the last-known status and retries.
* Fixed a race condition in Murph conversation creation that caused a `duplicate key value violates unique constraint` error when two concurrent requests attempted to start the same conversation simultaneously.
* Fix the Signal components MCP app launch so the standalone seller widget is registered, served, and allowed to call its signal authoring endpoints.
* Persist seller analytics chat artifacts as assistant-turn blocks and rehydrate them when a Murph conversation is reopened.
* Murph no longer errors out when its Slack answer is long. A thorough, docs-grounded reply that exceeded Slack's message-size limit previously failed the whole turn ("I hit an error trying to answer that"); long answers are now split across threaded replies, and Murph keeps Slack answers concise rather than pasting large doc excerpts.
* Cross-currency FX quotes now hold for the day. `get_products` and `create_media_buy` resolve the same deterministic rate-of-the-day per currency pair (fixed at first use each UTC day, sourced from the spot feed), so a buyer quoted "ZAR 52" books at "ZAR 52" as long as they transact within the day — no more intraday drift between the quote and the buy. FX-converted products carry a hard `expires_at` (the next UTC midnight); after it, re-discover to be re-quoted at the new day's rate. The expiry encodes the marketplace's FX-risk hold window and is tunable.
* Cross-currency FX now works on wholesale / passthrough products, not just composed ones. A buyer transacting in a marketplace-FX currency is admitted on the wholesale discovery path, the source's settlement-currency options are converted to the buyer's currency at the rate-of-the-day (a natively-priced currency is never re-converted), and the passthrough leg books the cross-currency split on the spread ledger — the source is still paid in its own currency. Conversion happens once, at the buyer's edge: internal storefront-to-storefront (pool/cascade) hops carry the settlement currency through and never re-convert, so a buy is never FX'd twice.
* When a buy matches both a brand discount and an operator discount, the buyer now
* gets the **larger** of the two (ties resolve to the brand axis) — rather than the
* brand discount always winning. Brand and operator are independent buyer
* identities, so neither hides a better deal from the other, and discount
* composition is now uniformly larger-of across both axes and across the
* house/buyer-instruction rails. Nearest-ancestor-wins still governs within a
* single axis.
* Improve Meta app-install discovery guidance with mobile-first creative, placement, and iOS measurement readiness recommendations.

## 3.10.0 — June 29, 2026 at 4:32 AM UTC

* Added a Components widget for mapping ad-server inventory into products and a bulk signal creation tool so sellers can create many signals after one approval.
* Storefront operators can now opt a specific trusted buyer into automatic approval
* for their media buys while the storefront stays in manual review for everyone else.
* Set it with `PUT /api/v2/storefront/buyer-auto-approvals/{buyerCustomerId}` (or ask
* Murph), and list current overrides with `GET /api/v2/storefront/buyer-auto-approvals`.
* It is relax-only and media-buy-only — an enabled buyer's media buys skip both the
* review queue and the acceptance-policy screen, creative review is unaffected, and it
* only takes effect while `mediaBuyApproval` is `manual`. Buyers must have submitted a
* media buy to the storefront (no pre-arming an unknown buyer), and disabling keeps the
* record for audit.
* Removed the standalone `validate_signals` storefront operation and the `POST /esa/{esaId}/signals:validate` REST route. Signal validation now runs through the dry-run path — `manage_esa_signal` with `action: "validate"` — which returns the same validation result plus a preview of the signal, in one non-persisting call.

## 3.9.0 — June 28, 2026 at 10:28 PM UTC

* Cross-currency buying is now global and automatic. Which currencies the marketplace accepts via FX is a single marketplace-curated set — the major traded currencies plus key emerging markets, including the launch markets Indonesia (IDR) and Brazil (BRL) and the pilot currency ZAR. A buyer in an accepted currency is admitted at every storefront and converted to that storefront's settlement currency at the platform spot rate; the source is always paid in its own currency. A storefront operator still decides which currencies it settles in directly (`paymentCurrencies`) — there is no FX on those, and no per-storefront FX configuration.
* Storefront creation now accepts an operator domain, storefront readiness blocks go-live until that domain is set and verified, and account customer-domain updates preserve storefronts that intentionally operate under a different domain.

## 3.8.0 — June 28, 2026 at 9:35 PM UTC

* Murph no longer deflects credential-policy questions to the secure credential form. Questions about bearer-token rotation, replacing compromised credentials, audit logs, or governance now get a real answer. The secret-in-chat backstop still redirects when an answer actually routes a secret into the chat ("paste your token here"), but no longer discards an answer that merely explains how credentials work.
* Storefronts with an FX overlay enabled can now accept and book a media buy in a buyer currency they do not settle in (e.g. a ZAR-locked buyer against a USD-settling storefront). `create_media_buy` admits the buyer currency, snapshots the operator's rate, and bills the source in its own currency (buyer budget ÷ rate); the cross-currency edge — the USD cost leg and the buyer-currency sell leg plus the booked rate — is recorded on the storefront's spread ledger. Default off; same-currency buys are unchanged.
* Not yet covered (follow-ups): FX buys on a storefront that requires media-buy approval are rejected until the approval path carries the rate snapshot; `update_media_buy` on an FX buy and FX over raw-passthrough inventory are not yet currency-aware; and FX spread rows are recorded but not yet surfaced in margin reports.
* Cross-currency curation now sources FX rates automatically: a storefront with the FX overlay enabled lists the buyer currencies it accepts (`allowedBuyerCurrencies`) and each is priced at the current platform spot rate — operators no longer have to hand-enter a rate, though they may pin a per-pair override in `rates`. The rate in effect is locked onto a media buy when it is created, so it bills the source and settles the campaign at the booked rate for the campaign's whole life. Spot rates only for now (no hedge); a forward rate for the settlement horizon is a later refinement. Default off.
* Murph now opens each conversation aware of the support requests you've already filed. On the first turn it sees your open and recently-resolved requests, so it won't ask you to re-file something already in flight, can pick up an open item when your message relates to it, and will let you know when a related issue looks resolved.

## 3.7.0 — June 28, 2026 at 7:52 PM UTC

* Murph now proactively follows up in your support channel when an issue you reported is resolved — a one-time "we believe this is now fixed, could you retry?" message, so you're not left guessing whether to try again.
* Creative format specs derived from a canonical `format_kind` now use the
* asset\_type the manifest validator actually detects (`vast`, `daast`, `html`)
* instead of names it never produces (`vast_tag`, `daast_tag`, `tag`, `html5`). This
* restores per-asset validation (duration, codec, dimensions) for VAST, DAAST, and
* HTML/HTML5 formats, which was previously silently skipped — so a non-conforming
* VAST/DAAST/HTML creative for such a format is now caught at validation instead of
* at the ad server.
* Creatives for adapter/canonical formats (e.g. Snapchat) no longer fail
* validation when the format's per-platform creative agent is unreachable. The
* format spec is now resolved from the format declarations the storefront adapter
* already provides on the product (`format_options`) before falling back to the
* agent, so a retired or unavailable creative-agent host can't block a creative
* whose spec we already hold. Genuinely unknown formats still return a clear
* "format not found" error.
* Refreshed the seller Signals widget with a new header and tabbed layout, plus a collapsible **Adapter capabilities** panel that surfaces what your connected ad server supports for signals — mapping kinds, source types, value types, and grouped (include/exclude, AND/OR) semantics. The panel is driven by the adapter's own capability manifest, so it reflects each adapter accurately rather than assuming a single ad server.
* Added a **Signal components** entry to the seller menu that opens the Signals widget directly. When you have more than one ad server connected, the widget includes an ad-server picker so you can browse and author signals on each one (two ad servers of the same type are distinguished by network code), and switch between them in place.
* Storefront budget updates now retry version activation on transient lock contention before giving up, and report the buyer's `update_media_buy` task honestly: the task completes when the new budget is live (including when a prior attempt already applied it) and fails only when the change genuinely never landed. Previously a never-staged update could be falsely reported as completed.
* Buyer product discovery (`get_product_details`) now surfaces a product's
* canonical `format_options` (format\_kind / format\_option\_id) alongside the v1
* product cards, so buyers can reference a format without the per-platform
* creative agent\_url. The storefront adapter already provides these; the read
* path now carries them.

## 3.6.0 — June 28, 2026 at 5:44 PM UTC

* Retry the creative asset media probe on transient read failures so uploaded image/video/audio dimensions and specs are reliably detected and persisted. Previously a transient network/timeout/5xx while reading the freshly-uploaded file could silently drop width/height/codec with no backfill.

## 3.5.0 — June 28, 2026 at 4:39 PM UTC

* A posture you pin as the storefront's learned default now sticks: the Merchandising Agent will not relearn over a pinned default, even as it keeps learning from outcomes, until you change it. Clearing the default returns it to agent-managed so the agent can learn a new one again. This makes the operator override durable once automatic learning is enabled for a storefront.

## 3.4.0 — June 28, 2026 at 2:33 PM UTC

* Ad-server provisioning probe failures now carry their recovery on the tool result. When a `storefront_api_call` operation fails with a structured upstream code (e.g. `ADAPTER_PERMISSION_DENIED`, `ADAPTER_NETWORK_NOT_FOUND`), the error response now surfaces that upstream code and the upstream remediation hint — so a seller's agent gets precise next steps at the moment of failure instead of a generic validation message. Murph's storefront-setup guidance no longer hard-codes the per-error-code remedies; it relays the remediation the result carries and keeps the operator out of raw adapter internals.

## 3.3.0 — June 28, 2026 at 2:14 PM UTC

* Storefront adapters now align to the AAO registry's canonical model: the
* deprecated per-platform creative-agent advertisement (the `creative_agent_url`
* field in generated adagents.json and the buyer-facing `list_creative_formats`
* catalog surface) is removed, and each adapter's publisher domain is aligned to
* the domain the registry publishes (e.g. Snap `ads.snap.com` → `snapchat.com`,
* Meta `business.facebook.com` → `facebook.com`). Creative formats are discovered
* canonically via `get_products` `format_options`; the registry already publishes
* these formats canonically with no creative agent.
* `manage_esa_signal` gains an `update` action to edit an existing signal (a full replacement, like create), and its `validate` dry-run now previews an update when given a `signalId` (otherwise a create). The `update` write is confirmation-gated like create/delete.
* ESA ad-server connection errors now carry structured recovery. The `test_esa_connection` and `get_esa_status` storefront operations classify adapter-probe failures (permission denied, network-code not found, invalid credentials) as `400 VALIDATION_ERROR` with the upstream `ADAPTER_*` code and remediation hint — matching connection creation — instead of a generic `503 Service Unavailable`. Murph's ESA tools surface that code and remediation in their results, so a seller gets precise next steps when a provisioning probe fails.
* Author buyer discounts conversationally through Murph and the storefront API.
* Discounts are structured rate-card objects keyed to one of a buyer's two
* identities: a **brand discount** (the advertiser or its house, e.g. `nike.com`
* reaching Converse) or an **operator discount** (the buying agency/DSP or its
* holdco, e.g. `wpp.com`), set via the required `scope` field. Each resolves up the
* buyer's brand hierarchy; the nearest ancestor wins within an axis and a brand
* discount beats an operator one. `create_house_discount` and
* `update_house_discount` are typed storefront operations (list/delete reachable
* through the storefront API), and `(houseDomain, scope)` is unique per storefront
* so the same domain can carry both a brand and an operator discount. New
* documentation frames these as the structured discount rail alongside buyer
* instructions (the tool for operator-and-brand intersections, country terms, and
* freeform notes), including how they compose and the wholesale-cost floor.
* The storefront media-buy forward worker no longer re-attempts a still-undelivered approved buy indefinitely. It now stops retrying a buy whose source forward has not succeeded within 6 hours of approval — on a wholesale forward failure the buyer was already notified on the first attempt, so the further re-attempts only burned upstream calls. Buys keep retrying within the window so a transient source outage still recovers automatically.
* Sellers can now clear or pin the Merchandising Agent's learned default negotiation posture. Ask your agent to clear the saved default (revert to none) or to pin a specific posture yourself — the saved reason then reads "Pinned by you". The learned default remains a fallback the agent uses only when it has no fresher read for the buyer in front of it, and your operating instructions always take precedence. The learned-default reason now reads with a friendly posture label (e.g. "Hold value booked 64% over 14 runs").
* The storefront signal create endpoint (`POST /esa/{esaId}/signals`) now accepts `?dry_run=true`, which validates and previews a signal draft via the sales agent's dry-run route without persisting it (returns `{ valid, issues, preview }`).
* Seller analytics now surfaces the Merchandising Agent's learned default negotiation posture — the rule the agent saves for itself once a posture has been converting consistently. The `sellerAnalytics.learnedDefault` payload (and the "What your agent learned" panel) shows the saved posture, why it was learned, and when. The agent uses it only as a fallback when it has no fresher read for the buyer in front of it — never a forcing override — and your operating instructions always take precedence.
* A media buy budget update that is forwarded to the inventory source but then fails to activate on the storefront side (the new budget version doesn't flip live) now terminalizes the buyer's `update_media_buy` task with a `failed` webhook instead of leaving it open indefinitely. The failure is reported with a distinct reason so a buyer can tell "the update reached the source but the live budget didn't change" apart from "the source rejected the update" — and it is never falsely reported as completed, since the live buy is still on the old budget. Previously a push-only or polling buyer was left with no resolution at all on this path.

## 3.2.1 — June 27, 2026 at 9:41 PM UTC

* Creatives can now be assigned to products that declare formats only as canonical
* `format_options` (no v1 `format_ids`). Creative↔product format matching now folds
* each product's `format_options[].format_option_id` into its accepted format set,
* so a creative whose `format_id.id` equals a product's `format_option_id` matches
* by that exact canonical id — fixing assignment to v2-native catalogs (e.g. Snap)
* that previously reported "no declared formats" or filtered out every creative.

## 3.2.0 — June 27, 2026 at 8:26 PM UTC

* Approved creatives that fail to forward to an inventory source are now retried automatically (bounded) instead of being stranded after a single attempt, and the buyer's `sync_creatives` webhook fires on the terminal outcome. A transient source failure is retried in the background for up to 30 minutes; on eventual delivery the buyer gets the approved webhook, and if the forward is structurally impossible or the retry window is exhausted the buyer gets a `failed` notification (with a generic message — the inventory source is never disclosed) so a push-only buyer is no longer left believing an undelivered creative is live. Previously an approved-but-undelivered creative produced no buyer notification at all.
* `manage_esa_signal` with `action: "validate"` now runs through the sales agent's dry-run route, so it returns a preview of the signal (what buyers would see) alongside the validation result — and surfaces would-be create/update conflicts as issues — all without persisting anything.
* Sellers can now set a discount scoped to a corporate house. A discount keyed at a house (e.g. `nike.com`) automatically reaches every descendant — so it applies to a `converse.com` buy that rolls up to it — and a discount can also be keyed at an exact brand or operator domain. It matches on either the buy's advertiser brand or its buying operator. When more than one applies, the **nearest** node in the corporate tree wins (a brand-specific discount beats its house's; a parent never overrides a child), and the brand dimension takes precedence over the operator dimension. Author them through the new `/api/v2/storefront/house-discounts` endpoints (list, create, update, delete). The discount is applied at product discovery and always floored at the wholesale cost.

## 3.1.0 — June 27, 2026 at 6:01 PM UTC

* Reduce repeated no-op `sync_accounts` calls to third-party storefront inventory sources by reusing a prior successful account sync for unchanged account payloads.
* `dryRun: true` on `create_esa_product` / `update_esa_product` now runs through the sales agent's single dry-run pass — the same validation and preview a real create or update would produce, with nothing persisted. An update dry-run also checks the product you're editing, so it surfaces not-found and inventory-profile conflicts before you commit. A dry-run check no longer asks for write-confirmation (it changes nothing); only the real commit does.
* Fixed `ask_murph` returning an invalid MCP result (error -32602) whenever a turn surfaced a widget. The embedded UI resource now carries the widget HTML inline, so MCP clients receive a valid tool result instead of a protocol error.
* Fix `update_media_buy` emitting a wire-invalid `format_id` (`agent_url: ""`, or a missing `agent_url`) when falling back to a product's declared formats. The AdCP format-id schema requires a real `agent_url`, so a forged empty value produced a reference the sales agent could reject. The update now drops any product format that lacks a usable `agent_url`/`id` instead of forging one.
* Fixed a bug where Murph's write-confirmation prompt ("reply with the confirmation phrase…") was sometimes replaced with an unrelated "I can't take credentials in chat — open the secure form" message. The credential-safety check no longer fires on confirmation turns, which carry no secret.
* Validating or previewing a wholesale product now surfaces an advisory warning when a declared publisher property (by id or tag) isn't found in the registry or on the publisher's live `adagents.json` — usually a typo. This is a **warning only** — it never blocks authoring. It's lag-aware (a publisher that exposes no property list yet is not flagged) and skips publishers that haven't authorized the agent, since the authorization advisory already covers those.
* Seller analytics now shows what your Merchandising Agent learned: which negotiation posture is actually converting, and whether following its own history-derived recommendation booked better than diverging from it. This surfaces the `postureConversion` data in the seller-analytics widget (both the Ask Murph panel and the seller dashboard) and documents it in the seller analytics reference.
* Reduce production Sentry noise from known Slack setup drift and harden several root causes found in prod triage, including catalog cache upserts, Murph conversation creation races, invalid Cloud Function metric values, creative sync source-health diagnostics, and indexes for scheduled health/insights jobs.
* Storefront media buys and updates that a buyer submits with a `push_notification_config` now fire the buyer's AdCP task webhook when the inventory source resolves acceptance asynchronously — on final acceptance, terminal rejection, and the pending-acceptance timeout. Previously only the operator-approval path emitted these webhooks, so a buyer that relied on push delivery (rather than polling `tasks_get`) was never told the outcome of an asynchronously-settled buy or update despite our "await your webhook" promise.
* `update_campaign` now reports which campaign creatives were dropped from each media buy during auto-link. When a campaign creative's duration or slot doesn't satisfy a buy's product format, the cascade drops it (and proceeds with the compatible ones) — previously that drop was silent. The response now includes a `droppedCreatives` array (`{ mediaBuyId, dropped: [{ creativeId, reason }] }`) so the buyer can see exactly what wasn't applied and fix or resubmit those creatives.

## 3.0.0 — June 27, 2026 at 7:16 AM UTC

* Fix Murph stalling when creating products or signals on an embedded ad-server source. It now validates, previews, and proceeds to call create — the in-chat Approve control is the confirmation step — instead of repeatedly validating and never creating. The ad-server source widget's draft buttons drive to creation rather than asking to confirm beforehand.
* Prevent duplicate managed FreeWheel ESA connections from bypassing the duplicate check when authenticated with a client ID.
* Remove the managed ad-server source `provisioningStatus` field. The `pending → provisioning → active → failed → deactivated` lifecycle was a stored state machine that nothing reliably advanced (sources stranded in `provisioning` indefinitely) and that misrepresented usability. A source's enabled/disabled state is now conveyed solely by `deactivatedAt` (null = enabled), and whether it is live/sellable is derived from upstream facts via the managed-source status (`operational.isLive`). The `provisioningStatus` field is gone from the ad-server connection and managed-sales-agent responses under `/api/v2/storefront/inventory-sources`.
* The managed-sales-agent summary now also exposes `lastErrorCode` — the machine-readable classification of the most recent provisioning failure (same vocabulary as `EsaConnection.lastErrorCode`), or null when there has been no failure.

## 2.201.0 — June 27, 2026 at 6:49 AM UTC

* Auto-linking campaign creatives to existing media buys no longer fails all-or-nothing when one campaign creative doesn't fit a buy. The auto-sync now drops creatives whose duration or slot doesn't satisfy the buy's product format and proceeds with the compatible ones (it already dropped format-mismatched creatives this way) — so a single incompatible campaign creative can't block every other creative from syncing to that buy. Dropped creatives are logged for the operator.
* Media buys now validate the full set of attached creatives against each product's format requirements (duration, dimensions, slot types) on both create and update. Previously a creative could skip the duration/slot check depending on how it was attached — a campaign creative auto-linked into a new media buy on create, or a creative attached per-package via `packages[].creative_ids` on update — so a creative whose duration didn't fit a product's slot (for example a 15s creative on a 30s-only slot) could slip through to a downstream ad-server rejection instead of being flagged up front. Both paths now run the same gate that top-level creative assignments already did.
* Agent discovery now surfaces a publisher's self-published creative formats. When a publisher's `adagents.json` resolves, the discover-agents response includes `publisher.formats` (the AdCP 3.1 `formats[]` inventory-identity catalog), read directly through the publisher's own canonical document — never assembled or stored by the platform. Absent when only the registry mirror resolves; an empty array for a pre-3.1 file that declares no formats.
* Buyer product discovery now forwards quick/long wait windows through storefront chains and returns structured timeout and upstream incomplete signals so agents can ask before retrying slow storefronts with a longer wait.
* `create_esa_product` and `update_esa_product` now accept `dryRun: true` to check a draft and return validation + preview without persisting — one dry-run step instead of separate validate/preview calls. `validate_esa_product` / `preview_esa_product` remain as deprecated aliases.
* Agent discovery now resolves a publisher through a single resolver that reports provenance. The discover-agents response carries the registry's `hosting` verdict and a `freshness` block indicating whether the authorization verdict came from the registry's crawl (`source: "registry"`) or the publisher's live `adagents.json` (`source: "live_origin"`), along with the registry's last-crawl time. When the registry's crawl lags a publisher's live file, the platform now asks the registry to re-crawl so its mirror converges, instead of silently overriding the stale verdict.
* Validating or previewing a wholesale product now surfaces an advisory warning when the product declares no publisher properties (it hasn't said which publisher inventory it covers). This is a **warning only** — it never blocks authoring; declaring publisher properties is recommended, not required. It complements the existing publisher-authorization advisory.
* Validating or previewing a wholesale product now surfaces an advisory warning when a declared publisher's live `adagents.json` hasn't authorized the storefront's sales agent. This is a **warning only** — it never blocks authoring (publisher authorization isn't required at this distribution stage), and it reads the publisher's *live* `adagents.json` (not the lagging registry mirror) so a not-yet-crawled publisher isn't falsely flagged.

## 2.200.0 — June 26, 2026 at 9:43 PM UTC

* Clarify the AAO check when connecting an inventory source. The connect-time gate verifies the **agent's** own AAO registration; its messaging now says so explicitly and distinguishes it from a **publisher's** authorization (`adagents.json`) to sell inventory, which is enforced later when traffic is served. The "agent not registered" rejection (`400`) is also clearly separated from a "registry temporarily unreachable" outcome (`503`, retryable), and both are documented on the create-inventory-source reference.
* Learn each GAM inventory source's approve-capability from real order outcomes and use it to stop stranded buys. When a create is structurally blocked at the ad server's approval step (the service account lacks Approve + Overbook, or the network mandates manual approval), the source is marked blocked: the storefront then refuses to enable auto media-buy approval — telling the operator to grant Approve + Overbook in Google Ad Manager — instead of accepting an auto setting it can't honor, and surfaces a readiness remediation. It recovers automatically once a subsequent order is created without an approval block, after the permission is granted. Detection is lazy — there is no synthetic probe order; the first real order is the probe. (This covers the approval axis — Approve/Overbook permission and mandatory-approval networks — not forecast or inventory availability.)
* When a managed inventory source rejects a creative or media-buy request as invalid, the buyer now sees the source's actual reason (for example, "creative needs a 4:3 640×480 rendition") instead of a generic "rejected as invalid" message — so the problem is actionable. The storefront operator owns the managed sales agent, so its validation rejection is the seller speaking to the buyer and is passed through. Authorization and transport failures stay generic (they are credential/plumbing problems, not a seller message), and rejections from cross-storefront linked sources remain redacted. Validation rejections are now identified by structured signals only (never a free-text message match), so a transport error can never be mistaken for a validation rejection.
* Murph now gathers a required creative format up front (via `list_esa_creative_formats`) before validating an embedded sales-agent product, so sellers no longer hit an avoidable "missing creative formats" round-trip when authoring a product.

## 2.199.0 — June 26, 2026 at 8:51 PM UTC

* Storefront inventory-source compliance is now actionable instead of inscrutable: it surfaces AAO's advisory observations (the `observations` array was previously always empty), labels skipped/not-run compliance tracks clearly ("not run" / "no coverage") instead of showing a blank track at 0 ms, and adds an explicit advisory when a registered agent has no scored compliance tracks yet (coverage-gap skips or a pending run). Compliance remains informational and never blocks going live.
* AAO inventory-source compliance is now informational at go-live: a non-`passing` compliance verdict no longer blocks a storefront from going live and transacting. The verdict is still surfaced prominently as an advisory warning (in storefront readiness and Murph's health snapshot) so you can see and address it. Connect-time registration and the agent-active readiness check are unchanged, and per-publisher authorization remains enforced.
* Discover-agents now explains a null AAO `member` instead of collapsing every cause into the same null. Each of `operator` and `publisher` carries a `lookup_status`: `member`, `not_member`, `scope_limited` (looked up without your AAO key, so members-only records may be hidden), or `lookup_failed` (the registry was unreachable — retry with `refresh`). Publisher lookups have no visibility tiers, so a null publisher member is always definitive. Transient lookup failures are no longer cached, so a refresh reflects a recovered registry immediately.
* Add AdCP integration docs, split by perspective: "Connect your sales agent" (seller/storefront side — how Interchange uses AdCP to integrate your agent as a storefront source, AAO compliance, and a governance/audit FAQ) and "How Interchange uses AdCP (buy side)" (cross-seller discovery and campaigns). Each pairs Interchange behavior with the AdCP spec.
* Buyer campaign targeting can now list targeting dimension dictionaries, resolve localized or messy Nielsen DMA labels such as "LA DMA" and "Dallas/Ft. Worth" to code candidates, and request geo metro display labels on campaign reads with `fields=geo_metro_names`.
* Creative attachment now checks a creative's duration against the format slot's required `duration_ms` range before a media buy is created or updated. A creative whose duration falls outside the slot's range — for example a 15s video on a 30s-only slot — is rejected up front with a clear reason, instead of being synced and then hard-rejected by the publisher's ad server. Linked creative assets accept an optional `duration_ms` so a VAST tag's duration can be declared, and uploaded video duration is measured automatically. Creatives whose duration is unknown are not blocked.
* Creative recognition now probes video and audio specs at upload, not just image dimensions. When a buyer brings a video or audio creative, the upload reads its intrinsic specs and surfaces them in the recognition card alongside the file:
* **Video:** dimensions, duration, codec, frame rate, overall bitrate, and container (MP4/MOV).
* **Audio:** duration, codec, sample rate, and bitrate (MP3, AAC/M4A, WAV).
* Detected specs are persisted on the asset and returned on the creative manifest (`duration_ms`, `codec`, `bitrate_kbps`, `frame_rate`, `sample_rate`, `container`), so they're available to the buyer and to placement auto-mapping without re-reading the file. Probing is best-effort: an unreadable or unsupported file still uploads, just without the extra specs. Dimensions continue to be confirmed against the filename, with disagreements flagged.
* Audio and QuickTime creatives now upload cleanly across both surfaces that feed recognition — the in-chat dropzone and the campaign creative-assets page. The chat dropzone accepts MP3, WAV, M4A, and `.mov` alongside MP4 (previously only MP4), and the creative upload endpoint now accepts `.m4a` and the common `.wav`/`.mp3` MIME variants (e.g. `audio/x-wav`, `audio/x-m4a`) that some browsers send, normalizing them to a canonical type so they classify and probe correctly instead of being rejected as an unsupported file type.
* Reduce database timeout exposure on the agentic database: replace the per-row LATERAL JOIN in storefront diagnostics with a set-based CTE, eliminate a duplicate COUNT(\*) query in agent activity listing, add expression indexes on murph\_test\_runs task\_id paths, and raise the agentic DB connection pool ceiling in production.
* The diagnostics `window` object now includes `activityTruncated: boolean`. When `true`, the 200-row sample cap was reached and `recentActivity[]` shows only the most recent 200 rows — performance rates and counts are derived from that sample, not the full window.
* Package-level budget updates for media buys backed by ESA storefronts are now correctly forwarded to the upstream source.
* Fix auth failure that blocked cancel (and silent false-ACTIVE on execute) for managed-storefront sales agents. The cancel path now routes in-process for platform-internal storefronts instead of calling their public OAuth-gated URL. Execute no longer marks a campaign ACTIVE when no upstream media\_buy\_id was returned.
* Fixed an intermittent "MCP app failed to initialize" error that could leave in-chat widgets blank. The widget-to-host handshake now arms when the widget frame mounts instead of waiting for its load event, so a large widget bundle can no longer send its initialization before the host is listening.
* Fix Murph chat attachments getting stuck on a loading spinner and never attaching. A drop cancel-guard was set when the chat unmounted but never re-armed on remount, so after a remount (or React StrictMode in dev) every dropped file silently skipped the attach step and spun forever.
* Fix source-webhook callback URL using wrong customer ID for storefront-routed buys. Async accepts (e.g. Ozone manual moderation) now route to the buyer's customer context instead of the storefront's.
* Murph now grounds answers in the AdCP protocol spec alongside the Interchange docs. The docs index is built from both corpora (the AdCP spec is fetched fresh at build time so it tracks the latest), search results are tagged by source and balanced so the larger AdCP corpus can't crowd out our own docs, and Murph cites the AdCP docs for protocol questions and the Interchange docs for platform behavior.
* The Murph chat composer now surfaces each attaching file as a chip with a spinner in its leading slot while the file is read and encoded, so attaching large files no longer feels unresponsive. Sending is held until encoding finishes so a file can't be dropped from the turn. The attach-file button is now a plus icon.
* Raise the per-turn chat attachment limit from 4 to 5 files. The 50 MB total-size cap per turn is unchanged.

## 2.198.0 — June 26, 2026 at 2:29 PM UTC

* Bound synchronous buyer product discovery so slow sales agents degrade instead of holding REST discovery responses open past client and deploy-gate timeouts.
* Product discovery now defaults to a 30-second quick wait, exposes opt-in longer waits, and reports storefront response timing so buyers can debug slow or timed-out storefront calls.
* Murph is now added automatically to newly provisioned Slack support channels and those channels are connected to the right customer account. A scheduled customer setup invariant reconciler also keeps existing Slack support channels repaired if Murph membership or the customer binding drifts.
* Make ESA product authoring resilient to stale creative-format catalogs and partial data. A single malformed or partially-authored wholesale product no longer blanks the entire seller product list — valid products are still returned and the bad row is logged. Product validation downgrades a "creative format not found" error to a warning when the format is present in the source's live creative-format catalog (so a stale validator snapshot no longer blocks authoring a format that is actually available), tolerates variation in the validator's message phrasing, and logs clearly when it cannot. When saving a product (create or update) is rejected because a creative format is missing from the source's discovered catalog, the seller now gets an actionable message — distinguishing a stale discovered catalog that needs refreshing (the format is available in the source's live catalog) from a format the source genuinely doesn't support — instead of a raw upstream error.
* Fixed storefront async budget-update rail: a source-rejected update no longer leaves a wrong budget live, and the seller spread ledger is now re-booked when an async update confirms. On a multi-source buy, a budget version is no longer promoted live when any leg was rejected, and a failed activation no longer reports the update as succeeded.
* Buyer product discovery now applies the quick/long wait deadline to the full per-storefront agent task, including account sync and in-process storefront dispatch, so wholesale discovery cannot hang beyond the requested wait.
* Legacy non-storefront product discovery has been removed. The `product_discover` and `media_product_list` tools on the legacy `/tools` endpoint no longer return products from standalone sales agents. Product discovery now runs exclusively through storefront-backed discovery (`POST /api/v2/discovery/discover-products`), which surfaces each storefront once rather than returning both a storefront and its underlying direct agent. Buyers still integrating against the legacy `/tools` discovery tools should move to the storefront discovery surface.

## 2.197.0 — June 26, 2026 at 11:08 AM UTC

* Add the `browse_ad_server_selectors` storefront MCP tool. It opens the in-chat inventory browser over an embedded sales agent's ad-server inventory: call with an `esaId` to list the adapter's available selector types, or add a `selectorType` to browse selectors of that type (narrowed by `query`/`parentId`, paginated with `cursor`). As a standard MCP Apps tool — it declares its widget binding and returns the inventory as `structuredContent` — any MCP host renders the inventory-selector surface from the tool result, not just the in-app guide.
* `ask_murph` now surfaces a turn's primary widget as a conformant MCP-UI tool result — an embedded `ui://` resource plus the widget's render data on `structuredContent` — so any MCP-UI host (Claude, ChatGPT) renders the widget from the result, not just the in-product drawer. Previously only the seller `open_<widget>` directive was surfaced as a resource; discovery, creative, inventory, analytics, and escalations widgets were invisible to external hosts. One primary widget is chosen per turn (an MCP-UI result carries one render payload); the in-product experience is unchanged.
* Paced campaigns now correctly split into per-period packages on first execute. A regression caused the first execute of a campaign with pacing periods to ship a single flat package instead of one package per period, so the configured weekly schedule was silently ignored. Executing a paced campaign now produces the expected per-period packages.
* Clarify campaign creation guidance so buyers leave `campaignType` unset by default and let the first media buy lock the campaign type.
* Expose sanitized ADCP transport request and response diagnostics for source debug calls.

## 2.196.1 — June 26, 2026 at 9:40 AM UTC

* Fix Murph storefront diagnostics so seller-scoped MCP sessions can access their sales-agent debug calls after customer switching, and allow source diagnostics to be filtered by either source slug or source row id.

## 2.196.0 — June 25, 2026 at 7:13 PM UTC

* Buyer creative v2: buyers can bring creative into chat and get it onto a campaign, whether or not they name the campaign up front.
* **Drop a zip bundle** of creatives and it unpacks into one creative per file, each titled from its filename and auto-mapped to a placement by size (images today). Unsupported files, SVG (active content), manifest/CSV sidecars, and macOS junk are skipped.
* **Upload then pick later:** uploads are saved as advertiser-level creatives up front (building on the advertiser creative library), so picking a campaign in a later turn — via the picker, a typo'd name, or "a campaign" left vague — still attaches and maps them. No more lost upload or picker loop.
* **Name the campaign with the upload** and it attaches directly, skipping the picker.
* Flagged behind `buyer-creative-v2`, off by default.
* Fix 500 error on storefront source webhooks caused by referencing a non-existent `customer_id` column on `storefront_inventory_source` — the column belongs to `storefront_agent_source`.
* Fixed inbound ADCP source webhooks returning 500 INTERNAL\_ERROR for every callback. The source resolver scoped the customer filter on the wrong table (the inventory source, which is storefront-scoped and has no customer column) instead of the agent source that actually carries it. As a result, create\_media\_buy activation callbacks and media\_buy\_delivery reports from third-party sources were rejected and not ingested; they now resolve and process correctly.
* Fix a media-buy activation edge case: an approved budget-change update could activate a brand-new buy that was still awaiting its initial source acceptance, flipping it live outside the normal create path. Storefront version activation now only promotes a budget change that is staged on top of an already-live version, leaving an unaccepted new buy untouched.
* Fix catalog warm crash when a seller returns the same product\_id on multiple pages. The error appeared in Sentry as a duplicate key violation on `storefront_catalog_wholesale_products_pkey`. Duplicate products are now skipped with a warning log so the rest of the catalog persists correctly.

## 2.195.1 — June 25, 2026 at 3:57 PM UTC

* `update_esa_product` now surfaces the salesagent's validation detail when a product update is rejected with a 400. Previously Murph received a generic "salesagent PUT ... returned 400" with no indication of which field failed or why. The salesagent returns a `{valid: false, issues: [{field, message}]}` body on these rejections (e.g. `format_missing_duration` for video\_standard on GAM requiring duration\_ms); the error parser now reads `issues[]` in addition to `errors[]` so the full field-level message reaches the operator.
* Fixed a bug where the Notifications Settings modal could not be reopened after being closed. Closing the modal now clears the `settingsSection` query parameter so subsequent clicks correctly reopen it.

## 2.195.0 — June 25, 2026 at 2:32 PM UTC

* Video creative assets now carry a bitrate. The server estimates a hosted video's bitrate from its file size and duration and forwards it on the creative manifest as `video_bitrate_kbps` (kilobits per second), so sales agents that require a bitrate on video asset metadata (e.g. Google Ad Manager) can traffic the creative. The video and audio asset bitrate fields are now `video_bitrate_kbps` / `audio_bitrate_kbps` (integer kbps), aligning with the canonical AdCP naming.
* Fix creative sync sending raw landing page URL instead of Scope3-wrapped click tracker URL to sellers.
* Fix campaigns to embedded storefronts silently reporting success when the inventory source rejects the forwarded buy on authentication. A forwarded media buy that the source refuses on auth — an `auth-required` status, an HTTP 401/403, or a failed task naming an identity/permission problem — now fails with a clear `not_authorized` error instead of being reported as accepted. Buyers are no longer told a campaign is live when it never reached the storefront.
* Creatives assigned to a campaign via the advertiser-library join table now appear correctly on the campaign card and count toward format coverage.
* Campaign type (DECISIONED vs ROUTED) no longer has to be chosen up front. `campaignType` is now optional on campaign creation: leave it unset and the campaign is created untyped, then locks to the type of its first media buy — a buy through an adapter storefront locks it to ROUTED, every other buy to DECISIONED. Once set, the type is immutable and later media buys of the other type are rejected, so a single campaign still can't mix the two. Set `campaignType` explicitly only when you want ROUTED on a non-adapter agent before adding any media buy.
* Fix execute gate using stale product-level budget instead of package budgets. When a storefront accepts a media buy and creates sub-packages with different amounts than originally requested, the execute reconcile check now reads the same packages-aware allocation as the buyer-visible remaining budget, so available budget shown to buyers matches what execute will honor.
* Fix existing-user signup so an invitation join lands on the invited org. When an existing user (typically an OAuth/SSO re-signup) accepts an invitation to an org we cannot resolve by id, domain, or tenant, provisioning now resolves the invited org from the invitation and grants the invited role there — instead of falling back to the user's oldest membership and reporting them against the wrong org. The oldest-membership fallback is reserved for genuinely idempotent calls with no invitation.
* Source diagnostics now include partner-safe debug IDs, bounded time-window lookup, and copyable redacted request details for recent sales-agent failures and timeouts.
* `update_media_buy` on a storefront now resolves edits a source accepts asynchronously (e.g. parked for manual moderation) instead of reporting a false failure. When a source takes the update out-of-band, the storefront returns a spec-compliant `submitted` task envelope with a `task_id` to poll (or await via webhook); the edit is applied to the buy once the source finishes accepting, and the task resolves to `completed` (or `failed` if the source rejects it). Previously such an update returned `SERVICE_UNAVAILABLE` even though the source had accepted it.
* Fix media-buy budget changes not persisting and SCD2 versions losing child-row history.
* Reducing a package/product budget on a live media buy is now recorded locally as the buyer's intent (it no longer depends on the sales agent echoing the change back, which adapter/GAM/3rd-party AdCP paths don't do). The change is staged on a new PENDING\_APPROVAL version that owns its own duplicated `packages` and `media_buy_products` carrying the new budget, while the still-ACTIVE version keeps running its current budget until approval. On activation the version markers flip without deleting or moving child rows, so the superseded version keeps its history. A migration scopes `packages` uniqueness to `(media_buy_id, package_id)` so each version can own its package copy. Reads that aggregate budgets across a media buy are scoped to a single live version to avoid double-counting during the approval window, and the campaign ledger commitment is recomputed/posted when an approved budget change goes live.

## 2.194.0 — June 25, 2026 at 12:52 AM UTC

* Agent widgets in the Murph chat no longer repeat as you work — only the most recent widget stays open, at the latest turn, instead of stacking a new copy each time it's surfaced. Reopening a conversation now restores a single live widget rather than one per past turn.
* Fix AAO compliance reader URL normalization: strip /mcp and /a2a transport path suffixes before registry lookup so storefront compliance checks correctly find agents registered under their bare root URL.
* Fix Murph in-chat widgets (product discovery, creative, inventory, and seller surfaces) rendering as a black box when the operating system is set to dark mode. The widget canvas is now pinned to the host's theme so content is always visible.
* Murph can now check a domain's `adagents.json` directly and resolves managed/network publishers via the ads.txt `managerdomain` fallback, so domains that host no file of their own (e.g. Raptive/CafeMedia-managed publishers delegating to `cafemedia.com`) no longer read as "no adagents.json". The `discover-agents` response now also reports how the file was resolved (`discovery_method`, `manager_domain`, `resolved_url`).
* Fixed signup notifications so the admins of the organization you join are notified of your signup, even when you accept several invitations at once. Previously the notification could target the wrong organization and report that no admins were found.
* Media buy products in `get_campaign` now include a `formatOptions` field with the publisher's declared creative format requirements. For video products this shows required duration, dimensions, and aspect ratio: use it to tell buyers what creative spec to provide before executing.
* Creative format references are now reconciled to the product's advertised format when a media buy is created. When a creative's stored format `agent_url` does not match the `agent_url` the matched product advertises for the same format `id` (for example a bare host on the creative versus an authoritative path on the product), the buy now uses the product's `agent_url` for the format-spec lookup and for the format reference sent to the sales agent. This prevents a mismatched creative `agent_url` from breaking the buy with a validation error. Formats a product does not advertise are left unchanged, so direct (non-storefront) buys are unaffected.
* Deselecting a product in discovery now removes it from a bound DRAFT media buy and frees its budget. Previously a removed product lingered on the DRAFT (still carrying its budget) and was forwarded to the sales agent on execute, so a buyer who dropped a product could still see it submitted to the source. Reconcile now drops the deselected product from the DRAFT before execution, keyed on the durable selection identity, and only ever touches DRAFT (non-executed) buys.
* Murph chat now redraws in-chat widgets and attachment references when a conversation is reopened or refreshed. Product-discovery and creative-iteration widgets persist their data so they reappear on reload (previously only a text recap showed), and files you attached are surfaced as reference chips showing what was sent (the file contents themselves are still not retained).
* Use the storefront media buy id for the utm\_media\_buy attribution parameter on synced creative clickthrough URLs, so clicks map to the correct buy for storefront-routed media buys.

## 2.193.1 — June 24, 2026 at 5:46 PM UTC

* Apply campaign UTM attribution to creative clickthrough URLs on media buy execution, not only on media buy update, so initial sync to sellers carries the buy and creative identifiers for attribution.

## 2.193.0 — June 24, 2026 at 5:25 PM UTC

* Creative clickthrough URLs synced to sales agents now carry the campaign's UTM attribution parameters (source, medium, campaign, content, media buy), so per-media-buy and per-creative click attribution works end to end.
* Product discovery no longer drops a sales agent's entire catalog when the account-billing handshake (`sync_accounts`) times out or fails. Discovery now falls back to the natural-key account and still fetches products, so a slow or flaky third-party handshake can't zero out an otherwise-healthy source. Sources that genuinely require a synced account still surface their error to operators.
* Fixed an issue where accepting an invitation during signup could create a duplicate organization instead of joining the organization you were invited to.
* Media-buy attribution now reaches sellers on creative sync: impression and click tracker URLs (and the embedded HTML pixel) carry the resolved media buy id instead of an unresolved macro.
* Murph now surfaces the interactive product-discovery widget in chat when you discover products. Discovered products render as the same selectable card surface used by external MCP hosts — browse, view details, and select products directly in the conversation — and the widget appears above Murph's reply. Instead of repeating the full product list in text, Murph gives a short orientation (totals, price range, recommended plans) and steers you to next steps.

## 2.192.0 — June 24, 2026 at 3:09 PM UTC

* Text slot validation now fails with a clear error when format spec is unavailable, instead of silently skipping per-slot length limits.
* `create_media_buy` and `update_media_buy` now return `ext.source_references` — the upstream media buy id (and, for pass-through agents, the source name) that your buy maps to on each inventory source, so you can reconcile against the system that actually serves it. Disclosure is gated: pass-through agents include the source name, the storefront's own managed agent returns the upstream id under a neutral label, and curated or in-process sources are omitted. The per-source breakdown on these responses now masks the underlying source identity for non-pass-through sources.
* Two ways to manage ad-server products faster. In the ad-server view you can now edit a product's name and description or delete it inline, without going through a full chat cycle. And for bulk work, drop a product spreadsheet (CSV/XLSX) straight into the chat — the agent reads the rows, validates them, and creates the whole set in one batch, then tells you which landed and which need attention.
* Fixed campaign start\_date set to today failing at execution. When a media buy's start time is today's midnight, the platform now treats it as "start immediately" (asap) rather than stamping the execution clock as the start time, which ADCP would reject as a past timestamp.
* Fixed duplicate media buys when re-running discovery or execute on a campaign. Composed products are now reconciled by a durable selection identity that stays stable across the targeting variations that previously made the same inventory look like a brand-new product, so re-binding or re-executing a campaign no longer spawns duplicate media buys for the same selection.
* Fixed ESA product validation incorrectly blocking products when a creative format exists in the live catalog but not in the validator's discovered catalog. The validator's discovered catalog can become stale after new formats are added to the creative agent. When this mismatch is detected, the `creative_format_not_found` validation issue is now downgraded from an error to a warning so product authoring can proceed.
* Fixed streamed Murph chat requests preserving selected workspace context, and let watched Slack channel requests reach Murph with supported Slack file attachments.
* Fixed the storefront navigation rail cutting off its menu and reserving empty space for recent chats. The menu now sizes to its content and the recent chats list fills the remaining space, with "New chat" set off from the section navigation by a divider.
* Fixed update\_media\_buy failing schema validation for sources that require an account field.
* Updated FreeWheel ad-server setup to collect and forward partner-program client ID and client secret credentials.
* Fixed a self-built sales-agent source being falsely reported as "unreachable" and unable to activate. The connectivity probe and capability refresh now reach a PENDING agent's endpoint to verify it, instead of short-circuiting before the request — so a healthy agent reflects its real connection status and can move to active.
* `url_type` is now required when supplying a `url_asset` on the create or update creative manifest endpoints. Previously the field was optional; clients must now explicitly declare the URL classification (clickthrough, tracker\_pixel, tracker\_script, or vast).

## 2.191.0 — June 24, 2026 at 12:32 AM UTC

* Clearer error when a campaign end date cannot be shortened. The API now lists every media buy that ends after the requested date and explains that active buys have to be shortened first, instead of a generic "update or complete the media buy" message that left buyers unsure what to do.
* Fixed an issue where a campaign's media buys could show no packages while a pending change was awaiting approval. The campaign endpoint now reports the current packages, products, and budget on each media buy, while still surfacing the pending status on the campaign's media-buy summary so reviewers can see a change is in flight.

## 2.190.0 — June 23, 2026 at 6:09 PM UTC

* Bulk creative updates can now set `format_id` and `target_format_ids`, not just `click_url`. This lets you retype many creatives to a sales agent's required format (for example OpenAds `display_300x250_nongenerative`) in a single call, matched by size, instead of editing each creative one at a time.
* Campaign execution now returns a clear, actionable error naming the affected product when a selected product cannot be funded within the campaign's remaining media budget, instead of failing later with an internal database error. Raise the campaign budget or reduce other media buys, then re-run execute.

## 2.189.1 — June 23, 2026 at 4:46 PM UTC

* Fixed available account discovery for adapter storefronts after connecting buyer-managed provider accounts.
* Fixed creative approval and assignment handling across the campaign → media buy → storefront flow:
* Creative approval status syncing back from sales agents: operator approvals (delivered as an "updated/approved" review verdict) were being recorded as still-pending and triggering spurious "changes requested" notifications; the per-agent approval status was also written in a different case than the readers expected, so approved creatives could read back as unregistered. Creative status is now derived across every sales agent a creative is synced to, so a creative one routed seller rejected can no longer appear approved.
* Attaching creatives to an active media buy no longer leaves its per-package creative assignments stale (they were silently not updated once a buy went live), so get/list responses now reflect the attached creatives.
* A creative-only change to a routed buy no longer forces an unnecessary seller re-approval.
* Murph now returns a user-friendly "temporarily unavailable" message when the Anthropic API is overloaded (HTTP 529) or encounters a temporary server error (HTTP 500), instead of propagating an unhandled exception.
* Fixed a 500 error when executing or re-syncing a campaign whose draft media buy already exists and the campaign has optimization goals set. The goals are now stored correctly instead of failing with a database serialization error.
* Normalized creative format identifiers during seller sync when a product declares a base format that covers sized variants.

## 2.189.0 — June 23, 2026 at 2:18 PM UTC

* Creating products on an ad-server inventory source from chat now works reliably, and you can create several at once. Ask the agent to build a batch of products (for example from a spreadsheet) and approve the whole set in a single confirmation. Creation continues even if one product fails. You get a clear summary of which products were created and which failed, with the reason, so you can retry just the ones that didn't land.
* You can now update several ad-server products at once from chat. Ask the agent to change a batch of products and approve the whole set in a single confirmation. Updates continue even if one fails. You get a clear summary of which products changed and which failed, with the reason, so you can retry just the ones that didn't update.
* Fixed video creatives failing to upload to the ad server ("failed to upload creative") when a video file was supplied for a VAST slot. The video was forwarded labeled as a VAST tag pointing at a raw MP4, which the ad server's VAST parser rejected. The video is now correctly sent as a video asset on every upload path — including syncing creatives directly and creating a media buy — not only the format-adapted path.

## 2.188.0 — June 23, 2026 at 1:49 PM UTC

* Murph no longer writes the auto-vs-manual approval mode into the acceptance-policy document. The acceptance policy now covers content rules (which advertisers/creatives are accepted and what needs review); whether creatives and media buys auto-approve is the separate approval setting. This stops the acceptance-policy page from showing a stale "manual review" posture after the approval setting is changed.
* Fixed deleting a media buy leaving the ad-server order live. When a buyer deletes an executed media buy, the platform now cancels it at the sales agent / ad server first (archiving the upstream order, e.g. a GAM order) before archiving locally, instead of stranding an orphaned order.
* Fixed video media buys being rejected by the ad server. When a media buy was forwarded with a video creative, the video asset was sent without its name and pixel dimensions, so the sales agent rejected the buy. The forwarded video asset now carries its name, width, height, and (when available) duration.
* Storefronts can now be paid in more than one currency. A new `paymentCurrencies` setting lists the ISO-4217 currencies a storefront will be paid in (the primary `defaultCurrency` is always included). There is no FX — the currency a buyer pays in is exactly the currency the seller is paid in — so a storefront cannot sell a pricing option in a currency outside this set. Product discovery returns products in the buyer's advertiser currency; if the storefront isn't paid in that currency it returns no products (rather than ones the buyer could never buy). A media buy is accepted only when denominated in a single one of the storefront's payment currencies. A storefront that sets no `paymentCurrencies` keeps its previous single-currency behavior, falling back to its `defaultCurrency`.
* Murph now shows Approve / Cancel buttons in Slack when an action needs confirmation. Previously a Slack user had to reply with a long confirmation phrase to approve a gated change; now a tap approves it. Only the person who requested the change can approve it.
* Storefront readiness now surfaces the real per-track AAO compliance results (e.g. core, products, audiences) with their pass / fail / partial status and scenario tallies, instead of collapsing every agent to a single track that could report "0 tracks executed".

## 2.187.0 — June 23, 2026 at 1:12 PM UTC

* Video media buys now carry the product's exact required duration to the seller. When a product declares a canonical video format with a required duration, the package sent to the sales agent includes that duration (`duration_ms_exact` / `duration_ms_range`) alongside the existing format selection, so duration-sensitive video inventory traffics correctly instead of dropping the requirement.
* Product discovery now documents and types the accepted video delivery containers and codecs a seller will accept. For hosted-video formats, `formatOptions[].params.containers`, `params.video_codecs`, and `params.audio_codecs` advertise the allowed values (for example, MP4 with H.264/AAC), so a buyer's agent can avoid sending a creative that would be rejected downstream. VAST formats intentionally omit these — the codec is carried inside the VAST document. The legacy `formats` reference array is also now documented on the product response.
* Fixed approval queue action buttons so approving one media-buy approval does not show a busy state on unrelated approvals, and approval decisions now return immediately while source forwarding continues in the background.

## 2.186.0 — June 23, 2026 at 10:36 AM UTC

* Hosted video creatives now carry their duration. The duration is extracted from the video file (including non-faststart MP4s, via a tail read) when a creative is published and when it is adapted to a publisher format, so downstream duration limits — such as a sales agent's maximum video length — can be checked. A missing duration is non-fatal: the creative still syncs, and only width/height remain required.
* Fixed a crash in the buyer catalogs view that prevented catalog details from rendering when an item count was shown.
* Fixed hosted video creatives failing to sync when they fill a VAST format slot. A hosted video used for a VAST slot is now sent as a video asset carrying its width and height, instead of being relabeled as a VAST tag pointing at the raw video file — which sales agents rejected as invalid (and which dropped the video's dimensions).

## 2.185.0 — June 23, 2026 at 6:03 AM UTC

* Your business profile now reads as structured cards — the pitch buyers see, plus your channels, regions, verticals, and authorized domains as legible tagged groups — instead of a flat gray list, and "Update profile" is a clear primary action.
* Fixed approved creatives not delivering on approval-gated storefronts. When a seller approved a creative, it was created on the ad server but never associated with the line item, so it could not serve. The storefront approval now forwards the creative's package assignment to the source, so the ad server creates the line-item creative association.
* Added a manual refresh control to the seller Approvals view, clarified pending media-buy review copy, and surfaced prior approval decisions with reviewer notes in the media-buy detail pane.
* Third-party storefronts can now leave Interchange merchandising tools off without being blocked by storefront-managed approval setup, and sellers can opt those tools back in from the Sales agent widget or Storefront settings.

## 2.184.3 — June 22, 2026 at 10:55 PM UTC

* Fixed an issue where `sync_creatives` calls could fail with `IDEMPOTENCY_CONFLICT` when the set of package assignments changed between calls. The upstream idempotency key now includes a content fingerprint covering the creative and assignment payload, so different payloads always produce a distinct key even when the caller reuses its own base key.

## 2.184.2 — June 22, 2026 at 9:48 PM UTC

* Fixed a crash when updating a storefront's publisher domain and operator domain in the same request.

## 2.184.1 — June 22, 2026 at 9:05 PM UTC

* Fixed creatives being synced to a seller without the media buy id or package assignments for media buys placed through a storefront. The storefront sync dispatch forwarded only the creatives and account, so the storefront fanned them out to every connected source unattached to a buy or package. The media buy id and per-package assignments are now forwarded through the dispatch, so creatives route to the buy's source(s) and attach to their packages on the seller.

## 2.184.0 — June 22, 2026 at 8:11 PM UTC

* Signing up with an email domain that already has an account but no owner now lets the first verified user from that domain claim the account and become its owner. Previously, only brand-new domains could create an account: if an account already existed for the domain but had no owner, the first user was blocked and routed to request access (which no one could approve). Accounts that already have an owner are unaffected.
* Fixed creatives being synced to a seller without their package assignments for media buys placed through a storefront. The assignment step resolved formats from the wrong product record and produced no assignments, so creatives reached the seller unattached to any package. It now resolves each package's own product formats and routed sales agent, so creatives are assigned to their packages on the seller for storefront-routed buys.

## 2.183.0 — June 22, 2026 at 8:02 PM UTC

* Fixed delivered spend (and other delivery metrics) being lost when a media buy is edited or re-synced. Delivery metrics are now carried forward to each new version of a media buy, and a one-time backfill restores metrics on existing media buys, so reported spend stays accurate after updates.
* Fixed client-side validation in the credentials form to allow Basic Auth with an empty password.

## 2.182.1 — June 22, 2026 at 6:16 PM UTC

* Fixed standalone creatives (submitted to a storefront without a media buy and held for manual operator review) failing to reach the underlying seller on approval. The forwarded sync\_creatives request was missing an account, so it was rejected before delivery. The buyer's account is now preserved on the review record and reused when the approved creative is forwarded.

## 2.182.0 — June 22, 2026 at 5:33 PM UTC

* Inventory sources that use basic auth or an API key can now be registered without supplying the secret up front. The source is created pending credentials, and the credential is collected afterwards through the secure in-chat form rather than being typed into the conversation. OAuth and no-auth sources are unchanged.
* Fixed two bugs in the storefront creative approval evaluator: the evaluator was incorrectly using the seller's own brand ID as the expected brand when validating buyer-submitted creatives, and a brand metadata mismatch was treated as a hard block that prevented approval entirely. Brand mismatches now escalate to manual review instead of blocking.
* Fixed creative approval getting stuck in pending when ad-server forwarding fails. Operators can now approve a creative even when the source forward encounters a transient error — the approval decision is recorded immediately, and forwarding is retried separately.
* External sales-agent sources now accept Basic Auth credentials with an empty password.
* Murph now says "Scope3 has been notified" when it files a report and tells users they can track status under the ? menu. The offer to notify Scope3 also uses plain language ("Would you like me to notify the Scope3 team?") so users know what the action means.
* Action buttons across the seller widgets now name what they do — "Fix this run", "Build my profile", "Update profile", "Get a recommendation" — instead of naming the assistant ("… with Murph" / "Ask Murph"). The agent still does the work; the button just says the outcome.

## 2.181.0 — June 22, 2026 at 3:44 PM UTC

* Fixed a bug where hosted MP4 video creatives could not be forwarded to sales agents. Dimensions for MP4 video assets are now extracted from the file's ISOBMFF container at upload and execution time, so video creatives proceed through media-buy execution without a "numeric width and height" validation error.
* Fixed service tokens showing no active agents when agents became active after the token was created. A token's active agent list is now kept current whenever an agent is registered, activated, disabled, or reassigned, and existing tokens have been backfilled.
* Fixed an issue where creatives synced to a media buy placed through a storefront could fail to reach the underlying seller. The forwarded sync\_creatives request was missing the account the media buy was created under, so it was rejected before delivery and the buy could stay in `pending_creatives`. Creative syncs now reuse the correct per-source account.
* Inventory-source health alerts are now owner-aware. When an official Scope3-hosted adapter (e.g. Pinterest, Reddit, Snap) has a runtime outage, Scope3 is alerted internally instead of notifying the seller about infrastructure they don't operate. When the issue is the seller's own adapter credentials, they still get a notification telling them to reconnect. Sources the seller operates directly are unchanged.
* Sellers now receive an "all clear" notification when a previously-unhealthy inventory source recovers, closing the loop on the unhealthy alert. It fires only for sources we actually alerted on, exactly once per outage, so it never spams.
* When a sales-agent connection check fails, diagnostics now report the specific failure — the HTTP status, whether it was an authentication/audience rejection, a timeout, or a network/DNS error, plus a redacted response excerpt — instead of a generic "not reachable" message. This makes it possible to tell an OAuth token or audience mismatch apart from an endpoint that is simply down.

## 2.180.0 — June 22, 2026 at 2:30 PM UTC

* Your acceptance policy now reads as a traffic-light — what you Accept (green) vs Decline (red) — instead of one flat gray list, so the two sides of the policy are clear at a glance. "Update policy" is now the clear primary action.
* Murph in-chat approval controls are more reliable. The window to approve a pending action is longer, so a review that takes more than a few minutes no longer lapses mid-decision, and a lapsed approval now shows an explicit "expired — ask again" state instead of a blank step that looked like the controls were missing. A pending approval also survives when the click that approves it is handled by a different server instance or after a restart, so approvals are no longer silently stranded. Approving an action started while signed in as another user (support-assisted setup) no longer fails with a confirmation error.
* Fixed several notification types that were silently failing to deliver — most notably the "your ad-server connection needs action" alert for sellers, plus outcomes-agent registration/update notices. These types were defined in the API but missing from the database's notification-type list, so the platform dropped them instead of sending them; they now deliver as intended.
* Fixed a managed media buy failing at ad-server line-item creation when a product offered both a sized display format (e.g. 970×250) and the dimensionless display family format. The buy now forwards the sized format so the line item can be trafficked, instead of sending the dimensionless one alongside it and failing.
* Merchandising rules now has one clear primary "Update rules" action instead of a row of look-alike low-contrast buttons, and its actions are named for the task ("Update rules", "Write merchandising rules") rather than the tool.

## 2.179.0 — June 22, 2026 at 1:48 PM UTC

* You can now stop an in-flight Murph chat turn. While Murph is working, a Stop control appears in the composer — pressing it ends the turn immediately instead of waiting for it to finish. Stopping does not undo anything Murph already did on that turn (for example, a change it had already applied); the reply makes that clear.
* Storefront readiness now reflects when Stripe later disables, restricts, or disconnects your connected payout account. Previously, once payout onboarding completed it was recorded as done permanently — so if Stripe turned off payouts afterward, your storefront still showed billing as complete and "ready to sell" even though you couldn't be paid out. Readiness now re-flags payout setup when Stripe reports the account can no longer pay out.
* Signal lifecycle status now shows a color-coded badge (active / draft / archived) instead of a flat gray pill where every state looked the same, reusing the shared seller-widget status badge.
* Fixed approved creatives getting stuck at "0/1 source" when forwarded to an ad server (e.g. Google Ad Manager) that reviews creatives asynchronously. An async-accepted creative is now correctly recorded as forwarded, so the operator's approval lands instead of bouncing back as pending.
* Murph can now attach URL-backed creatives reliably. The `create_creative_manifest` operation now publishes its request schema through `describe_operation`, so the agent uses the correct shape (a URL asset, an object-form format id) instead of guessing and failing.
* Product discovery no longer hangs indefinitely when a single sales agent is slow to respond. Each agent now has a hard per-call ceiling, so one unresponsive seller is skipped (and reported) instead of stalling the whole discovery run.
* Stop Murph from re-issuing the same failing tool call turn after turn. When a request with byte-identical arguments has already failed in multiple previous turns, Murph now tells you the request keeps failing and stops retrying, instead of silently re-sending it. Mutations that are simply awaiting your approval are not affected.
* Fixed a confirmation-loop bug where Murph's in-chat Approve button could misattribute a banner-attach (or other buyer write) approval to a discovery re-run when multiple pending confirmations were in context. The server-injected approval message now names the specific operation, so Murph cannot confuse which call to replay.
* Murph now presents the complete product discovery results to the user before offering curated recommendations. Previously, Murph could jump directly to a shortlist without giving the buyer a chance to browse the full inventory.
* Fixed the Murph sidebar recents empty state so it no longer creates unnecessary scrolling in compact layouts.
* Fixed Murph chat occasionally failing with a "network blip" error during long-running turns. The chat stream now sends a periodic keep-alive so a multi-minute response (for example a large product discovery) is no longer cut off by an idle-connection timeout.
* Fixed a loop where registering a third-party sales agent with no authentication kept redirecting to the credential form. Murph's post-registration guidance ("add a bearer token later via /source credentials") was being misclassified as an in-chat credential solicitation and replaced with a secure-credential redirect, leaving the registration visibly incomplete.
* Fixed the "Confirm currency" control in the seller setup checklist, which silently did nothing when clicked. The settlement-currency update is now applied, and a failed save surfaces an error instead of leaving the step unchanged.
* Storefront readiness now reflects real product availability for storefronts backed by a managed sales agent. Previously these storefronts always showed products as ready regardless of whether any products or signals existed; go-live now blocks only when a storefront genuinely has nothing to sell (no wholesale products and no signals to compose from). A storefront with signals but no pre-built products is correctly treated as sellable.
* The approvals view now shows a clear "you're all caught up" confirmation when nothing is waiting on your review, instead of a bare line of text that could look like a broken panel. Introduces a shared empty-state used across seller widgets.
* Event source health now shows a color-coded status (Receiving / Needs attention / Not seen) that stays legible in dark mode, instead of a flat gray pill where every state looked the same. Introduces a shared status badge used across seller widgets.
* When a seller-operated inventory source stays unhealthy past a short threshold (default 10 minutes), Interchange now opens a Pylon support issue so the seller is reached in their support channel — and auto-closes it once the source recovers. Sporadic blips that self-heal within the threshold never open a ticket, and Scope3-hosted adapter outages route to Scope3 rather than the seller.

## 2.178.0 — June 22, 2026 at 8:54 AM UTC

* Sellers are now proactively notified when a third-party inventory source they operate goes unhealthy, so they can restore it before it stops serving demand — instead of only finding out by opening diagnostics. The alert is operational (always-on, customer-scoped) and debounced so a flapping source cannot spam. Official Scope3-hosted adapters are excluded for now; their owner-aware alerting is a follow-up.

## 2.177.0 — June 22, 2026 at 6:25 AM UTC

* Removing an inventory source no longer leaves it able to block your storefront. Source removal is a soft delete, so an unresolved trafficking error on a removed source previously kept readiness blocked indefinitely (and the resolved item lingered in your work queue). Readiness and the work queue now exclude items on removed sources.
* Inventory-source diagnostics now identify who owns a failure. The `diagnosis` block of `GET /api/v2/storefront/inventory-sources/{sourceId}/diagnostics` includes an `owner` field: for an official Scope3-hosted adapter (Pinterest, Reddit, Snap, …) a runtime failure is attributed to Scope3 — with guidance that it recovers automatically — instead of asking you to debug infrastructure you don't operate. Adapter credential issues and your own external sales agents remain yours to fix.

## 2.176.0 — June 22, 2026 at 5:55 AM UTC

* A separate action-required indicator now appears in the top navigation when your storefront is blocked from selling, and opens the "Get ready to sell" readiness view so you can fix the blockers. It's distinct from the notifications bell (which stays for passive updates) and only shows while there's something to act on, clearing once your storefront is ready.
* Ad-server connection alerts ("sync action required") are now always-on like other storefront readiness alerts — delivered to your whole team and shown in the notifications feed regardless of preferences, since a broken ad-server connection stops your storefront from selling. They no longer appear as a toggle in notification settings.
* Storefront readiness alerts — your storefront was paused, or products aren't ready to traffic — are now delivered to your whole team automatically rather than being something you had to opt into. These operational alerts can't be muted, so a storefront problem never goes unnoticed, and they no longer appear as toggles in notification settings.
* Fixed the Ad server item in the seller navigation doing nothing when clicked — it now opens your ad-server inventory view (connections, sync status, wholesale products, and signals), the same surface the inventory link already opened.
* Notification settings no longer show a duplicate "Storefront" category, and the list now only includes the categories relevant to your account — buyers see buyer notifications, sellers see storefront notifications. The sales-agent notification category is now labeled "Sales agent."
* Murph now acts immediately when you approve a change it proposed (for example a campaign start-date edit), instead of repeating the confirmation in a way that left it unclear whether Murph had already made the change or was still waiting on you.
* Fixed Murph confirmation messages to unambiguously use future tense so users can tell whether Murph has acted or is waiting for their approval.
* Murph confirmation and approval summaries now use plain language — no API field names, ISO codes, JSON paths, or internal schema reasoning. Before any gated action (campaign creation, policy write, advertiser setup), Murph describes what will happen in terms of the buyer's intent, not the underlying API call structure.
* Murph no longer warns that a campaign or flight start date of today is in the past — a start date of today is valid and is accepted without friction. When you ask which inventory covers a channel or region, Murph now leads with the storefronts that match and offers to run discovery for actual products and pricing.
* Fixed duplicate approval prompts appearing for product discovery actions in sessions where discovery had previously been run. Returning buyers no longer see a second confirmation gate when re-running discovery in the same conversation.
* Improved the error message shown when Murph is temporarily unreachable server-side. The message no longer instructs users to check their own connection when the issue is on Scope3's end.
* Murph no longer infers an advertiser's primary currency from seller-side storefront data (name, domain, region, pricing, or rate card). Currency is now always sourced from the buyer's own stated preference or by asking directly.
* Fixed an issue where Murph incorrectly rejected today's date as a campaign flight start date. The validator now correctly uses UTC midnight for date comparisons, matching how ISO 8601 date strings from clients are parsed.
* A new seller's menu now keeps the focus on getting set up. Until the storefront
* is live, the Merchandise and Operate sections start collapsed — one click opens
* them — so the rail shows the foundational steps instead of every option at once.
* They expand automatically once the storefront is live, or whenever you're working
* in one of them.
* The Approvals item in the seller navigation now opens the full approvals view, where you can see every pending creative review and media-buy approval and approve or reject each one inline — instead of a read-only summary of the most recent few.
* The Self-serve buyers item in the seller navigation now opens its full in-chat view, where you can create and share your buyer invite link, copy or disable it, and approve, decline, suspend, or reactivate the buyers who have joined — all in one place.
* The Business profile and Pricing & terms items in the seller navigation now open their full in-chat views — your profile, voice, and pitch; and your rate-card rules and approval settings — instead of a condensed summary panel.
* Once a seller's storefront is live, the menu now collapses the set-once "Set up"
* section and leads with the ongoing Merchandise and Operate work — mirroring how a
* not-yet-live storefront keeps Set up open and collapses the rest. Collapsed
* sections are one click away, and any section you're working in stays open.
* Rebuilt the seller "Get ready to sell" surface into a go-live readiness dashboard and extended it to reflect live operational health. It now leads with your go-live progress and one clear next action, lets you confirm simple settings like your settlement currency right in the surface, and offers accept-default / upload-your-own / build-with-help for your acceptance policy. Once you're live it stays a glanceable health check: if an inventory source goes down or buys fail to traffic, it flags exactly what's stopping you from selling — with direct "reconnect" and "resolve" actions — in step with the action-required indicator.
* The Test runs item in the seller navigation now opens its full in-chat view: your sandbox test history, and for each run the per-sales-agent breakdown (which agents returned products, came back empty, or failed — with the raw call payload), the run's context, and a one-click handoff to Murph to fix a failed run.
* When a campaign's selected products include a sales agent that can't be used with the campaign's routing type (for example, a decisioned storefront selected into a routed campaign), that agent is now skipped with a warning instead of failing media-buy creation for the entire campaign. Compatible sales agents in the same campaign still get their media buys.

## 2.175.0 — June 22, 2026 at 1:06 AM UTC

* Advertisers are now unique within a customer by the pair of brand domain **and** primary currency, instead of by brand domain alone. The same brand domain can back more than one advertiser as long as each uses a different currency (e.g. one in USD and one in EUR). Creating — or updating an advertiser onto — a brand domain + currency pair already taken by a sibling advertiser returns a conflict.
* Murph now coaches sellers all the way through acceptance-policy setup instead of stopping to say the decision "has to come from the operator." When a step asks which advertisers or creatives to accept, decline, or send for review, Murph asks the questions, drafts the policy, and writes it on your confirmation — rather than handing back a generic template. The in-product recovery after a hiccup also no longer implies a change that already saved cleanly failed.
* Fixed Murph chat scrolling and added clearer debug-call provenance, including timestamps, initiators, and whether calls came from sandbox tests or non-test demand traffic.
* Murph now proactively coaches sellers whose storefront isn't live yet. On the
* first message of a conversation, Murph leads with where the storefront stands —
* how many steps remain before it can answer its first buyer brief and what the
* immediate next step is — and offers to walk through it one step at a time,
* instead of waiting to be asked. The offer is made once per person, with a
* lighter "pick up where you left off" nudge on a later visit, and it stops
* automatically once the storefront goes live.
* When a seller opens Murph without an active conversation, it now opens directly
* to the right place — the setup checklist while the storefront isn't live yet,
* the dashboard once it is — instead of a blank screen next to the full menu.
* Starting a new chat still gives a clean chat to type into.
* Sellers can now attach pricing to wholesale signals (CPM or revenue-share), so audience signals can be sold with an incremental price.

## 2.174.0 — June 21, 2026 at 3:47 PM UTC

* Storefronts now flag products synced from a connected sales agent that can't be trafficked — for example, video formats missing a duration. The issue appears in your storefront health and raises a notification naming how many products are affected, so you can fix them in your sales agent and re-sync. This extends the same not-traffickable detection that managed ad-server products already have.
* Fixed Murph chat consistently failing with "Murph chat stream ended without a result" even though the reply was generated and saved. The streaming response now reliably delivers its final result.
* Product activity entries now record the full set of seller-meaningful fields (delivery type, inventory type, formats, pricing, exclusivity) instead of only name and pricing, so edits to those fields are no longer silently omitted from the activity feed. The audit row no longer stores the raw product payload, keeping unbounded upstream data out of the activity log.
* Murph no longer stops a conversation when an account reaches its daily usage
* budget. During the beta we meter usage and watch instead of blocking, so a
* seller or buyer is never cut off mid-task. A high runaway-safety limit still
* guards against abuse or a stuck loop.
* The seller rail's "Get ready to sell" now opens the coached go-live checklist (the Setup widget with a highlighted "do this next" step and a walk-me-through option) instead of the older state drawer — so the most important setup row lands a new seller on the guided surface.
* The "connect an inventory source" and "ad-server source" go-live checks now name the actual ad servers (Google Ad Manager, FreeWheel, SpringServe) and the sales-agent option in their guidance. This makes the step clearer for a new seller and routes Murph's "walk me through it" hand-off to the GAM-access documentation, so the most common setup question is answered at the moment of friction.
* Reorganize the seller agent's navigation rail into three teaching sections — **Set up**, **Merchandise**, and **Operate** — with plain-language labels, so a new publisher can see the whole journey at a glance. Renames the opaque rows ("Demand inbox" → "Demand", "Selling terms" → "Pricing & terms", "Source sales agent" → "Sales agent", "Source ad server"/"Inventory" → "Ad server", "Go live" → "Get ready to sell", and more), splits ad-server vs. sales-agent connection into distinct rows, and surfaces Acceptance policy, Merchandising rules, and a Components coaching entry directly in the rail.
* Added a Setup view to the seller chat experience. Ask Murph "is my storefront set up?" (or use `/setup`) to see your go-live checklist — the single most important next step is highlighted, required steps come first, and every step can be done with Murph right there. "Walk me through it" hands the whole sequence to your agent.
* Renamed the app support menu status link to "Scope3 service status".
* The not-traffickable product check now covers every connected source's synced catalog — not just third-party sales agents — and runs even when a storefront also has a managed ad server, so any source with products that can't be trafficked (e.g. video missing a duration) is caught and named per source. Managed ad-server sources continue to be covered by their own setup checklist.

## 2.173.0 — June 21, 2026 at 4:58 AM UTC

* Creative changes now appear in your activity feed: creating, updating, archiving, and assigning or removing a creative to/from a campaign — and bulk creative updates — are each recorded with who did it and when. Previously the creative service wrote no activity at all.
* More seller actions now appear in your activity feed: creating a storefront, resetting brand verification, linking an agent as an inventory source, and approving or rejecting an ad-server (ESA) workflow are each recorded with who did it and when. This clears the last of the known audit-coverage gaps.
* Your activity log is now reachable from chat: type `/activity` in the composer to open it. The log opens on recent account-wide activity instead of requiring you to pick an advertiser and campaign first — those filters now refine the view rather than gate it. The buyer Diagnostics shortcut also now opens the diagnostics view as intended.
* Storefront API calls scoped to your own storefront (listing products, demand signals, the dashboard summary, and responding to a demand signal) no longer require you to pass a `storefrontId` — the server resolves your storefront from your account. A wrong or guessed id is corrected automatically, and calling before you have a storefront returns a clear "start onboarding first" message instead of a confusing missing-parameter error. Inventory-source `executionType` and `status` values are documented as the uppercase enums the API requires (`AGENT`, `PENDING`/`ACTIVE`/`DISABLED`).
* Added a Dashboard view to the seller chat experience. Ask Murph "how am I doing?" (or use `/dashboard`) to open your storefront performance at a glance — win rate, booked budget, delivery, how your agent's negotiation postures convert, and what to improve — without leaving chat.
* Storefronts now flag go-live blockers when a product cannot be trafficked (for example, a video product missing its duration). The blocker is surfaced the moment you ask your storefront agent about capabilities, and it raises a notification (with email for opted-in operators) — naming how many and which products are affected — so you know your storefront is not live and exactly what to fix.

## 2.172.0 — June 20, 2026 at 3:21 PM UTC

* Added an in-chat Acceptance Policy view to the seller Murph experience — see your storefront's acceptance policy (which advertisers, categories, and creatives your agent accepts or declines) with version history, and ask Murph to summarize, explain, or update it.
* Added an in-chat Activity Log for storefronts. Ask your agent to "show the activity log" (or type `/activity`) to open a read-only feed of recent changes — each entry shows what changed, whether it was a person, the agent, or automation, and whether the action succeeded, was denied, or was blocked. You can also just ask "who changed this?", "what changed yesterday?", or "what got blocked?" and get the answer in chat.
* Added an Approvals view to the seller chat experience. Ask Murph for "Approvals" (or use `/approvals`) to see your review-gate settings alongside anything waiting on you — pending creative reviews and pending media-buy approvals — and hand decisions or gate changes back to Murph in chat.
* Activity feed entries now record how each action was initiated. A new `actorOrigin` field on buyer and storefront audit logs distinguishes a change made directly by a person (`human`) from one the Murph agent made on a user's behalf (`agent`), as well as `autonomous` and `system` actions. The activity timeline shows a "via Murph" badge on agent-initiated changes so you can tell at a glance who — or what — made a change.
* Added an in-chat Business Profile view to the seller Murph experience — see your storefront's channels, regions, verticals, properties, and the pitch buyers see, and ask Murph to update it.
* Added an in-chat Merchandising Rules view to the seller Murph experience — see how your agent turns your inventory into sellable products (your operating instructions), with version history, and ask Murph to summarize or update them.
* Sellers now choose the country their business is based in when connecting a Stripe payout account. This country is set when the account is created and determines the payout/settlement currency (for example, a seller in Germany settles in EUR), so it can no longer default to US. Provisioning a Stripe Connect account now requires a `country` (ISO 3166-1 alpha-2) value, restricted to countries Stripe supports for payouts; an unsupported country returns a clear validation error instead of a generic failure.
* The seller Approvals view is now a place to do the work. Open Approvals (or `/approvals`) to drill into a pending creative review or media-buy approval, see how it was pre-screened (the policy/brand/readiness verdict and what was flagged), preview hosted creatives inline, and approve or reject it with a note — without leaving the view. Changes to live media buys are flagged; approving a flagged item asks for a deliberate confirm; and when an approval can't reach your ad server you now get the specific reason (and the item stays pending to retry) instead of a generic error. Approval automation settings now live with your other policies rather than in the queue.
* Advertiser edits, archives, and restores — and attaching a discovery run to a campaign — now appear in your activity feed, with who made the change and when. Previously only advertiser and campaign *creation* was recorded.
* Closed two gaps where changes weren't reaching the activity log. Creating an advertiser is now recorded (it previously left no audit entry, so "who created this advertiser?" had no answer), and a new `ADVERTISER` resource type is filterable in the activity feed. Storefront product changes — including floor-price edits — are now recorded as updates with a before/after diff instead of being logged as a fresh "create" with no history; identical re-saves are no longer logged at all, so routine discovery refreshes don't add noise.
* Managed ad-server source changes and billing changes now appear in the activity log. Connecting, reconfiguring, rotating credentials for, deactivating, and reactivating a managed ad-server source, plus connecting a payout account and updating billing terms, are each recorded — so operators can see who changed what. Credentials and Stripe identifiers (account ids, onboarding links, client secrets, tokens) are never written to the log.
* Product discovery now only surfaces products priced in the storefront's settlement currency. A storefront sells in one currency and can't settle a buy in another, so products (Chef-composed or passed through from sources) with no pricing option in the storefront's currency are no longer returned, and off-currency pricing options are dropped from the products that remain. Storefronts that have not yet confirmed a settlement currency are unaffected.
* The buyer and storefront activity feeds can now be filtered by who and how. New query parameters on the audit-log endpoints let you narrow to a specific actor (`actorUserId`/`actorUserEmail`), to how a change was initiated (`actorOrigin`, e.g. only changes the Murph agent made), to a single resource (`resourceId`), and to specific actions (`actions`). This makes questions like "what did the agent change last week?", "who deleted this?", and "what has this user done?" answerable directly. Murph's recent-activity lookup also now reports the origin and the before/after of each change, supports an end-of-window bound, and returns more rows.
* Setting credentials now opens the sales-agent management surface (where credentials live alongside setup and diagnostics) instead of a separate standalone credentials screen that showed "no sources found". The seller rail's sales-agent entry opens the same consolidated widget.
* Connecting an ad server no longer shows a server error on the Signals or Creative-formats tabs when the upstream ad-server adapter is briefly unavailable or doesn't advertise those capabilities. Capability and creative-format probes now degrade gracefully to an "unavailable / not supported yet" state instead of failing the whole source view, so inventory, signals, and formats stay usable independently.
* Simplified seller source-management entry points around Source ad server and Source sales agent, with credentials, setup checks, and diagnostics managed in the sales-agent source widget.
* Media buy responses now populate creative formats for composed (storefront-curated) products, which previously came back empty because composed products aren't in the raw product cache. The media buy list additionally fills in the product name and publisher for composed products. These are resolved from the storefront's composition data and product index.
* Fixed media buy execution against embedded storefront sales agents whose in-process ADCP endpoints are stored as relative paths.
* Clarified that a storefront settles in one currency, which must match its connected Stripe payout account. The go-live currency copy no longer implies the currency is derived from your ad server, and the storefront agent now explains that clearing a second currency means setting up a second storefront rather than adding a currency to an existing one.
* The activity log now records mutation attempts that did not take effect, not just successful changes. Actions blocked by a permission or Terms-of-Service gate are recorded as "denied" and ones that errored mid-execution as "failed", so you can answer "who tried to change this and why didn't it stick" — including the "I didn't do that" dispute case. The buyer and storefront audit-log endpoints accept a new `outcome` filter; by default the feed still shows only changes that succeeded, and passing `outcome=denied` (or `failed`) surfaces the attempts across all resource types. Murph's recent-activity lookup can report and filter on the outcome too.
* Sellers can now ask Murph about their storefront's activity log — who changed the storefront config, billing, or a managed ad-server source (connect, reconfigure, rotate credentials, deactivate), whether it was a person or the agent, and what got blocked or failed — over a time window. Connecting a Stripe payout account now appears in the seller activity feed.
* Advertisers are now single-currency. `primaryCurrency` is required when creating an advertiser, and it can only be changed while the advertiser has no campaigns — once the first campaign is created the currency is locked. Every campaign is created in its advertiser's currency: if `budget.currency` is supplied on campaign creation it must match the advertiser's currency, otherwise the advertiser's currency is used.
* Source management is clearer and more self-serve in Murph and the seller widgets:
* Murph now explains the difference between an **ad server** source and a **sales agent** source and which you need, instead of dead-ending on the question.
* "Debug my sales agent" no longer silently assumes your ad server — when you have both, Murph asks which one, then diagnoses the right source (live connection probe, ranked likely causes, and next steps for an external agent; sync health for an ad server).
* The **ad-server source** widget adds a Health view that lists every blocking and warning issue with the exact next action — including a one-click **Set default advertiser** fix for the most common go-live blocker — and now consistently calls it your "ad server" (not "ESA").
* The **sales-agent source** widget can now connect a new external AdCP agent directly (name, endpoint, protocol, credentials) instead of leaving you with nowhere to start.
* Opening a source widget now previews what you can do next instead of a bare "Opening…".
* Ensured approved storefront creatives forwarded to third-party inventory sources register callback webhooks when asynchronous source-side review is available.
* Storefront media buys are now validated against the storefront's settlement currency. A `create_media_buy` whose stated budget currency differs from the storefront's confirmed currency is rejected with an `INVALID_REQUEST` (`currency_mismatch`) error rather than silently accepted. A storefront clears in one currency — to transact in another currency, use a storefront that clears in it. Buys that omit a currency are unaffected and are treated as denominated in the storefront's currency.
* A storefront's confirmed settlement currency is now verified against its connected Stripe payout account before go-live. The payout account's settlement currency is captured when Stripe onboarding completes, and go-live is blocked if the storefront's currency doesn't match it — preventing payouts that would otherwise silently convert into a different currency.
* Campaign creation now accepts a `feeType` of `GROSS` or `NET` (defaults to `GROSS`), and campaign pricing is resolved through the Pricing Engine. `GROSS` means the budget is the all-in total the customer pays and the Scope3 fee is carved out of it (media budget = budget − fee); `NET` means the budget is the media spend and the fee is added on top (media budget = budget; total paid = budget + fee). The fee is the same percentage of the budget either way, and the campaign's total budget is stored unchanged. `feeType` is returned on the campaign and is immutable after creation. The pricing rate is pinned at creation and refreshed on each budget edit while the campaign is still a draft; once the campaign is live the rate is frozen and budget edits re-split at that pinned rate — so a rate-card change can never silently re-price a running campaign. Media buys always draw against the media budget, never the total budget. Media-buy and package budget updates are now validated against the campaign's media budget — raising a media-buy budget past what the campaign can fund is rejected instead of silently over-allocating.

## 2.171.0 — June 19, 2026 at 1:58 PM UTC

* Improved campaign media-buy status responses to distinguish draft, pending creative review, upstream submission, and delivery states, and added read-only ESA media-buy diagnostics for verifying upstream persisted buy state.
* Allow Murph creative workflows to attach MP4 video files up to 50 MB and preserve creative dashboard deep links from account-level URLs.
* Added in-chat Test Runs and Selling Terms views to the seller Murph experience, restored direct Murph seller navigation, and opened inventory sources in the inventory setup widget.

## 2.170.0 — June 19, 2026 at 11:41 AM UTC

* Advertise AdCP 3.1 release negotiation on storefront agents and use the stable 3.1 client pin for external seller calls.
* Storefront get\_products now honors pricing currency filters when returning pass-through source products.
* Added customer notifications for managed storefront sync issues that require reconnecting an ad server adapter.
* Added embedded sales agent webhook and buyer discovery cache diagnostics to ESA status and admin sync health, with clearer storefront product-authoring validation in Murph.
* Storefront media buy creation now echoes source-returned package status fields while preserving storefront product and package identifiers.
* Improved chat widgets so they use the available width by default and long Inventory Sources sync views remain scrollable.
* Storefront product discovery now preserves product-scoped signal targeting metadata returned by upstream sources.
* Storefront product discovery now preserves vendor metric reporting and optimization metadata returned by upstream sources.

## 2.169.0 — June 18, 2026 at 8:39 PM UTC

* Publisher discovery now follows redirects and the ads.txt `managerdomain` fallback when resolving `adagents.json`, so domains managed by a network (e.g. Raptive/CafeMedia) correctly surface their authorized agents and properties.
* Murph can now set authentication credentials on an ADCP inventory source directly in chat through a secure credential form — basic auth and API key are entered inline, and OAuth sources get an Authorize button that opens the provider's consent page. This replaces a storefront menu path that no longer existed. Open it with the `/source credentials` command or by telling Murph you have credentials to provide.
* Fixed a crash on `POST /api/v2/storefront/resolve-brand` when a brand manifest from the AAO registry contained non-string field values (arrays, numbers). The advertiser-industry classifier now filters these out instead of throwing a TypeError.

## 2.168.0 — June 18, 2026 at 7:16 PM UTC

* Fixed creative format validation incorrectly rejecting raw video creatives for VAST video placements when the publisher's format declared the video slot without an explicit asset type. These creatives can now be assigned to and kept on media buys for those placements.

## 2.167.0 — June 18, 2026 at 6:04 PM UTC

* Fixed Murph approval controls so pending storefront setup confirmations stay visible when a conversation is reopened and stale approvals no longer block follow-up setup.
* Fixed Murph wrongly interrupting unrelated actions (like filing a report) with an ad-server credential redirect, and pointed the secure credential link for FreeWheel and SpringServe setup at the working inventory-source screen.
* Storefront legacy links now open the matching Murph storefront surfaces.
* Route the buyer creative workspace root through Murph so all creative asset entry points share the dashboard surface.
* Seller inventory-source links now open the shared Murph diagnostics widget instead of a standalone legacy page.
* Legacy advertiser and supply discovery URLs now open the equivalent Murph buyer surfaces.

## 2.166.0 — June 18, 2026 at 3:51 PM UTC

* Added a source diagnostics MCP app for third-party sales agents and modular inventory sources, including tool-level latency, timeout, outcome, and next-step rollups that Murph and other MCP hosts can launch with "open diagnostics."
* Fixed an error when approving an action in Murph (such as filing a report). Approvals
* now reliably go through instead of occasionally failing with a confirmation error.
* Route the buyer activity deep link through Murph while preserving the full campaign activity workflow.
* Route advertiser-scoped creative asset deep links through the Murph creative dashboard surface.
* Migrated legacy product URLs with equivalent Murph surfaces so planning briefs, reporting, supply browse, and buyer connections open inside the unified Murph surface instead of standalone pages.
* Added a `+` menu and `/` commands to the Murph composer so launchable MCP widgets open from chat instead of static navigation. Sellers can open demand inbox, buyers, and sales-agent diagnostics from the composer, including `/diagnostics` and `/inventory sources`.

## 2.165.0 — June 18, 2026 at 1:18 PM UTC

* `add_discovery_products` and `apply_proposal` now report whether the discovery session is attached to a campaign. The response includes `campaignBound`, and when it is `false` a `campaignWarning` explains why no campaign reflects the products: either the session was never attached to a campaign (pass `campaignId`, or run discovery with `campaignId`, to bind it), or the campaign it was attached to has been archived (restore it, or pass `campaignId` for an active campaign). This removes the "add reported success but the campaign still shows 0 products" confusion.
* Improved media buy creative validation errors so invalid video assets are reported as invalid requests instead of source availability failures.

## 2.164.0 — June 18, 2026 at 10:13 AM UTC

* Added an explicit Linear visibility status to Murph escalation artifacts so clients can distinguish unavailable Linear tickets from role-redacted ticket references.
* Added customer-facing guidance for connecting ad platform accounts, including recommended Meta, TikTok, Google Ads, and other platform access levels, and linked it from the Connections setup experience.
* Improved activity diffs so long brief-style updates remain readable.
* Buyers can now request `audio` and `dooh` channels in `discover_products`. Both were previously rejected by schema validation even though the underlying ADCP layer already supported them.
* When `discover_products` returns zero results, the response now includes a specific reason - e.g. how many publishers were queried, how many were skipped and why, or whether no publisher connections are configured for the account. This prevents agents from blind-retrying identical calls.
* Keep MCP connections alive during long-running tool calls. Tool calls that take several minutes to complete (such as product discovery against a slow sales agent) no longer get dropped by the connection idle timeout before the result is returned.
* Fixed Murph incorrectly redirecting to the secure credential form when explaining ad-server setup steps. Guidance like "you'll need to provide your FreeWheel credentials to complete the setup" is no longer mistaken for an in-chat credential request, while Murph still redirects genuine attempts to paste passwords or tokens directly in Slack.
* Fixed DMA code-to-market-name resolution so the buyer agent correctly identifies Nielsen DMA markets by name rather than relying on model memory.
* Fixed a bug where a campaign with a stranded DRAFT media buy (from a prior failed execution) could not be re-executed. The execute endpoint now bypasses the discovery session gate when DRAFT buys already exist, and the media-buy-status endpoint now surfaces DRAFT buys so they are visible rather than silently hidden.
* Fixed Murph starter prompt labels so they use the selected interface language instead of falling back to English.
* Ask Murph can now show you a "Your requests" panel — the issues and requests you've escalated to the Scope3 team, each with its current status, how long ago it was filed, and what's happening next. Ask Murph to show your requests (or use the escalations shortcut) and the panel renders right in the chat, covering everything from open to resolved.
* Fixed product discovery only returning the first page of a sales agent's catalog. Both catalog enumeration and buyer product discovery now retrieve the full catalog by following `get_products` pagination, so products on later pages (for example CTV, interstitial, or banner inventory listed after a first page of other formats) are discoverable and available for deals. Large catalogs that previously truncated at the first page are now returned in full.
* Make a curator's media buy from a pool seller work end to end. Two gaps blocked the in-process buy that only a real (un-stubbed) buy exercised: the bridge's SDK client refused `create_media_buy` because a storefront advertises itself as a discovery agent (its capabilities null out the `media_buy` protocol), and the curator's forward only accepted a `completed` upstream status and rejected the `pending_start` (accepted-but-trafficking) state a storefront seller returns. The bridge now skips the pre-flight feature gate for the trusted in-process seller, and the forward accepts a linked seller's create whenever it returns a media buy id. Adds an end-to-end real-Postgres test of the full cascade (curator → bridge → seller → modular terminal) with both spread-ledger legs booked.

## 2.163.0 — June 17, 2026 at 11:57 PM UTC

* Added selection and refinement actions to buyer starter proposal cards, and surfaced seller-side demand coverage in storefront readiness.
* Added seller documentation for diagnosing third-party sales-agent inventory sources, including source health, recent AdCP activity, and buyer discovery debug output.
* Brand resolution now classifies each resolved brand into a canonical AdCP advertiser-industry code (e.g. a steakhouse → `food_beverage.restaurants`), surfaced as `advertiserIndustry` on the brand manifest. Brands now share one category vocabulary across the platform and with AdCP, so a brand.json can advertise its canonical industry. This is the foundation for category-based starter briefs.
* Standardized the buyer dashboard page headers. Every section — Campaigns, Creatives, Data sources, Reporting, and Activity — now renders a consistent header at the correct size, with each section's controls in the header: Reporting's date filters, Creatives' campaign filter, Data sources' Catalogs/Conversions tabs, and Activity's kind filter. Buyer page headers also stay pinned while scrolling, and the Planning Briefs page uses the standard page-header layout for a consistent title, description, and primary action.
* Storefront interchange is now an open marketplace pool. A curator storefront automatically discovers and composes wholesale inventory from every listed storefront whose offerings match the curator's own channels — there is no per-storefront linking or approval step. A storefront participates simply by being listed in the marketplace, and a seller's price floor and content policies are always enforced on every resale.
* Streamlined the storefront navigation. The rail is reordered around going live and daily demand, renamed for clarity ("Reporting", "Agent training"), and Team and Billing moved into Settings to keep the rail focused on selling. Storefront testing now lives in the Demand inbox.
* Fixed a bug where multiple Anthropic API 500 errors from the same call site would each open a new GitHub issue instead of deduplicating onto a single issue. The Anthropic SDK embeds a unique `request_id` in each error message, which was causing the error fingerprinter to generate a distinct hash per occurrence.
* Fixed the activity feed rendering a campaign brief change one word per line. Long brief edits now show the new brief as a full-width paragraph instead of a cramped side-by-side diff.
* Customer account lists now include active child accounts accessible through parent administrator permissions.
* Fixed publisher authorization discovery so live authorization can clear stale verification results, and Murph checks specific seller domains with a fresh domain lookup instead of browsing cached catalogs.
* Corrected storefront setup documentation to use the canonical Interchange storefront agent URL and updated managed ESA publisher-property lookup to avoid treating ESA authorization checks as the source of truth.
* Fixed `PUT /storefront` rejecting a settlement-currency update with "At least one field must be provided to update". `defaultCurrency` (and `supportedLanguages`) were valid fields but were missing from the update body's non-empty check, so sending only `defaultCurrency` — the call required to clear the `currency_confirmed` go-live blocker — failed validation. These fields now satisfy the check, so a currency-only update works. Also documented the field in the storefront agent skill's Update Storefront reference.
* Fixed media buy status not updating for buys placed through a storefront. A storefront fans a single media buy out to multiple upstream sources, so its status is now rolled up from those per-source statuses rather than left stuck at "pending approval". A buy that is live upstream now correctly reports as active, and reflects paused, rejected, completed, and other states the same way.
* Localized buyer activity filters, empty states, pagination copy, and invitation accept prompts.
* Localized advertiser management copy, table labels, advertiser dialogs, and archive/restore prompts.
* Localized buyer storefront connection copy, status labels, account prompts, feature controls, and notification preference labels.
* Localized Discover Supply table, page, note, and submit copy.
* Localized storefront account card metadata and archive dialog fallback copy.
* Localized storefront card preview fallback messages and Supply page empty states.
* Localized storefront card channel/status labels and Supply page filter copy.
* Localized storefront demand signal cards and locale-formatted their budget, flight, and fit details.
* Localized storefront drawer readiness, pricing, and performance summaries.
* Localized storefront drawer chat prompts for setup, readiness, approvals, catalog, and document-processing actions.
* Localized storefront test-run diagnostics and helper status labels.
* Localized storefront inventory and source status labels across source tiles, details, and catalog rows.
* Localized storefront inventory-source chooser, filters, empty states, and adapter connection labels.
* Localized storefront link request dialogs and inbound request actions.
* Localized storefront setup task controls and demand contact editing copy.
* Localized storefront setup task rows and translated their status, action, and sync-health copy.
* Localized the storefront state drawer, including setup guidance, source diagnostics, buyer invite actions, and document-processing details.
* Re-validating a publisher's `adagents.json` is now reliable when a fix has just gone live. If you publish or correct your `adagents.json` and product creation is still rejected as "not authorized", you can ask the assistant to re-check your domain and it will re-read the live file, refresh authorization, and re-sync your properties so you can create products without an out-of-band support request. Storefront agent discovery also now self-heals a stale authorization flag when your live `adagents.json` is valid, regardless of how many properties are already registered.
* Murph campaign summaries now include stored campaign constraints, including AdCP geo metro targeting codes.
* Storefront interchange discovery now scopes the ambient wholesale pool by geo/region in addition to channel. A curator storefront discovers wholesale inventory from LISTED storefronts whose declared regions overlap its own (legacy region-code aliases are honored). Region scoping is lenient on the seller side: a storefront that has not declared regions stays discoverable everywhere — only a seller that explicitly serves non-overlapping regions is filtered out.
* Restored seller demand inbox and buyer management surfaces as MCP app widgets in the Murph chat shell.
* Brought the storefront chat experience in line with the buyer one: New chat and recent conversations are always visible in the rail, prompt suggestions now fill the composer (so you can add context before sending) instead of sending immediately, the chat input shows only in the chat view, and rail spacing, labels, and suggestion styling are tightened and consistent across buyer and seller.
* You can now delete a chat from Murph's Recents list: hover a conversation, open the "⋯" menu, and choose **Delete chat**. Deleting removes the chat from your sidebar right away. Behind the scenes the conversation is retained so support can review product issues, but it no longer appears anywhere in your view.
* The storefront overview now shows your **realized margin** and **margin %** alongside delivery metrics, so a curator can see resale profitability at a glance — what you charged buyers, minus what you paid sources — for the current period. Margin is reported in your primary settlement currency; it fills in once your media buys start delivering.
* The buyer assistant can now look up an operation's exact request schema and a canonical example before calling it, so it gets field names and types right the first time instead of guessing. It also adds discovery products to a campaign through a verified workflow that confirms the campaign-facing product count actually rose — preventing a silent zero-count attach from being reported as success.

## 2.162.0 — June 16, 2026 at 6:58 PM UTC

* Fixed a media buy failing to save at execution when an inventory source returns tokenized product identifiers containing colons (e.g. `wh:<source>:<product>`). The id validation now accepts the colon-delimited token format these sources use, so the buy completes instead of erroring with an "invalid format" message after the source already accepted it.

## 2.161.0 — June 16, 2026 at 5:20 PM UTC

* Added `GET /api/v2/storefront/reporting/margin` — a curator's resale P\&L. It reports booked vs realized buy/sell/spread and margin %, rolled up buyer → media buy → package → source leg, so a storefront operator can see what it paid each source, what it charged its buyer, and the spread between them. Amounts are signed (a resale at a loss is shown, not hidden) and are reported per settlement currency, never summed across currencies. This is a cumulative as-of snapshot, scoped to the calling storefront.
* When you create an advertiser from a domain, the brand profile shown for confirmation is now the exact profile that gets saved — a freshly built profile is briefly cached and reused at save time instead of being re-derived, so what you confirm is what you get.
* Brand resolution now builds a profile from a buyer's own website when the brand isn't in the registry. Previously a domain that wasn't registered (most local, regional, and smaller brands) resolved to nothing; now we read the site's declared metadata (name, logo, description), its page content, and — when a brand publishes one — its `/llms.txt` summary to fill in name, industry/vertical, tagline, audience, and tone, so the buyer still gets a co-branded experience and a personalized proposal. Harder-to-read or ambiguous sites are read more thoroughly, including additional pages. The profile is always shown for confirmation and is never saved until the buyer reviews it.
* When creating an advertiser, a buyer can now look up their brand by domain and see a "here's how I see you" confirmation card — logo, name, and industry/tagline resolved from the brand registry — before committing. A new `POST /api/v2/buyer/brands/resolve` endpoint resolves a domain to a brand-confirmation card with no side effects; the buyer confirms by creating the advertiser as before. Unregistered domains return a friendly "we'll create one when you save" state instead of an error.
* Added a clear way to return from account settings to the main account screen.
* Restructured the Murph seller storefront surface so Dashboard and setup action areas are first-class left-rail widgets, added a go-live training dashboard for sellers, and fixed OAuth signup so new users reach signup reliably and remain signed in after completing it.
* Fixed an issue where a creative created or updated with a recognized format (such as VAST video) could be rejected when assigned to a new media buy. The canonical format is now inferred automatically, so these creatives attach without an extra step.
* Localized the storefront operating instructions tab.
* Localized the storefront ad-server connection dialog.
* Localized the storefront agent connection dialog.
* Localized the storefront AI usage reporting tab.
* Localized the storefront API access settings panel.
* Localized the storefront directory card modal.
* Localized the storefront communications settings panel.
* Localize storefront settings copy for state controls, brand identity, approvals, visibility, and regional settings.
* Localized the storefront inventory source detail dialog.
* Localized storefront inventory source status tiles.
* Localized the storefront single sign-on settings panel.
* Localize storefront team management copy, invite modal text, role labels, and membership auto-join settings.
* Fixed media buys to agent-backed storefront inventory sources being rejected with a "product not hydrated for account" error. The buyer's brand is now forwarded consistently on both product discovery and the buy, so the source resolves the same account for both legs even when account sync is unavailable.
* Storefront product discovery and composition now transparently retry the underlying inventory source on transient connection failures (e.g. a brief upstream restart) instead of immediately surfacing a "service unavailable" error. Only idempotent reads are retried, with capped exponential backoff.

## 2.160.0 — June 16, 2026 at 8:31 AM UTC

* Creative assets now report their actual pixel dimensions (`width`, `height`) in the manifest response for image and video files. Uploads are validated at creation time: a `warnings` array on each asset surfaces filename-vs-actual mismatches (e.g. a file named `300x250.png` that is actually 600x500) and flags unusually small assets auto-assigned as the primary creative. When a media buy targets a format with explicit pixel requirements, those dimensions are also verified at assignment time.
* Added HTTP Basic Auth support for external inventory sources. Publishers can now register inventory sources that use username/password credentials by specifying `authenticationType: 'BASIC_AUTH'` with `auth: { type: 'basic', username: '...', password: '...' }`.
* Completed HTTP Basic Auth support for storefront inventory source registration, UI configuration, polling clients, and local end-to-end validation.
* Fixed create\_media\_buy failing with PRODUCT\_NOT\_FOUND ("not hydrated for account … call get\_products first") when forwarding to a pass-through sales agent. The buy now syncs and forwards the same account the get\_products discovery leg established, so the source resolves the buy against the account its products were hydrated under instead of a different one.
* Localized activity feed labels and controls, including locale-aware activity timestamps and campaign budget details.
* Localized the buyer planning brief list, detail view, response cards, and sharing dialog.
* Localized proposal cards and storefront media buy approval review surfaces, including locale-aware budget and submission date formatting.
* Localized the storefront proposal queue and proposal code composition flow.
* Add a centralized seller dashboard summary endpoint and wire the Closer widget to use it for buyer brief closing analytics.

## 2.159.0 — June 15, 2026 at 7:03 PM UTC

* Expanded reviewed UI translation catalogs and added safeguards for new localized UI copy.
* Murph now treats portfolio seller onboarding and avails intake as explicit storefront setup flows, with checklist guidance for missing seller materials before inventory can be loaded.

## 2.158.0 — June 15, 2026 at 6:40 PM UTC

* A buyer sponsored into a storefront now lands on a bespoke proposal — "here's what {storefront} can do for you" — instead of a blank planning brief. A new `GET /api/v2/buyer/proposals` endpoint runs a brief-less product discovery scoped to the buyer (confined to the sponsor's storefront for a sponsored buyer) and returns the resulting media-plan proposals, and the buyer home renders them as a card grid (plan, why it fits, placements, budget guidance). Selecting a proposal carries it into the chat to set up. Buyers with no advertiser yet, or storefronts whose agents don't return plans, degrade gracefully to the co-branded home.
* Murph can now draft a concrete avails-feed request and CSV template when seller-provided material is market context rather than actual sellable availability rows.
* Fixed "Service token with ID 0 not found" error when deleting API keys from the UI.
* Fixed product discovery returning no results from strict sales agents. Outbound get\_products requests now send only the brand identity (domain and brand id), matching the behavior already applied to create\_media\_buy and sync\_accounts.
* Storefront modular avails feeds can now preview and commit raw seller rows from CSV text, JSON text, or spreadsheet-like row objects before publishing updated availability.
* Murph now distinguishes seller market summaries from actual avails feeds and asks for real sellable inventory rows before committing modular feed updates.

## 2.157.0 — June 15, 2026 at 2:43 PM UTC

* Catalog sync responses and catalog listings now expose feed health, freshness, version summaries, and item-change summary fields. Catalogs can also store deterministic transform definitions that turn feed items into campaign groups, creative prompt cache keys, budget hints, and backend-inferred seller sharing plans; syncs with an active transform automatically generate a latest activation plan. Item-level catalog changes remain internal to support catalog-driven campaign, creative, and seller re-syndication workflows.
* Creative collections now fan out member creatives into campaign assignments on attach, respecting the format\_kind upgrade gate. Added advertiser-scoped collection endpoints (`GET/POST /advertisers/:advertiserId/creative-collections`) and `owner_scope` field on collection summaries.
* Added locale-aware Murph preference plumbing, reviewed core-language UI catalogs, and a glossary-aware translation workflow for seller-facing Murph actions.
* Added a storefront demand inbox: every buyer brief sent to your storefront, how your agent responded, and the commercial outcome. `GET /api/v2/storefront/intelligence-runs` now accepts a `buyingMode` filter (`brief`, `wholesale`, `refine`) and a `commercialResult` filter (`booked` — forwarded upstream or delivering; `pending` — awaiting your acceptance-policy approval; `rejected`) so you can pull just the demand that converted, the demand still waiting on your sign-off, or the demand that didn't — and each run carries its qualification reason and composed-product explanation.
* Added a buyer MCPUI setup widget and workspace launcher for registering advertiser event sources with expert-run setup, integration mapping metadata, basic ingestion health, and alignment with the shared ADCP event taxonomy.
* Fixed the buyer Ask Murph landing page so it no longer uses seller Merchandising Agent naming.
* Fixed product discovery returning no results from sales agents pinned to AdCP 3.0. Discovery get\_products calls no longer attach a discovery webhook (push\_notification\_config) when the client is below AdCP 3.1; results are retrieved synchronously via polling instead.
* Fixed media buy execution and account sync failing against sales agents that strictly validate the brand field. Outbound create\_media\_buy and sync\_accounts requests now send only the brand identity (domain and brand id); brand-kit and other inline brand overrides are resolved by the seller from the brand's published brand.json.
* Fixed Murph handing out broken ad-server credential-connection links outside of Slack. Links now always point at the configured storefront domain so the secure FreeWheel/SpringServe credential form is reachable.
* Campaign-level postal-code guardrails now merge correctly with the country-local postal area shape: the country is preserved and postal codes are no longer merged across different countries that share a postal system. Targeting a single country's postal codes (e.g. South Africa) through a campaign guardrail now produces valid, country-scoped targeting.
* Storefront `update_media_buy` is more honest when a multi-source buy only partially applies: if some sources accept the update and others reject it, the storefront now returns an error with per-source detail instead of reporting a clean success for a half-updated buy. Budget changes that the storefront cannot parse (for example a non-numeric amount) now require seller approval rather than being auto-forwarded, and a buyer's push-notification callback config is no longer forwarded to upstream sources.
* Fixed storefront media-buy updates so mutable fields are forwarded to inventory sources, material updates enter seller approval before taking effect, and pending update tasks emit terminal webhooks.
* Storefront `update_media_buy` now forwards each change to the correct source instead of broadcasting the buyer's full update to every source. Per source, the storefront keeps only that source's packages (translated to the upstream package IDs) — each package carrying its own budget — and passes through lifecycle and flight changes (pause/resume, cancel, start/end, targeting). This fixes over-committing on multi-source media buys, where every source previously received every package.
* Added an opt-in FreeWheel modular inventory source setting that attempts campaign, insertion order, and placement execution automatically while falling back to the source work queue when execution cannot complete.
* The capability gate that rejects unsupported targeting on ROUTED media buys now covers metro-area systems (`geo_metros`) in addition to postal codes, and is structured as a generic per-dimension registry so future targeting dimensions are covered without bespoke wiring. Behavior is unchanged for postal and for any seller that does not declare a given dimension (fail-open).
* Extended the seller dashboard spec with contract metadata, data sources, metric definitions, data status, and the Closer widget for seller brief outcomes.
* The identity-match targeting feed now accepts root-relative seller agent endpoints (e.g. platform-hosted storefronts) in addition to absolute URLs, so packages backed by hosted storefronts are no longer dropped from the feed.
* Storefront sales agents now declare postal-code targeting per country (ISO 3166-1) and translate buyer-supplied country-local postal codes into each platform's native geo targeting. Snap and Meta read the buyer's `geo_postal_areas` (previously dropped) and emit country-scoped postal targeting; Reddit no longer advertises postal targeting it cannot honor. Declared postal support remains US-only pending per-country platform verification.
* Storefront-to-storefront buying is now end-to-end: a curator storefront with an ACTIVE link can place, update, and track a media buy against a linked seller storefront's inventory. Create/update/delivery forward in-process to the seller, the seller's manual-approval responses are reconciled automatically, and the buyer-facing status rolls up across linked and direct sources. A reach-fence restricts the linked connection to buyer operations only, the loop/depth guard and call-time link-active recheck extend to every mutating call, and the seller is never disclosed to the buyer.
* Added seller-facing endpoints and storefront controls for modular inventory source work items.
* Improved buyer catalog refresh and activation history so feed updates show clearer downstream impact and seller delivery readiness.
* Improved buyer catalog feed visibility with recent refresh and fan-out history in catalog responses.
* Murph no longer pauses ESA product creation when a publisher domain has no
* `adagents.json` / AAO record. AAO publication remains a separate, optional
* setup step in the business-profile flow — operators can author products
* immediately and add AAO authorization on their own timeline.
* A buyer sponsored into a storefront now enters a co-branded experience scoped to that sponsor. A new `GET /api/v2/buyer/scope` endpoint surfaces the sponsoring storefront (name, branding, channels, regions, and account status), the buyer home and shell are framed in the sponsor's brand, and Murph speaks in the sponsor's voice — scoping guidance and starter actions to advertising through that storefront. While an account is awaiting the storefront's approval (or suspended), the home and Murph explain the status and steer toward setup instead of buys that can't go through yet. Ordinary marketplace buyers are unaffected.
* Storefronts can now decline buyer briefs that clearly don't match what they sell or violate their acceptance policy, before composing products — cutting wasted composition cost and capping buyer-driven spend. Fit is judged from the storefront's actual inventory (its packages, channels, regions, and verticals); policy is judged from its acceptance policy. If you set an acceptance policy, briefs that violate it are declined automatically. Buyers receive a standard "no matching products" response — the seller's reasons are never exposed. Every incoming brief is recorded with its outcome (responded / declined for fit / declined for policy), filterable via `GET /api/v2/storefront/intelligence-runs?disposition=...`, so sellers can see exactly which briefs they're winning and missing. This applies to every configured storefront, and the qualifier fails open (composes) on any error so a fault never silently turns away demand.
* The storefront intelligence-runs list endpoint gains a `q` query parameter for case-insensitive brief search, alongside the existing `disposition` filter: `GET /api/v2/storefront/intelligence-runs?disposition=declined_fit&q=fintech`. Find the demand you're winning and missing by searching brief text and filtering by outcome.
* `get_media_buy_delivery` now reports a real, rolled-up status for a media buy that spans multiple sources, instead of always returning `pending_start`. The status reflects the worst material leg — a rejected or unreachable source is never hidden behind a delivering one — and per-source problems (a refused leg, a source that could not be reached) are listed in the response `errors` array. When no source returns observable delivery, the call returns a `SERVICE_UNAVAILABLE` error rather than zeroed totals under a misleading status.
* `get_media_buys` now reports a real, rolled-up status for each media buy instead of always returning `pending_start`. A background reconciler keeps each source's upstream status fresh, and the list folds the per-source statuses into one buyer-facing status — fail-visible, so a rejected or unreachable source is never hidden behind a delivering one. The list is cached for cheapness; `get_media_buy_delivery` remains the live, authoritative current status.
* Added structured buyer brand context to planning briefs and storefront proposals, and forwarded storefront product selectors through live passthrough discovery.
* Offering-based postal targeting now honors each offering's country. Previously, postal codes supplied via an offering's `geo_targets` were always targeted in the US — a non-US offering's postal codes were silently mis-targeted. Offerings now carry country-aware postal areas (`geo_targets.postal_areas`), and the legacy country-less `postal_codes` field is wrapped using the offering's country (falling back to US only when no country is known). On Meta, package-level targeting supplied by the buyer is also preserved when an offering adds its own geo, instead of being dropped.
* Storefront MCP connections now stay reliable across multiple server instances. A follow-up request that lands on a different instance than the one that opened the session is transparently recovered instead of intermittently failing, matching the behavior of the buyer and creative MCP surfaces.

## 2.156.0 — June 14, 2026 at 3:08 AM UTC

* ROUTED media buys are now rejected at execution when the selected sales agent has not declared support for the requested postal-code targeting (`geo_postal_areas`), instead of silently dropping the targeting or failing with an opaque seller error. The seller's declared postal support is read from `get_adcp_capabilities`.

## 2.155.0 — June 14, 2026 at 12:46 AM UTC

* Added storefront acceptance policies plus creative and media-buy policy evaluation so approval workflows can distinguish definitely-on-policy, definitely-off-policy, and human-escalation cases instead of relying on generic operating instructions.
* Optimization suggestions awaiting operator approval are now automatically expired when the underlying media buy is updated. Previously, an operator could approve a suggestion only to discover at apply time that the media buy had been edited and the suggestion was no longer valid. The expiry now happens at the moment the new media buy version becomes active.
* Fixed optimization suggestion apply flow so that when a media buy is updated between when a suggestion is produced and when it is applied, the suggestion is correctly handled based on whether the content actually changed. Stale pins where the underlying configuration is identical now retarget to the current version automatically; pins where the configuration has drifted are marked as expired with a clear reason. Suggestions that pre-date this change continue to use the prior strict-version-equality check.
* Deleting a creative manifest now succeeds even when the creative is actively synced to sales agents. Instead of returning an error, the creative is archived, unlinked from any media buys it was assigned to, and the removal is synced to those sales agents.
* Your Merchandising Agent now learns which negotiation strategy actually wins deals and leans into it. Its strategy recommendation favors the posture that has booked the most for you recently — but only once there's enough evidence to trust (at least four runs that used it, and only if it's actually converting). Your operating instructions and a buyer's live signals still take precedence, and the reasoning is recorded with each run so you can see why a strategy was chosen. Below the evidence threshold, the agent falls back to its existing heuristics.
* Advertiser-scoped creative, discovery, and account-sync calls now use the advertiser's linked brand reference so downstream partners receive the resolved brand identity consistently.
* Murph now publishes reviewed brand.json updates to the AAO community registry through the ADCP SDK registry client.
* Every storefront now starts with default selling behavior: the Merchandising Agent uses your wholesale products and signals to answer briefs as best as possible from the moment the storefront is created. Operating instructions no longer appear in the storefront panel or block going live — you refine how your agent sells by coaching Murph in plain language, and the readiness check now reads "Selling behavior." Pricing stays separate throughout: wholesale rates come from your inventory sources (your embedded or third-party sales agent), and your rate card shapes buyer-facing pricing. The version history remains available on the operating instructions tab for audit.
* The storefront detail endpoint (`GET /api/v2/buyer/storefronts/:storefrontId`) now includes an `adcpCapabilities` field exposing which AdCP operations the underlying agent declares support for. Buyers can check `supportsUpdateMediaBuy`, `supportsCreateMediaBuy`, `supportsGetReporting`, `supportsSandbox`, `extensions`, `protocols`, and reporting delivery methods before attempting calls, without needing to call the agent directly. The `capabilitiesCachedAt` timestamp indicates when the manifest was last refreshed from the agent.
* Murph and buyer agents now explicitly warn that `budget.currency` is immutable after campaign creation and must always be confirmed with the user before calling `create_campaign`. This prevents campaigns from being silently created in the wrong currency (e.g., USD when EUR was requested), which required a full campaign recreate to fix.
* Fixed a bug where creating a GAM advertiser via the storefront ESA endpoint (`POST /api/v2/storefront/esa/:id/gam/advertisers/ensure`) failed with a validation error on the live path while the dry-run path succeeded. The upstream service returns a numeric advertiser ID on real creation; the response schema now accepts both string and numeric IDs and coerces them to strings.
* Updated Google Ads offline conversion logging to use the Google Data Manager API.
* Added modular inventory source controls for operator-confirmed avails feeds, reservations, lifecycle readiness, demo Cadent handoff preparation, booking release, and source-side work queues.
* Storefront diagnostics now live with the storefront. Each inventory source's drill-in shows its recent ADCP calls and status changes next to its health diagnostics, so a failing source carries its evidence with it. The seller navigation slims down to chat and history: the standalone Diagnostics and Dashboard pages are no longer in the seller nav (test runs live in "Test your storefront", change history and activity are available by asking Murph), and the conversation-history sidebar starts collapsed.
* Before your Merchandising Agent is selling, the storefront panel now shows the journey instead of a console: the header counts what stands between you and your first buyer brief ("Two things stand between you and your first buyer brief."), each open blocker is a numbered step you can tap to fix with Murph (with consequence framing — "No sources connected — your agent has nothing to sell yet"), and everything non-blocking is tucked into a single "How your agent represents you" section. The status chip now reads "Selling" / "Not selling yet". Once the agent is selling, the panel becomes the health dashboard as before.
* Media buy execution failures against storefront agents now preserve the structured AdCP error envelope, including `details.per_source`. When every inventory source rejects a media buy, the per-source errors appear in debug output (`errors[].debug.response.adcpError`) instead of being flattened to a single message string.
* Your storefront now prices to value, not to cost. For every brief, the Merchandising Agent sets the price from what the brief is worth to that buyer — premium format, scarce audience, advertiser type, urgency, stated budget — bounded by your wholesale floors and any ceilings you've set, never anchored to a historical auction-clearing percentile. The old fallback percentile is retained only for explainability and no longer sets prices; Murph no longer asks you to choose one. Explicit rate-card targets still act as a value floor the agent can exceed for higher-value briefs, and wholesale rates continue to come from your inventory sources.
* The "Watch your agent sell" card now leads with reality: when buyer demand signals are queued for your storefront, the card shows the actual brief — buyer name, audience, geo, budget — and "Answer this brief" takes it straight to Murph. With no queued demand, briefs are generated from your business profile (your channels, regions, and verticals) instead of a generic pool. Before a storefront exists, the storefront panel now shows a single action — create your storefront — and sections appear only as they become real.
* Improved the storefront Merchandising Agent screen with clearer onboarding copy, a live seller performance dashboard, and cleaner action hierarchy.
* REST error responses with a 5xx status now return a generic message ("An internal error occurred…") instead of the underlying error detail. Internal errors previously embedded the raw error string — which can include database/driver internals — into the response body; that detail is now logged server-side only. Intentional 4xx messages (validation, not-found, conflict) and the 503 retry message are unchanged.
* Seller analytics now breaks conversion down by the negotiation strategy your agent actually used. The `show_seller_analytics` payload includes a `postureConversion` rollup: per-posture run count, booked count, win rate, and booked budget, plus an adherence summary comparing how often your agent followed its recommended posture and whether following it converted better. This turns the per-run strategy capture into "which strategy wins deals" — the evidence base for tuning your selling terms.
* Murph's seller starter prompts now speak in selling verbs instead of setup verbs — "See my agent handle a brief", "Train how I sell", "Connect what I sell", "Is my agent ready to sell?" — and the seller chat header reads "Train the agent that sells your inventory."
* Murph now stays in the seller's register when things break or go deep: connection failures are summarized in plain language with an offer to write up the technical details for your developers, ad-server objects keep the names operators use (never internal identifiers), and acronyms are expanded on first use. Copy refresh from the fresh-eyes audit: the example brief on the chat home is labeled "Example brief", and the starter chips say "Show me my latest buyer briefs" and "What can my agent sell right now?". The panel header no longer clips its collapse button in narrow layouts.
* The Merchandising Agent panel now has a "Selling terms" section showing the enforced facts your agent prices and gates on. Under "How it prices", each rate-card rule shows its floor / target / ceiling by pricing model, marks enforced floors ("Hard floor") versus advisory guidance, and names the brief it applies to. Under "Reviews & approvals", your creative-review and media-buy approval gates are shown in plain language, with a one-tap "Change approvals" action. When you have no price rules, it says so plainly — your agent prices from your sources' rates — with a one-tap "Set selling terms" action. Wholesale rates always come from your inventory sources; these rules shape the buyer-facing price.
* The inventory-source health indicator now tells the whole truth. A source no longer reads "healthy" while its connection is failing or degraded, while nothing has ever successfully synced or been called, or while its inventory list hasn't been pulled — each of those states now downgrades the verdict, explains itself in the status tooltip, and marks the matching row in the source's detail view.
* Storefront sellers can now see their AI usage by model over time in a usage dashboard.
* The storefront api\_call tool now supports a named `operation` field (e.g. `list_partner_agents`, `get_storefront`, `create_esa_connection`), matching the buyer surface. Operation mode derives method and endpoint automatically, validates path parameters before dispatch, and rejects unknown operations and unexpected path params — so agents call storefront operations by name instead of constructing raw endpoint URLs. Raw method+endpoint mode still works as a fallback.
* Sellers can now see how their agent is selling, broken down by negotiation strategy. A new `GET /api/v2/storefront/seller-analytics` endpoint returns the posture-conversion rollup — per-posture run count, booked count, win rate, and booked budget, plus how often the agent followed its recommended strategy and whether following it converted better. The Merchandising Agent rail surfaces this as a "How your agent is selling" section once the storefront is live, so the answer to "which strategy wins deals" lives on a durable surface, not just in chat.
* Manual-approval media buys are now visible end-to-end. Storefront operators see pending media buys on the storefront homepage (live count) and can review, approve, or reject them on the new Media buy approvals page. Buyers can see which layer a `PENDING_APPROVAL` media buy is waiting at via the new `pendingAt` field (`storefront`, `salesagent`, or `unknown`) on campaign media buys. Executing a campaign with no media buys to execute now returns `mediaBuysExecuted: 0` with `reason: no_media_buys_to_execute` and no longer marks the campaign ACTIVE. The execute-campaign request body now rejects unknown fields with a 400 that names them.
* The seller chat home now opens with "Watch your agent sell": a synthetic buyer brief your Merchandising Agent answers honestly from your actual setup — naming the missing supply when no inventory is connected, asking to be trained when selling rules are missing, and offering to run the brief once you're live. "Train how I answer this" starts the coaching conversation with Murph; "Try another brief" rotates briefs, leading with the channels you sell.

## 2.154.1 — June 12, 2026 at 9:38 PM UTC

* Brand identity for product discovery, campaigns, and media buys is now always governed by the brand configured on the advertiser — it can no longer be set or overridden per request. Previously a `brand_manifest` sent on a media buy could override the advertiser's brand at execution time, producing a brand domain that didn't match the one products were discovered under; valid products were then reported as unknown and the buy failed before reaching the sales agent. Media buy execution and product discovery now both resolve the brand solely from the advertiser, so the two can never disagree. Additionally, an advertiser must have a brand configured before product discovery can run or a campaign or media buy can be created: these actions now fail with a clear validation error directing you to add a brand to the advertiser first, instead of failing later with confusing errors.

## 2.154.0 — June 12, 2026 at 9:06 PM UTC

* Creative manifests now expose a `requires_upgrade` boolean field. Legacy manifests (created without a `format_kind`) have `requires_upgrade: true` and must be upgraded via the new `POST /campaigns/:campaignId/creatives/:creativeId/upgrade` endpoint before they can be assigned to new media buys. Existing media buy assignments are unaffected.
* Fixed optimization suggestion HIL expiry so that newer suggestions correctly supersede older pending suggestions for the same media buy, even when a media buy update created a new version between them.
* Fixed optimization-suggestion expiration so that a new suggestion only expires prior pending suggestions for the same media buy. Previously, a new suggestion on one media buy expired pending suggestions across all media buys in the campaign, leaving only one pending suggestion per campaign at any time.
* Storefront media-buy and creative approvals now surface consistently in the storefront-managed approval queue, execute against the underlying sales agent after approval, and send buyer ADCP webhooks when queued approvals resolve.
* Reframed the storefront setup panel around your Merchandising Agent. The panel header now shows how far the agent is from going live and names the next blocker, the readiness section is a blocker-led go-live checklist, brand identity and business profile are combined into a single "About your business" section, and sandbox test plans are now "Test your storefront". Section summaries lead with what needs attention (for example "1 of 2 sources needs attention") instead of raw counts. Every empty state now offers a one-click action — Connect inventory, Run a test brief, Build my profile, Draft my instructions — that drops a ready-made prompt into the Murph composer, and suggested prompts stay available above the composer mid-conversation instead of appearing only on a new chat.
* Media buys forwarded through a storefront to its inventory sources no longer fail client-side schema validation on creative asset values the seller would accept — most notably VAST tag URLs containing `[MACRO]` placeholders (e.g. IAS `[OMIDPARTNER]`), which previously failed `format: "uri"` validation before the request ever reached the source. The source now adjudicates its own request schema; validation issues are logged as warnings.
* TikTok adapter now preserves the upstream HTTP status and response body when a request fails. Gateway errors and timeouts previously collapsed into an opaque "Upstream request failed" with no detail; they now surface the real HTTP status and a body snippet so failures are diagnosable.
* TikTok adapter now logs the upstream error code, message, and request ID when TikTok rejects a request with a structured error (e.g. budget below minimum, invalid parameter, account/permission issue). Previously these rejections were masked to a generic "Upstream request failed" with no detail in logs, making the actual cause impossible to diagnose.

## 2.153.0 — June 12, 2026 at 6:00 PM UTC

* Currency pickers (advertiser primary currency, planning brief budget) now offer every ISO 4217 currency instead of a fixed list of ten.
* Campaign currency now defaults to the advertiser's primary currency when not specified on create (instead of hard-defaulting to USD); an explicit budget currency still takes precedence. Contract rate cards no longer constrain a campaign's currency — only product pricing must match the campaign currency. An advertiser's primary currency can now be changed at any time, even when existing campaigns use a different currency (each campaign keeps its own currency); the previous block has been removed. The advertiser creation form now prompts for the primary currency (defaulting to USD) so it is set explicitly during setup.

## 2.152.0 — June 12, 2026 at 5:08 PM UTC

* Fixed a bug where package budget and bid allocations were not persisted locally after an optimization suggestion was applied. Agents that don't return `affected_packages` in their `update_media_buy` response left the optimizer with stale baseline data for future runs.
* Improved Google Ad Manager buyer-routing diagnostics for storefronts, including safer advertiser-create recovery guidance and warnings when an advertiser sync completes without reporting how many advertisers were retrieved.
* The Terms of Service update prompt now requires admins to tick a confirmation checkbox before the "Agree" button becomes active, so accepting updated terms on behalf of an organization is a deliberate two-step action rather than a single dismiss-the-popup click.

## 2.151.0 — June 12, 2026 at 2:40 PM UTC

* Adds an advertiser-level creative library. Creative manifests can now be created directly under an advertiser (without requiring a campaign), stored as reusable masters, and assigned to campaigns via new endpoints:
* `POST /advertisers/:id/creatives/create` - create an advertiser-level creative master
* `GET /advertisers/:id/creatives` - list the advertiser's creative library
* `POST /advertisers/:id/creatives/:creativeId/campaigns` - assign a master to a campaign
* `DELETE /advertisers/:id/creatives/:creativeId/campaigns/:campaignId` - remove a campaign assignment
* Existing campaign-scoped creative endpoints are unchanged.
* Child accounts can now create campaigns using their parent organization's contract pricing. Previously, creating a campaign from a child account failed with "No active contract found for customer" even when the parent organization had an active contract.

## 2.150.1 — June 12, 2026 at 1:38 PM UTC

* Capability-mismatch errors (`CAPABILITY_NOT_SUPPORTED`) from update operations are now classified as `correctable` and include suggestions naming the specific actions the sales agent does not support (for example `update_pacing`), so you can remove the unsupported field(s) and retry. Previously they were classified as `transient` with no guidance, which could prompt repeated identical retries of a request that can never succeed as-is.

## 2.150.0 — June 12, 2026 at 1:21 PM UTC

* Fixed storefront inventory source assessments so AdCP 3.0 agents that support signals are probed with a schema-valid signals discovery request instead of being marked unsupported before a request is sent.
* Fixed product discovery returning zero products from storefronts whose connected inventory source requires a buyer account. The buyer account is now passed through when discovery runs against an in-process storefront agent.
* Improved buyer campaign creation guidance so explicitly requested budget currencies are preserved when campaigns are created.

## 2.149.0 — June 12, 2026 at 2:38 AM UTC

* Added embedded sales agent signal management endpoints and an interactive widget for authoring mapped and composite signals.
* Allowed advertiser creation to register a reviewed brand identity when registry enrichment has no brand data.
* Buyers can now inspect the AdCP capability manifest for any storefront via `GET /api/v2/buyer/storefronts/:storefrontId/capabilities`. Returns the supported operations, account resolution mode, billing types, and raw capability payload for each source agent — useful for diagnosing why an operation like `update_media_buy` may be gated.

## 2.148.1 — June 11, 2026 at 10:12 PM UTC

* Fixed format\_option\_ref to use the AdCP 3.1 scope-discriminated union. Now accepts `scope:"publisher"` (requires `publisher_domain`) and `scope:"product"` (forbids `publisher_domain`). Legacy flat input without a `scope` field continues to work -- scope is inferred from `publisher_domain` presence.

## 2.148.0 — June 11, 2026 at 8:40 PM UTC

* Clarified and implemented campaign-level budget reductions for executed media buys: lowering a campaign budget now proportionally reduces live package budgets when needed, while explicit package amounts remain available through the campaign update operation.

## 2.147.0 — June 11, 2026 at 6:44 PM UTC

* Operating instructions now make their effect clear during storefront setup. The storefront panel keeps a plain-language "what this does" line on the active instructions — that these rules drive every buyer request to decide what it offers, prices, and rejects — instead of collapsing to a bare version/status once a version is live. Murph also states the effect and next step while showing the assembled draft, before asking to activate.
* Tidied the embedded sales-agent catalog view in the storefront panel so its create-product and add-signal actions read as a consistent, matched pair.
* Fixed media buy pacing and budget queries to exclude pending update proposals, ensuring calculations use only the current active version of each media buy.
* Fixed a bug where Murph would abandon the GAM inventory-source provisioning flow after the operator confirmed the service-account grant. Murph now calls the provisioning endpoint immediately on confirmation instead of stopping the flow.
* Murph's inventory selector widget now hands selections to chat without
* requiring a product name up front. After you click "Send selection to
* Murph," Murph proposes a sensible default name based on your publisher
* and selectors and asks you to confirm or rename before validating or
* creating the product. Empty selection now shows a clear next-step
* prompt instead of a disabled form.
* A storefront can no longer be opened for transactions when it has no products available, so buyers only see "Active" storefronts they can actually buy from. Storefronts whose product availability cannot yet be confirmed are unaffected.

## 2.145.0 — June 11, 2026 at 3:14 PM UTC

* Added creative collections for grouping saved creatives and source assets, plus a bulk creative update operation for previewing and applying saved creative changes with canonical click-through URL updates that refresh creative tracking metadata.
* Allowed buyers to connect multiple provider accounts for the same official adapter storefront, such as separate Snap business accounts.
* Reducing campaign budget and active media buy budget in the same request now works correctly. Previously the validation checked the campaign budget against current allocations before applying the media buy changes, causing atomic reduce requests to fail with INSUFFICIENT\_MEDIA\_BUDGET even when the new budgets were consistent.
* Fixed an inventory-selector search error that affected storefronts on SpringServe (and would have affected any adapter whose selectors carry null `name`, `path`, or `status`). Previously the response parser rejected the upstream payload as malformed; it now accepts the documented contract shape so SpringServe operators can browse cached selectors and author wholesale products.
* Storefront inventory-source views no longer surface an embedded sales agent connection that has no ad server attached (and was never provisioned) as a separate source. These incomplete connections previously rendered as a second "Embedded" card next to the real ad-server connection — reading as a confusing duplicate — and inflated the inventory-source count and health summary. Embedded connections that have an ad server attached continue to appear, including ones that are still provisioning or have failed, so genuine setup work stays visible.
* Improved advertiser setup guidance so agents research brand domains before asking follow-up questions and avoid unnecessary optimization-mode prompts.
* Sped up the buyer storefronts list (`GET /api/v2/buyer/storefronts`). Adapter-connection status is now resolved only for the storefronts on the requested page, so response time no longer grows with the total number of adapter storefronts a buyer has accumulated.
* Storefront cards now show the status chip in the footer next to the "Visit website" action, giving the brand name the full card width so longer titles no longer wrap awkwardly.

## 2.143.0 — June 11, 2026 at 3:28 AM UTC

* Expanded the buyer Murph workspace rail with campaign and reporting prompt actions alongside creative and asset context.
* Buyer MCP API calls now mirror additional REST routes and filters, including campaign product lookup, data delivery credential revalidation, and measurement record date/geography filters.
* Improved creative-session MCPUI review data so buyer agents can render source assets, processed renditions, and shared creative review widgets more consistently.
* Expanded the buyer Murph workspace rail with creative, audience, catalog, and event prompt areas for advertiser setup and iteration workflows.
* Prevented discovery product selections from reporting success when the request is bound to a different campaign discovery session.
* Fixed Murph customer switching during multi-customer admin conversations so scoped writes can recover from customer ambiguity.
* Hid storefront sandbox test runs from the buyer creative workspace so the rail starts with creative work and advertiser assets.
* Murph customer list tools now use server-side filters, larger default pages, and explicit pagination metadata for advertiser, campaign, and sales-agent audits. Buyer advertisers can also be filtered by linked partner account before pagination.

## 2.142.0 — June 10, 2026 at 10:26 PM UTC

* Added the reactivate-campaign endpoint to the buyer API reference and made it callable as the `reactivate_campaign` named operation. `POST /api/v2/buyer/campaigns/{campaignId}/reactivate` reactivates a paused campaign and cascades to its paused media buys, returning the per-media-buy outcome. Previously this endpoint existed but was undocumented and could not be invoked through the named-operation path.
* Added clickable asset URLs, copy actions, and a gallery view to buyer creative asset management.
* Made Murph's agent call trace control a compact footer icon instead of a full-width button below each message.
* Fixed formatted creative previews so they no longer reload the raw preview URL as a fallback.

## 2.141.0 — June 10, 2026 at 8:43 PM UTC

* Added an embedded sales agent inventory browser for searching, expanding, selecting ad-server selector hierarchies, and drafting wholesale products with observed ad sizes.
* The buyer storefront detail response (`GET /buyer/storefronts/:storefrontId`) now reports a single storefront-level connection status instead of a per-source `sources[]` array. Each storefront returns `connected` (ready to transact), `requiresCredentials` (the buyer must register credentials first), and `customerAccounts` (the buyer's registered accounts for the storefront, deduped across sources). Credentials are still registered against individual sources.
* Improved Murph creative generation workflows with connected creative-adapter discovery, richer draft/refine/finalize guidance, locked asset and rendition handling, creative workspace previews, and current default image generation models.
* Scoped the Murph creative workspace brand and asset views to the selected advertiser.

## 2.140.0 — June 10, 2026 at 5:48 PM UTC

* Storefront operators can now invoke ADCP protocol tools directly on connected seller agents via `POST /api/v2/storefront/agents/{agentId}/invoke`. Supported tools: `get_products`, `create_media_buy`, `update_media_buy`, `get_media_buys`, `get_media_buy_delivery`, `get_adcp_capabilities`. Use this to drive deal validation flows and test agent integrations end-to-end.

## 2.139.3 — June 10, 2026 at 4:30 PM UTC

* Fixed pacing period packages submitting a past start time when a period's start date has already begun. The package start time is now clamped to the current time, enabling same-day execution.
* Buyer agent lookup and media-buy creation now reject a storefront's underlying inventory-source agent. Buyers transact with the storefront, which routes to its sources; the source agents are not addressable directly.
* Product discovery now resolves inventory exclusively through storefronts. Buyers transact with the storefront, which routes to its underlying sources, instead of addressing those sources directly. Discovered products are attributed to the storefront that surfaced them.

## 2.139.1 — June 10, 2026 at 1:28 PM UTC

* Murph now surfaces the correct endpoints for browsing GAM ad units and placements when operators ask how to search inventory selectors on an ESA. Previously, `ask_about_storefront_capability` returned no guidance for selector search, causing 404s on incorrect paths.

## 2.139.0 — June 10, 2026 at 12:38 PM UTC

* Creative sessions now track derived asset renditions for locked product assets, including transparent cutouts and thumbnails, while preserving the original source asset.
* Murph can now compare uploaded or linked brand artifacts against current AAO brand.json state, upload logo images to AAO review, preview proposed updates, and publish confirmed brand.json updates to AAO for verified storefront operator domains.
* Fixed ESA connections not triggering initial reporting, pricing/availability, and signal coverage syncs after creation. These data streams now start automatically when a new embedded sales agent connection is provisioned.
* Fixed `GET /campaigns` returning 500 when any campaign in the list had an end date on or before its start date. The date-ordering validation is now applied only on create and update requests, not when reading persisted campaigns.
* Murph now gives tighter, more scannable replies during multi-step flows like campaign setup: it leads with the decision you need to make instead of re-stating context it already covered, and keeps each turn focused on one thing.
* Surface embedded sales agent creative-format discovery errors instead of returning an empty format catalog when discovery is unavailable.
* Embedded sales agent signal listing now surfaces upstream failures instead of silently returning an empty list. Previously any error while fetching signals was swallowed and shown as "no signals", which could make a populated signal catalog look empty. Genuine "not found / not wired" responses still degrade to an empty list.

## 2.138.0 — June 9, 2026 at 10:16 PM UTC

* Fixed an issue where pacing period dates on draft media buys could not be modified, even though draft buys have never been submitted to a publisher.
* Ask Murph's side panels now adapt to the window width. As the window narrows, the conversation rail collapses to a slim strip first, then the state rail — each expanding into a panel that floats over the conversation when opened, instead of squeezing it. Wide windows keep both rails docked side by side; narrow windows stack the panels into a single column.

## 2.137.0 — June 9, 2026 at 7:55 PM UTC

* Refreshed the buyer test-runs rail in Ask Murph to match the storefront sandbox-test layout: scan the run list with at-a-glance status icons, then click a run to drill into its full diagnostics — execution trace, agent calls, and a copyable diagnostic trace. Failed or blocked runs can be sent straight to the chat composer for help.
* Improved creative session planning so image, audio, and video adapters expose generation strategy, composition strategy, and native capability metadata, with cleaner evaluator selection for modality-specific creative review.
* Creative sessions can now carry locked brand assets such as logos from advertiser brand data or chat uploads through draft, refinement, preview, and finalization.
* Property list creation with large domain counts no longer intermittently times out when the AAO registry is slow. The registry lookup phase is now bounded to 45 seconds; when that limit is reached, domains are classified as unresolved (the same behaviour as when the registry is unavailable).
* Storefronts that cannot serve products due to a missing operating-instructions ruleset are now automatically paused and the operator is notified. Buyers see "This storefront is temporarily unavailable" instead of an internal configuration message.

## 2.136.0 — June 9, 2026 at 4:54 PM UTC

* Added a Murph diagnostics workspace for test runs, third-party agent debug calls, and account change history.
* Audio creative sessions now preserve requested AudioStack ad duration/language, allow ElevenLabs voiceover drafts without requiring a separate image-generation key, and keep draft preview links stable across API instances.
* Fixed external signals catalog probes so AdCP 3.0 sellers are not sent unsupported wholesale signals requests.
* Keep the Ask Murph chat composer focused after sending a message, so you can keep typing without clicking back into the input.
* Murph now treats staying in character as a hard rule. When a tool fails, a validation step errors, or the customer must supply inputs Murph doesn't hold, it states the limitation in Interchange terms and asks for what it needs instead of stepping back to describe its underlying model or deny being Murph.

## 2.135.0 — June 9, 2026 at 1:53 PM UTC

* Added a buyer creative iteration workflow with draft variant galleries, natural-language refinement, linked asset preservation, staged evaluator checks, creative previews for image/video/audio assets, and finalization into campaign creative manifests.
* Creative sessions now plan draft target formats and required manifest assets from a plain brief, can start AudioStack draft audio variants without raw adapter JSON, and treat fal.ai as the creative provider while using transformers such as FLUX for model-family selection.
* Buyer-stack sandbox test runs resolved by storefront name are now recorded against their storefront, so they appear in that storefront's test history instead of being saved without a storefront.
* Corrected the discovery selected-products response schema: the per-product price field is now documented as `bidPrice` (the value the API actually returns) instead of `cpm`. The wire response was always `bidPrice`; only the schema and generated reference were mislabeled.
* Murph now always replies with a clear message when it can't complete a request. Previously, if Murph ran out of tool steps mid-task (for example, while repeatedly probing for data that wasn't available), it could return a blank "no answer" response and the user had to ask again. Murph now makes a final pass to explain what it found and why it's stuck, falls back to a plain-language message if it still has nothing to say, and stops probing failed calls sooner so it spends its effort on a useful answer.
* Murph now offers publishers a faster path to going live. As soon as an ad server is connected, Murph can propose a set of run-of-site starter products — one per authorized site and creative size, with no targeting — that are sellable as-is as a non-guaranteed CPM auction, surfacing the ad server's pricing guidance, and frames targeted packages, curated bundles, and guaranteed deals as later steps to grow revenue rather than go-live requirements.
* Storefront sandbox test plans now show every test run for that storefront, scoped per storefront instead of per signed-in user. Operators on the same account now see each other's test runs, and a storefront's drawer no longer mixes in runs from other storefronts on the account.
* Murph can now retrieve storefront catalogue and embedded sales agent wholesale product lists through the storefront API tool.

## 2.134.0 — June 8, 2026 at 10:18 PM UTC

* Fixed BYOK creative-family storefronts so ElevenLabs and Veo expose usable audio and video creative formats.
* Fixed `PayloadTooLargeError` (413) on `get_products` webhook callbacks. Seller product catalogs can exceed the previous 64KB body-size cap; the limit is now 5MB for `get_products` and remains 64KB for all other task types.
* Fixed generated creative manifests so image, audio, video, text, and URL assets include ADCP-required asset type metadata.
* Fixed generated creative manifests so text and URL assets include required delivery metadata.
* Fixed an issue where extra creative assets (not declared in a publisher's format spec) were included in media buy submissions, causing publisher validators to reject the request.
* Fixed create\_media\_buy payloads for fixed-price CPM products to include an impressions count derived from budget and CPM rate.
* Removed unused incrementalityTestingEnabled field from advertiser measurement configuration.
* The storefront panel now surfaces sandbox buyer test-run diagnostics. Each run lists its status and a step-by-step execution trace, and you can drill into a run to see per-agent get\_products results — including the upstream request and response summary for each agent. When a run fails or is blocked, an "Add to chat" shortcut sends a prefilled prompt (the failed steps and any suggested next actions) into Murph chat so you can resolve it without retyping the diagnostics.
* When a seller rejects a media buy update because it falls outside the original quote envelope, the error is now logged with the specific field(s) that triggered the rejection and actionable recovery guidance.
* Publishers can now declare base template format IDs (e.g. `display_html`, `video_vast`) on their products and buyers' sized creatives (e.g. `display_300x250_html`, `video_vast_30s`) will be correctly matched and assigned. Previously only exact format ID matches were accepted.

## 2.133.0 — June 8, 2026 at 2:17 PM UTC

* Added webhook callbacks for adapter-hosted creative review status transitions.
* Add storefront adapter support for Gemini, OpenAI, FLUX, Veo, and ElevenLabs creative generation families.
* Added MCP endpoints for family-filtered creative generation and preview tools.
* Buyers now land on the Ask Murph chat experience when opening their home page, keeping the same URL. Accounts without Ask Murph enabled continue to see the existing buyer home.
* Fixed embedded sales agent (ESA) product authoring so validation failures and product lists are reported accurately. A failed product validation now surfaces the specific offending field(s) instead of an opaque error, and the product list no longer renders empty when the upstream response can't be read — it now reports a clear "couldn't load" error so a real fault isn't mistaken for "no products yet".
* Fixed Murph occasionally rendering its closing question merged into the last bullet of a list instead of as its own line.
* Media buy creative updates now send inline package creatives to sales agents that do not support creative library sync. For library-only sellers, creative sync failures now fail the update synchronously instead of continuing with local-to-seller creative state drift. Malformed creative format agent URLs are rejected before inline creative delivery.
* Storefront adapter OAuth metadata now points developers to the agentic-api adapter documentation.
* Added storefront API controls for inspecting modular inventory source setup state and updating non-secret module configuration.

## 2.132.0 — June 5, 2026 at 7:00 PM UTC

* Added a seller-side preview discovery endpoint so storefront owners can test how buyer agents respond to a brief before going live.
* Fixed Murph losing access to buyer write tools (create advertiser, create campaign) mid-conversation when the router classifies short affirmative messages ("yes create it", "go ahead") as knowledge-only. Buyer API tools now remain available for any turn that follows a turn where they were already successfully used.
* Fixed product validation during campaign execution blocking media buy creation when sales agents return non-deterministic product IDs across calls. Products are now trusted as valid until their expiration date once discovered, eliminating the re-query that caused spurious "product not found" errors.
* Creative manifests now accept `format_kind` (AdCP 3.1 canonical format kind, e.g. `image_carousel`) as an alternative to `format_id` when creating or updating a manifest. Also added `format_option_ref` to pin a manifest to a specific product format option via `capability_id`, and `industry_identifiers` to attach Ad-ID, ISCI, Clearcast clock, or IDcrea identifiers. All three fields are returned in manifest responses.
* Format spec lookups now correctly handle parameterized (template) format IDs such as `{id: "display_static", width: 300, height: 250}`. Dimension and duration parameters are applied as asset slot requirements in the resolved spec, and different parameterizations of the same template get distinct cache entries so validation results are accurate per variant.
* Exposed managed GAM advertiser search, ensure, and default selection operations through the storefront MCP API so sellers can complete buyer-routing advertiser setup from chat.
* Data Delivery Outputs now substitute date placeholders in object-store path prefixes. `{YYYY}`, `{MM}`, `{DD}`, and `{HH}` are filled from the delivery period start (UTC) and `{DATA_DELIVERY_TYPE}` from the Output's data type, so a prefix like `lld/{YYYY}/{MM}/{DD}/{HH}/{DATA_DELIVERY_TYPE}/` writes to `lld/2026/06/03/14/IMPRESSIONS/`. Previously these tokens were written literally.
* A `pathPrefix` that contains an unsupported placeholder (for example `{YYYYMMDD}` or `{yyyy}`) is now rejected when the Output is created or updated, instead of being silently written into the object key. Any text that is not a brace-delimited placeholder is still used verbatim.
* The format detail endpoint (`GET /formats/:agentUrl/:formatId`) now returns `capability_id` alongside `format_id`. Use this value in `build_creative` or `PackageRequest.capability_ids[]` to target a specific format option on a product.

## 2.131.0 — June 5, 2026 at 1:14 AM UTC

* Bumped the Storefront MCP AdCP SDK integration to include the latest task polling and authorization error behavior.
* Fixes an issue where storefront adapter media buys would fail after pod restarts when scoped product IDs couldn't be resolved to their product config.
* Enabled async completion webhooks for storefront inventory source product discovery.
* Fixed submitted product discovery polling so account-scoped inventory sources can return completed get\_products results.
* Improved third-party inventory discovery so async product lookups can register callbacks and complete reliably with AdCP 3.0 seller agents.
* Child customers now inherit alpha access over MCP when their parent organization is enrolled. Previously the MCP tool-listing and execution gates only matched a customer's own ID, so child accounts saw an empty tool list and "access denied" even when their parent was opted in — REST and the web app already honored this inheritance.
* Fixed media-buy product validation so account-scoped sales agents receive advertiser account context when products are revalidated before execution.
* Fixed `refresh_agent_capabilities` MCP tool surfacing a garbled error message when the remote agent is unreachable. The tool previously doubled the "Failed to refresh capabilities:" prefix; the message now surfaces cleanly.
* Fixed a crash on the storefront Intelligence tab where the page failed to load with "Something Went Wrong" for runs that were skipped or that listed matched products.
* Send campaign creatives inline when creating media buys so sellers without a creative library can transact from buyer workflows.
* Added a Dashboard view to Ask Murph for storefront operators. The sidebar now offers a "Dashboard" entry that swaps the chat column for a tabbed surface — Overview, Reporting, Activity, and Merchandising engine — without leaving Murph, while the conversation sidebar stays in place.
* Updated the AdCP SDK used by buyer and storefront integrations to 9.0.0-beta.24.

## 2.130.0 — June 4, 2026 at 6:05 PM UTC

* When connecting Google Ad Manager, Murph now explains what access Scope3 needs, what it will not do, and what the granted role allows, then asks for explicit consent before walking a publisher through granting access to their network.
* Fixed access token cookie expiry being set to 1 hour regardless of the token's actual lifetime. The cookie now expires when the JWT does, preventing unnecessary session interruptions for long-lived tokens.
* Wait for async product discovery results from third-party inventory sources before falling back or returning no products.
* Fixed credential rotation so stale credential secret references can be replaced when the existing secret cannot be updated.
* Fixed the assistant chat not scrolling to follow new messages when a conversation is started fresh. Auto-scroll now engages as soon as the first message is sent, keeping the latest reply and the "writing it up" indicator in view.
* OAuth token exchange and refresh now delegate to adapter-provided methods when available, enabling TikTok and other providers with non-standard OAuth flows. TikTok is now a refresh-supported provider.
* Flight date updates (start and end time) on active media buys no longer require seller pre-approval. The update is still dispatched to the seller via the normal ADCP flow.
* The assistant chat now keeps the latest message in view as you send and receive messages, automatically following the conversation. When you scroll up to read earlier messages it stays put instead of yanking you down, and a control lets you jump back to the latest. Auto-scrolling respects your reduced-motion preference.
* Multi-day delivery reports now produce correct per-day, per-package metrics in delivery reporting. Previously a report covering several days collapsed its package metrics onto a single day; reporting timeseries now attribute each day's spend and impressions to the correct date.
* Refreshed the storefront cards to a clean, consistent look. Every card is now the same light surface with a thin brand-color accent on top, so a directory of storefronts reads as one cohesive set instead of a patchwork of differently colored headers. Each logo sits on a tile chosen to contrast it — dark or colored logos on a clean white tile, light/knockout logos on a dark tile drawn from the brand's own colors (e.g. a white wordmark on the brand's signature color) — so logos never wash out. Whether a logo is light or dark is resolved once when the brand is looked up — from the `brand.json` `logos[].background` field, the logo's color tags (`light`/`dark`), or its filename — and persisted on the storefront, so cards render instantly with no per-card image processing.

## 2.129.0 — June 4, 2026 at 1:48 AM UTC

* Buyer storefront listings now include each storefront's coverage `regions` alongside `channels`, so buyers can see and filter the marketplace by region.

## 2.127.3 — June 3, 2026 at 10:55 PM UTC

* Fixed adapter storefront product discovery so returned products remain valid when executing media buys for the selected provider account.
* Fixed routed adapter storefront execution so scoped products discovered through adapter storefronts can be purchased without being rejected by repeat product validation.
* Allow adapter storefront sales agents to execute routed media buys without requiring legacy operator-auth flags.
* Fixed adapter storefront MCP calls so buyer-connected provider accounts are passed through to sales adapters.
* Fixed campaign execution so selected product budgets are constrained to the campaign's remaining media budget after fees.
* Fixed `GET /campaigns/:id` returning duplicate `mediaBuyRefs` entries and stale `optimizationGoals` when a media buy had both an ACTIVE and PENDING\_APPROVAL version due to SCD Type 2 versioning. The response now de-duplicates by `media_buy_id`, preferring the pending version which reflects the most recent buyer-requested state.
* Fixed routed campaign execution for adapter-backed storefronts so buys dispatch through the storefront adapter with delegated provider authorization.
* Prevented storefront-backed media buy status refresh from reporting spurious upstream agent URL errors.
* Fixed storefront `sync_accounts` dry-run responses so clients receive the expected structured result.
* Fixed third-party storefront inventory sources so buyer account sync and account-scoped product discovery use the submitted natural-key account instead of upstream account discovery.

## 2.127.1 — June 3, 2026 at 4:58 PM UTC

* Improved error propagation in the account-switch flow: internal errors now preserve their original cause for easier diagnosis, and creating a child account now correctly returns a 500 instead of an empty response when user-info retrieval fails after account creation.
* Database circuit-breaker errors now return HTTP 503 with a `Retry-After` header instead of HTTP 500, and no longer trigger spurious GitHub error reports.
* Fixed storefront cards on the Browse storefronts page briefly rendering in the default palette before swapping to each storefront's real branding. Cards now show a loading placeholder until branding resolves.

## 2.127.0 — June 3, 2026 at 4:38 PM UTC

* Connections are now accessible from Account Settings in the buyer UI. OAuth-capable providers no longer show a redundant bearer token option.
* Fixed product discovery for BYOK adapter storefronts (Snap, Meta, etc.) returning zero results. The buyer's connected provider credential is now correctly resolved and forwarded when discovering products across adapter storefronts.
* Storefronts backed by a third-party sales agent no longer require an operating-instructions ruleset to return products. When no ruleset is active, these storefronts now pass the sales agent's catalog through directly instead of returning a `composition_pending` error — matching the behavior already in place for embedded sales agents.
* Fixed TikTok OAuth authorization URL to use `app_id` parameter instead of `client_id`, resolving the "app\_id: value is required but missing" error when connecting TikTok from the buyer connections page.
* Ask Murph now lets you keep typing while a reply is still streaming. Follow-up messages you send mid-reply are queued and delivered one at a time as each turn finishes, so you no longer have to wait for an answer before lining up your next question. Queued messages show as pending bubbles and can be removed before they send.
* Storefront operators can now refresh a sales agent's cached capabilities themselves via `POST /api/v2/storefront/agents/{agentId}/capabilities/refresh` (also available through the storefront MCP). This previously required platform admin access. Use it when an agent changes what it advertises (for example, whether it requires operator credentials or which billing modes it supports) and the cached state hasn't caught up yet. Sellers can only refresh agents their own storefront owns.

## 2.126.0 — June 3, 2026 at 2:31 PM UTC

* Added compatibility handling for media buy delivery reporting webhooks that are sent without an ADCP task envelope.
* Adapter storefront inventory is now identified as ROUTED-only and rejected when used with DECISIONED campaigns.
* Added an account analysis MCP tool for adapter-backed storefronts, including structured findings, recommendations, and an interactive analysis viewer. The tool uses delegated storefront adapter connections for provider auth, and Spotify is available as a wired storefront adapter provider.
* Added `adapterProviderType` field to the buyer storefront list response, indicating the adapter platform (e.g. "meta", "tiktok") or null for non-adapter storefronts.
* Buyer storefront browse now filters by status, channel, and region server-side. `GET /api/v2/buyer/storefronts` accepts three new optional query params: `status` (`configuring` | `transacting` | `archived`), `channel` (an ADCP channel code such as `display`, `olv`, or `ctv`), and `region` (a region code such as `EMEA`, `NORAM`, or `APAC`), returning only matching storefronts. On the browse page, the status, channel, and region filters are now populated from known option sets and drive the query directly, so they render fully on first paint instead of appearing only after the storefront cards finish loading.
* Delivery webhooks now deduplicate on idempotency\_key, preventing duplicate processing when sellers retry delivery reports.
* Murph seller analytics now returns historical performance and strategy signals, and product composition can use recent storefront outcome history to tune built-in negotiation defaults.
* Added seller recommendation signals to Murph seller analytics.
* Products now surface `formatOptions` in discovery responses when the sales agent publishes AdCP 3.1 `format_options[]` declarations. Each entry carries a `format_option_id` that buyers can reference via `format_option_refs` in `create_media_buy` to select a specific format option.
* Added durable storefront adapter connections so server-side workflows can use delegated provider credentials without client-held tokens.
* AM-1287: Derived managed ad-server operational health from the upstream tenant status feed, and treated local provisioning state as lifecycle bookkeeping rather than request-readiness.
* Added Spotify as a supported expert-run adapter provider for Storefront configuration.
* Fixed adapter storefront discovery so connected adapter storefronts can be used from buyer-agent product discovery workflows.
* Added buyer-facing provider connections for official adapter storefronts, including browser handoff URLs for OAuth providers and bearer-token setup for direct adapter credentials.
* Documented the storefront source graph architecture, clarified the Storefront routing boundary, and exposed storefront-level routing metadata plus adapter OAuth discovery for expert-run adapter storefronts. Linked storefronts and embedded sales agents are private Chef sources, not Storefront routing modes.
* Expanded Murph seller analytics with buyer-level negotiation conversion, monthly seasonality signals, and richer guidance for storefront negotiation strategy.
* Fixed third-party sales-agent calls (get\_products, create\_media\_buy) failing with a spurious ADCP error. Activity capture is now best-effort: when a source has no entry in the shared agent registry, the activity is skipped rather than failing the underlying call.
* Fixed the adapter OAuth success page close button so it works under the deployed content security policy.
* Fixed adapter OAuth authorization so allowed localhost callback URLs can be used with providers that auto-register OAuth clients.
* Fixed a race condition in Ask Murph where clicking "New Chat" while a response was streaming would be overridden by the completing stream, leaving the user in the old conversation instead of starting fresh.
* Fixed buyer agent access to official adapter storefront connection management.
* Improved Buyer MCP tool discovery so agents can reliably find and use the API call tool after selecting an account context.
* Fixed carousel creatives being rejected during sync when the format spec declares only a repeatable group (no individual asset slots). The asset builder was incorrectly falling back to generic type-based keys (`image`, `image_2`, etc.) alongside the correct `cards` array, causing the pre-sync asset validator to flag those keys as unrecognized and block the request.
* Fixed a 500 (`Failed to browse products`) in product discovery when a sales agent returns a product card without a format id. The product-card projection now tolerates a missing `format_id` instead of throwing, matching the guarding already used elsewhere in the same path.
* Fixed list tables showing a contradictory "Page 1 of 0" pager when there were no results. The pagination footer is now hidden whenever a list is empty, across the campaign creatives page and all tables built on the shared entity table (storefront, proposals, advertisers, connections, discover supply, and others).
* Fixed storefront media buys so products backed by embedded sales agents can be bought and have creatives synced end to end.
* Fixed Storefront adapter OAuth authorization so allowed redirect URIs can be used reliably after server restarts or across multiple API pods.
* Improved storefront product pricing so audience signals do not incorrectly apply unrelated inventory rate card rules to premium packages.
* Fixed a budget error that blocked executing a campaign whose selected products carry no explicit per-product budget (for example a single discovered product executed directly). Such products now default to a share of the campaign's post-fee media budget rather than the fee-inclusive total, so they no longer overshoot the media budget and get rejected during execution.
* Product discovery is now resilient to a single sales agent returning a malformed response. Previously, one agent's unparseable products (for example an invalid format list) could fail the entire discovery request with a 500; now the offending agent is skipped and recorded, and the remaining agents' products are still returned.
* Updated the buyer storefront browse copy: renamed "Browse the Interchange" to "Browse storefronts" with the subtitle "Discover who sells on the Interchange." on both the home-page section and the full storefronts page.
* Renamed the embedded-sales-agent surface from "PSA" to "ESA" across the storefront API. Storefront REST routes move from `/api/v2/storefront/psa/...` to `/api/v2/storefront/esa/...`, the inventory-sync webhook moves from `/webhooks/psa-sync/...` to `/webhooks/esa-sync/...`, and the response/schema names (`PsaConnection`, `PsaTenantStatus`, `PsaSyncHistoryResponse`, etc.) are renamed to their `Esa...` equivalents. The unrelated Platform Services Agreement ("PSA") used in terms-of-service acceptance is unchanged.
* Fixed adapter storefront product discovery routing when existing storefront agent rows had stale MCP endpoints.
* Storefronts now compose third-party sales-agent inventory into their own branded catalog, alongside embedded sources. A connected third-party agent's products are warmed, offered to Chef composition as single-source products, and exposed pass-through — all routable on `create_media_buy`. If composition is briefly unavailable, the storefront still serves each source's own products rather than returning empty.
* Storefront MCP sessions now use the AdCP SDK platform handler at the existing `/storefront/:platformId/mcp` endpoint. Storefront discovery, buyer session binding, and config-derived capabilities are preserved. Mutating Storefront tools now advertise and enforce AdCP idempotency with a 24-hour replay window, SDK request/response validation is strict, and buyer-visible SDK tasks are persisted in Postgres for restart and cross-pod polling safety.
* Storefront source diagnostics now report per-source health. Each entry in a storefront's readiness `sourceDiagnostics` includes a `health` object — `status` (`healthy` / `degraded` / `unhealthy` / `unknown`), the last error message and code, and the last error / success / check timestamps — so operators can see when an upstream inventory source last responded and why a read degraded.

## 2.125.0 — May 30, 2026 at 6:45 PM UTC

* Added a Murph-guided sandbox buyer campaign test planning flow that checks storefront visibility, sandbox advertiser readiness, and the buyer-infrastructure steps Murph would run once server-issued approval tokens are available.
* Added buyer-level outcome and ask rollups to Murph seller analytics.
* Improved Murph document processing so uploaded files can be converted into structured facts, gaps, recommendations, next steps, and brand.json mapping candidates during offline processing.
* Added attributed booking and delivery outcome summaries to Murph seller analytics.
* Added an optional seller analytics panel to Murph responses so storefront operators can visualize recent pricing, composition, and refine activity.
* Improved storefront product composition guidance for price objections, packaging changes, and buyer-history negotiation context.
* Added storefront outcome attribution so seller analytics can connect product exposure to media-buy booking and delivery events.
* Add card-by-card authoring UI for image\_carousel creatives. The creative detail page now switches to a carousel editor when the format spec declares a repeatable\_group asset slot, letting buyers add, edit, reorder, and delete cards with image uploads and text fields.
* Fixed a bug where deleting a sales agent did not remove it from `service_token.active_adcp_agent_ids`. The cleanup query was using the numeric database id instead of the stable `agent_id` string, so deleted agents could remain referenced in service-token active agent arrays.
* Improved Murph document uploads by summarizing PDF contents, highlighting gaps and recommendations, separating next steps, and recording first-pass processing status for the storefront state rail.
* Added a Murph-operated sandbox test execution path for connected external sales-agent inventory sources.
* Added Murph guidance for planning a test campaign against a connected external sales agent before running any campaign execution steps.
* Improved Murph's storefront setup flow for registering and assessing external sales agent inventory sources.
* Added per-inventory-source diagnostics to storefront readiness and surfaced them in Murph's setup rail.
* Returned a clear client error when ADCP webhooks use an unsupported payload envelope.

## 2.124.0 — May 30, 2026 at 3:54 PM UTC

* Murph seller analytics now includes attributed booking and delivery outcome summaries. The `sellerAnalytics` payload adds a top-level `outcomes` object and per-run `outcome` details using last-touch product-overlap attribution.
* Murph seller analytics now includes buyer-level outcome and ask rollups, and booked budget is counted once per attributed media buy instead of being inferred from the latest event.
* Murph now surfaces storefront health blockers, including managed sales agent setup tasks, when operators start a storefront conversation.
* Added storefront composition pricing settings for value-based pricing facts, fallback auction pricing targets, Murph-authored structured pricing rules, composed-product pricing options, wholesale product pass-through, and negotiation analytics capture.
* Fixed operator domain setup incorrectly failing with "Domain is already registered to another organization." Multiple organizations can now share the same operator domain. Setting a shared domain no longer reassigns another organization's signup routing.
* Allowed storefront owners to test product discovery and Murph-run brief evals against their own configuring storefronts before opening them for transactions. Murph now offers candidate test briefs and runs pre-built, imagined, or pasted briefs through the same dry-run storefront eval path, and intelligence-run records include a user-facing explanation of why products were selected, priced, omitted, or rejected.
* Added buyer endpoints to poll and cancel media buy update proposals: GET /api/v2/buyer/update-proposals/:id and DELETE /api/v2/buyer/update-proposals/:id.
* Show all returned storefronts in Browse the Interchange, simplify the section description, require storefronts to pass marketplace review before appearing to buyers, and notify Slack when a storefront is ready for review.

## 2.123.0 — May 29, 2026 at 8:18 PM UTC

* Data Delivery is now discoverable from the buyer MCP. Added a Data Delivery section to the buyer skill documentation (concept model, field reference, Probe lifecycle, advertiser-vs-campaign scoping) so `ask_about_capability` can surface it, and registered a `revalidate_data_delivery_credential` operation that re-runs the destination Probe without resubmitting the credential. Also published a buyer guide for end-to-end setup across GCS, S3, and Azure Blob destinations.
* Added storefront API support for managed-sales-agent buyer advertiser routing, including GAM advertiser search, advertiser ensure, buyer mapping management, recent buyer visibility, and readiness checks for upstream Sales Agent setup blockers.
* Advertisers now have a primary currency. Campaign budget currency defaults to the advertiser's primary currency when not specified. Selected product pricing is rejected when it uses a currency that does not match the campaign budget currency.
* Aligned Storefront setup, inventory-source, and Merchandising Agent terminology across the v2 API descriptions, docs, and UI copy.
* When a media buy update requires seller approval (`requires_approval` mode), the campaign update endpoint now returns HTTP 202 with a `proposals` array instead of a blocking error. Each proposal entry includes `proposalId`, `mediaBuyId`, and `status: PENDING_SELLER_APPROVAL`. Updates that require `requires_proposal` mode continue to return an error until that flow is implemented.
* Clarified storefront readiness checks by separating required go-live checks from setup guidance and optional status checks.
* Closed multiple cross-tenant authorization gaps in the `/tools` route-handler surface (also reached via Murph `invoke_action`):
* `customer_get` and `customer_get_seats`: now reject requests for customers the caller is not authorized to view (matches existing MCP tool behavior).
* `customer_invitation_approve` / `resend` / `reject` / `cancel`: now verify the invitation belongs to a customer the caller can access before forwarding to the internal backend.
* `product_save` / `product_discover`: now scope writes and reads to the caller's customer for non-SuperAdmin callers; non-SuperAdmins can no longer pollute or read another customer's product catalog or create generic (null-customer) Scope3 products.
* `seat_details_get`: cross-tenant seat fetches by non-SuperAdmin callers now return a not-found error instead of leaking seat name, members, and connected agents.
* PSA storefronts now return their warmed catalog products when buyers call `get_products`, instead of blocking with a `composition_pending` error due to missing operating instructions.
* Fixed media buy delivery webhooks failing with `VALIDATION_ERROR` on the `status` field since the SDK 8.0.0 upgrade. The delivery notification the SDK passes to handlers contains only the inner report data, not the task-envelope `status` field that `GetMediaBuyDeliveryResponseSchema` now requires. The fix merges `status` from the webhook metadata before schema validation so sender payloads in the correct MCP format are accepted again.
* Non-admin users whose organization has an unaccepted Terms of Service now see a blocking modal with a "Notify your admins" button, instead of landing on a page where all API calls fail silently. If no admins exist on the account, the modal directs the user to [support@scope3.com](mailto:support@scope3.com).
* When a media buy update is blocked because the sales agent requires seller approval (rather than a self-serve flow), the API now returns a distinct `SELLER_APPROVAL_REQUIRED` error code instead of the generic `CAPABILITY_NOT_SUPPORTED`. The error message and recovery suggestions tell the buyer to have the seller approve or activate the buy before retrying.
* Surface Sales Agent cached product pricing guidance, forecast freshness, bookability, and managed sync-health drill-down in storefront discovery.

## 2.122.0 — May 28, 2026 at 1:56 PM UTC

* Added a storefront managed-sales-agent connection test action and secure credential-form deep links so publishers can re-check ad-server connectivity after setup or credential updates.
* Murph chat now supports dragging and dropping PDFs, images, and common document formats into the conversation.
* Added secure Slack handoff buttons for Murph ad-server credential setup so operators can enter SpringServe and FreeWheel credentials in Storefront instead of chat.
* Added `POST /campaigns/:campaignId/creatives/validate` for dry-run creative manifest validation. Calls the ADCP agent's `validate_input` tool and returns per-target results indicating pass, fail with slot-level violations, or unvalidatable (for nondeterministic formats).
* Allow shipping the same Data Delivery type (e.g., IMPRESSIONS) to multiple credentials on a single advertiser or campaign scope. The uniqueness rule on Data Delivery Output arrays is now `(dataDeliveryType, credentialName)` instead of `dataDeliveryType` alone — list one Output per destination to fan a type out to several buckets or warehouses.
* Fixed signup notifications failing to reach admins when a customer has no domain mapping configured. The system now automatically populates the customer domain and mapping table after the first signup for that customer, so subsequent signups resolve admins correctly without manual intervention.
* `image_carousel` manifest validation now enforces the `allowed_card_media_asset_types` constraint declared in the format specification. Submitting a card with a disallowed media type (e.g. a video card in an image-only carousel) now returns a `card_media_type_invalid` validation error instead of silently accepting the manifest.
* Murph can now read transcript text from supported Loom links and clearly reports when a Loom recording has no readable transcript available.
* Fixed Data Delivery transfers failing with "Anonymous caller does not have storage.objects.list access" by aligning the worker's `google-auth-library` version with the one bundled inside `@google-cloud/storage`. Impersonated credentials now attach correctly to the export-bucket read, so GCS, S3, and Azure deliveries can complete.
* Prevented Murph from confirming reports, learnings, or business profile writes unless the corresponding action completed, and corrected report confirmations to use the ticket ID returned by the filing action.
* Prevented Murph from self-disclosing as an underlying model or treating routine action confirmations as roleplay tests during active conversations.
* Improved Murph storefront setup guidance so next-step questions continue the setup flow instead of reworking agent personality suggestions.
* Kept Murph's storefront setup tools available throughout storefront setup conversations so operators can activate confirmed product-rule versions from chat.
* Fixed re-inviting users who were previously removed: admins can now successfully re-add users who had been removed from a customer or seat.
* Fixed signup blocking new domains: the CSP backend returns `showPsaBox` but the agentic API was reading `showTosBox`, causing all first-time signups from unregistered domains to be incorrectly blocked.
* Fixed brand name drift between `POST /storefront/resolve-brand` and the cached `storefront.brand_name` column. The endpoint now persists the resolved brand name and logo URL back to the caller's storefront row when the resolved domain matches their operator domain, so the Configuration view and the storefront state drawer no longer disagree. The drawer also falls back to the live resolution when the column is null. Also pointed the storefront gear icon at the Account tab instead of Configuration.
* `getFormatDetails` now discovers AdCP v2 canonical formats (`image_carousel`, `sponsored_placement`, `responsive_creative`, `agent_placement`) via static SDK definitions, and supplements format discovery with `get_adcp_capabilities → creative.supported_formats` for seller-declared formats.
* `url_type` values in URL assets now normalize to lowercase (`clickthrough`, `tracker_pixel`, `tracker_script`, `vast`) to match the AdCP spec. Uppercase inputs are still accepted and automatically lowercased.
* Improved managed sales agent sync status reporting so storefronts show derived refresh health, safe warnings, and retry progress instead of raw sync-run failures.
* Renamed the storefront's per-pass observability endpoints from `/chef-runs` to `/intelligence-runs`. The endpoints now sit under a "Storefront intelligence" framing that scales to future input → reasoning → output use cases beyond product composition (creative approval, media-buy approval, pricing, policy).
* `GET /v2/storefront/chef-runs` → `GET /v2/storefront/intelligence-runs`
* `GET /v2/storefront/chef-runs/:id` → `GET /v2/storefront/intelligence-runs/:id`
* `PUT /v2/storefront/chef-runs/:id/label` → `PUT /v2/storefront/intelligence-runs/:id/label`
* The wire field `ingredientsSnapshot` on each row is renamed to `inventorySnapshot` for consistency with the storefront's "inventory sources" vocabulary. The OpenAPI schemas `ChefRun*` / `LabelChefRunBody` are renamed to `IntelligenceRun*` / `LabelIntelligenceRunBody`.
* The readiness check id surfaced via `GET /v2/storefront/readiness` changes from `first_chef_run` to `first_intelligence_run`.
* Simplified the S3 Data Delivery Credential shape. The `config.auth` block (with `mode: ASSUME_ROLE`, `roleArn`, and `externalId`) has been removed — S3 credentials now require only `bucket` and `region`. Scope3 writes objects into the buyer's S3 bucket using a single shared IAM principal; grant `s3:PutObject` (and `s3:DeleteObject` for the Probe sweep) to that principal in your bucket policy under the Output path prefix.
* Carousel card validation now rejects `cta` values not in the format's declared `cta_values` list, returning a structured `card_cta_invalid` error with the allowed values. When `cta_values` is not declared, any CTA is accepted.

## 2.121.0 — May 27, 2026 at 1:18 PM UTC

* Added Data Delivery query support for impressions, clicks, MMP postbacks, and media-buy delivery report types. Outputs configured with these `dataDeliveryType` values now produce log-level exports against the corresponding signals tables. The `MEASUREMENT` data delivery type has been removed from the API — it was never wired and is not on the near-term roadmap; submitting it on an Output now returns a validation error.
* Add carousel authoring support: POST /campaigns/:id/creatives/create and the buyer MCP api\_call tool now accept a cards array for image\_carousel format creatives. Each card supports filename (for multipart file uploads) or url (for pre-hosted assets), plus optional headline, description, cta, and landing\_page\_url.

## 2.120.0 — May 27, 2026 at 3:23 AM UTC

* Storefronts now appear in buyer-side product discovery as first-class ADCP agents. Every storefront has a matching row in the ADCP agent registry so buyers can reach the storefront's curated product surface through the same discovery flow they already use for third-party agents. Existing storefronts are backfilled automatically.
* Pre-flight capability guard on campaign update now consumes the structured `available_actions[]` vocabulary from AdCP RFC #4480 (PR #4514), with fallback to the legacy `valid_actions[]` for sellers that pre-date the spec. Direction-of-change for budget and flight mutations is resolved per-buy (extend vs shorten, increase vs decrease), so mismatches surface before any downstream call. The runtime path additionally parses the structured `ACTION_NOT_ALLOWED` error so failure responses carry the typed `attempted_action`, `reason`, and `currently_available_actions` fields.

## 2.119.0 — May 26, 2026 at 9:47 PM UTC

* Added Azure Blob Storage as a Data Delivery destination. Buyers can now register a Data Delivery Credential with a container-scoped SAS token and a Data Delivery Output pointing at it; scheduled deliveries write JSONL files into the buyer's Azure container. The SAS expiry (`se=` claim) is parsed at credential submission and surfaced on the credential response as `expiresAt` so the credential can be rotated ahead of time.
* Creative manifests now accept carousel/multi-card creatives. The `image_carousel` canonical format is fully supported: the `cards` asset slot accepts an array of card objects (each with a required `media` image or video, plus optional `headline`, `description`, `cta`, and `landing_page_url`). Cardinality bounds from the format declaration are validated (min/max card count). Previously, repeatable-group slots were silently dropped during validation.
* Bump @adcp/sdk to 8.1.0-beta.13 and wire the beta.13 get\_products cache\_scope behavior through storefront MCP responses.
* Account-scoped composed products are partitioned from public products across brief and refine flows, and async ADCP response errors are surfaced as advisory errors without making synchronous seller errors non-fatal.
* Added `channels` field to buyer storefront list and detail responses, surfacing the ad channels each storefront supports (e.g. CTV, display, audio). `POST /api/v2/storefront/resolve-brand` now prefers iconographic logo variants (icon, mark, square) over wordmarks when selecting `logoUrl`, so storefront cards render a brand mark next to the brand name instead of duplicating it as a wordmark image.
* Fixed `apply_proposal` failing with "No discovery results cached" after Redis cache expiry. Proposals are now persisted to the database when discovered so they can be recovered even after the cache expires and ADCP re-discovery fails.
* Fixed campaign budget-mode pacing allocating incorrect package budgets when media buys were executed from separate discovery sessions. Each media buy's packages now receive the correct proportional share of its own product budget across periods.
* Fixed advertiser update so a single PUT can replace Data Delivery Credentials and Outputs together when the new Outputs point at new credentials. Previously, the request was rejected because the old credentials were archived before the Outputs that referenced them were cleared. Updates now upsert credentials first, replace Outputs, then archive credentials no longer referenced.
* Duplicating a creative now generates fresh tracking URLs for the new creative, so the click-through and impression tracker URLs are present immediately after duplication.
* Fixed a crash when setting per-buy pacing periods on campaigns where the media buy start\_time is stored as a text string rather than a Date object.
* Fixed platform-managed (PSA) storefronts not appearing in buyer storefront listings. Storefronts backed by Scope3-managed sales agents were invisible to buyers due to a query that required an agent ID - PSA sources have no agent ID by design. These storefronts now appear as connected with no credentials required.
* Fixed storefront not appearing in buyer discovery after going live. When a storefront was set to transacting, any inventory sources whose agents were still pending at registration time would remain stuck in a pending state and be excluded from buyer listings.
* Fixed a validation error when syncing HTML and text creatives to sales agents. Assets are now stamped with the required `asset_type` discriminator field before being submitted to the ADCP protocol.
* Accounts that inherit their organization's contract no longer have their own row, no longer prompt for ToS, and contract reads transparently walk to the organization. New `/api/v2/contract` response fields (`inheritedFromOrganization`, `organizationId`, `organizationName`) and new status values (`inherited_active`, `inherited_hidden`, `organization_contract_missing`). New `PATCH /api/v2/contract` lets organization admins toggle whether inheriting accounts can see contract details and rate cards. `POST /api/v2/accept-tos` returns 403 for accounts that inherit.
* The `.well-known` discovery endpoints (`/.well-known/jwks.json`, `/.well-known/brand.json`, `/.well-known/oauth-authorization-server`, `/.well-known/oauth-protected-resource`, `/.well-known/openid-configuration`) now return the same response on both `https://interchange.io` and `https://api.interchange.io`. Programmatic API and MCP endpoints remain at `https://api.interchange.io`.

## 2.117.0 — May 25, 2026 at 5:06 PM UTC

* Added per-storefront buyer instructions: notes + discount rules scoped by (operator\_domain, brand\_domain) and optionally filtered by country. Storefront operators manage rows via `GET/POST/PATCH/DELETE /v2/storefront/buyer-instructions`; the product-composition agent resolves matching rows at `get_products` time (most-specific notes ordered first, MAX discount across matches).
* Approving a pending media buy now forwards the stored request to the underlying source(s) and records the routing so subsequent `update_media_buy` / `get_media_buy_delivery` calls work end-to-end. When an operator decides `approved` on `POST /api/v2/storefront/media-buy-approvals/{mediaBuyId}/decide`, the service replays the buyer's create\_media\_buy payload, fans it out per source, persists the upstream media\_buy\_ids, and stamps `forwardedAt`. The response now includes per-source forward results so the operator UI can render partial failures. The decision itself is recorded regardless of forwarding outcome — partial or failed forwards are retryable separately. Direct-forward (`offersCampaignApproval=false`) and post-approval modes share a single `forwardMediaBuyToSources` helper.
* The product-composition agent now owns pricing arithmetic deterministically: each composed product's baseCpm, operator discount, and finalCpm are computed server-side from the selected bundles and signals plus any matched buyer instructions. Prompts to the model carry a precomputed price playbook and explicit guidance to vary channel mix and record any excluded bundles in the run rationale.
* Storefront agent hardening from review feedback: scope every storefront media-buy route to the buyer that opened it (cross-buyer leak fix on `get_media_buys` and friends), bind each per-storefront MCP session to its authenticating customer (refuse 403 on hijacked session ids), only stamp `forwarded_at` after every source completes (adds a `POST /api/v2/storefront/media-buy-approvals/:mediaBuyId/retry-forward` for the operator UI), and stamp a deterministic `idempotency_key` on each forwarded source call so retries dedupe upstream. Tightens chef pricing (clamp final CPM at zero, take the min CPM across multi-priced bundles, warn on dropped currency-mismatched signal addons) and trims a few storefront wire shapes (creative-review response is camelCase end-to-end, `get_adcp_capabilities` tucks the scope3 storefront block under `extensions.scope3`, list endpoints drop the fake pagination envelope when the service doesn't paginate yet).
* PSA-backed storefronts now honor operator-stored workflow flags for `offersCreativeReview` and `offersCampaignApproval`. Previously all three capability flags were force-locked on for any storefront with a PSA inventory source — operators could not opt their PSA storefront into pass-through review or pass-through approval even when that was what they wanted. `offersProductComposition` remains locked on (a PSA must surface composed products or it has nothing to sell), but the review and approval workflow flags now flow from `storefront_config.settings.capabilities` verbatim so operators can configure either queue-mode or pass-through per storefront.
* Adopted the AdCP SDK's typed response builders across the storefront MCP surface: `productsResponse`, `mediaBuyResponse`, `updateMediaBuyResponse`, `getMediaBuysResponse`, `deliveryResponse`, `syncAccountsResponse`, `syncCreativesResponse`, and `taskToolResponse`. Replaces hand-rolled `structuredContent` objects with builders whose `data` parameter is the canonical AdCP type — TypeScript now catches schema drift at compile time instead of at storyboard runtime. As a side effect, `sync_accounts` now returns proper `SyncAccountsSuccess.accounts[]` entries with `brand`, `operator`, `action`, and `status`; `create_media_buy` direct-forward returns a proper `CreateMediaBuySuccess` with `media_buy_id` and `packages`; `get_media_buy_delivery` returns the canonical `GetMediaBuyDeliveryResponse` with `reporting_period`, `aggregated_totals`, and `media_buy_deliveries`. Storyboard runner moves from 22-passing/18-failing to 25-passing/16-failing.
* Storefront operators can now inspect the product-composition agent's reasoning over time. Each `get_products` pass writes an internal compose-run record capturing the buyer scope it resolved against, the prompt it built, the raw and parsed LLM output, the matched buyer-instructions rows, and the products it persisted. Operators read these via `GET /v2/storefront/chef-runs` and `GET /v2/storefront/chef-runs/:id`; evaluators attach structured labels via `PUT /v2/storefront/chef-runs/:id/label`.
* Added per-storefront creative review endpoints. When a storefront takes over creative review from the underlying salesagent, buyer-submitted creatives land in a review queue that operators can browse and decide via `GET /api/v2/storefront/creative-reviews`, `GET /api/v2/storefront/creative-reviews/:creativeId`, and `POST /api/v2/storefront/creative-reviews/:creativeId/decide`. The decide endpoint accepts `approved` or `rejected`. Submissions are idempotent on `(creative_id, buyer_customer_id)` — a buyer resubmitting the same creative updates the stored payload without resetting a prior operator decision.
* Storefront `get_products` now honors AdCP `buying_mode` and the `refine[]` change-request array. `buying_mode: 'brief'` is the existing fresh-discovery path; `buying_mode: 'refine'` lets a buyer iterate on a previous response — entries with `scope: 'product'` reference an existing `product_id` and an action (`include` / `omit` / `more_like_this`, optionally with an `ask`), `scope: 'request'` adds whole-response asks, and `scope: 'proposal'` is acknowledged but not yet honored. Product identity is preserved across refines: `more_like_this` and `ask` modifications keep the existing `product_id` and update the recipe in place; `omit` drops the product from the response; `include` with no `ask` is a verbatim passthrough. The response includes a position-matched `refinement_applied` array. `buying_mode: 'wholesale'` returns `UNSUPPORTED_FEATURE` — storefronts are curated discovery surfaces, not raw catalogs.
* Storefronts now expose a per-storefront AdCP MCP endpoint at
* `/storefront/:platformId/mcp`. The tool surface is capability-filtered
* from the storefront's flags: `get_adcp_capabilities` is always available;
* `get_products`, `sync_creatives`, and `create_media_buy` are registered
* only when the matching storefront capability is enabled. Pass-through
* storefronts (`advertiseAsAgent === false`) and unknown platform IDs
* return 404. The endpoint accepts scope3 customer API key auth this
* round; product composition, creative review, and campaign approval
* handlers remain placeholders while their pipelines land.
* Storefront MCP surface (`/storefront/:platformId/mcp`) now exposes the full AdCP buyer tool set, not just `get_products`. New tools: `sync_accounts`, `sync_creatives`, `create_media_buy`, `update_media_buy`, `get_media_buys`, `get_media_buy_delivery`. Capability flags drive the implementation path, not whether a tool is exposed: `offersCreativeReview` and `offersCampaignApproval` switch between operator-managed queues and direct pass-through to the underlying sources. `create_media_buy` resolves each package's source from the composed product's stored implementation\_config and fans out per source. Subsequent calls to `update_media_buy`, `get_media_buys`, and `get_media_buy_delivery` read a new `storefront_media_buy_routes` table so they route per source automatically. `sync_accounts` registers buyers on every connected source and records the per-source upstream account id in `storefront_account_routes`.
* Added per-storefront media-buy approval queue endpoints. When a storefront opts into operator review of buyer-submitted media buys, buyer `create_media_buy` calls land in a pending queue and operators decide via the new REST surface: `GET /api/v2/storefront/media-buy-approvals` (defaults to pending; `?status=approved|rejected|revoked` to filter), `GET /api/v2/storefront/media-buy-approvals/:mediaBuyId` (single entry), and `POST /api/v2/storefront/media-buy-approvals/:mediaBuyId/decide` with body `{ status: 'approved' | 'rejected', reviewerNotes? }`. Decisions are recorded with the reviewing operator and timestamp; double-decide attempts are rejected. Re-submitting the same media\_buy\_id while pending is idempotent; re-submitting after a decision requires a fresh id.
* Added per-storefront operating instructions endpoints. Operators can author versioned markdown rules that the storefront's composition agent consumes when producing products: `GET /api/v2/storefront/operating-instructions`, `GET /api/v2/storefront/operating-instructions/active`, `GET /api/v2/storefront/operating-instructions/:version`, `POST /api/v2/storefront/operating-instructions` (creates a new version, never overwrites prior versions), and `POST /api/v2/storefront/operating-instructions/:version/activate` (swaps the storefront's active version). Versions are immutable and per-storefront monotone — creating a new version produces a clean cutover so composition output for the new rules is distinguishable from the prior generation.
* Storefront `get_products` responses now meet the AdCP v3 schema contract. Every product carries `publisher_properties` (derived from the storefront's platformId), `reporting_capabilities` (daily UTC reporting with the standard impressions+spend metrics and `date_range_support`), and pricing options now use the canonical `pricing_option_id` + `fixed_price` shape (not the previous `rate`/`is_fixed` pair). The response envelope itself includes the v3 canonical `status` field and echoes the buyer's request `context` back unchanged. `get_adcp_capabilities` accepts and echoes `context` as well. These changes move the AdCP storyboard runner from 3-passing/33-failing to 22-passing/18-failing on the same agent surface — the remaining failures are protocol-level error-code conformance (PRODUCT\_NOT\_FOUND, VERSION\_UNSUPPORTED, TERMS\_REJECTED, etc.) and response-shape work on sync\_accounts / sync\_creatives / create\_media\_buy envelopes.
* Storefront MCP tools now echo the AdCP `context` field on every response (success and error), reject unsupported `adcp_major_version` values with the canonical `VERSION_UNSUPPORTED` envelope, and validate `start_time` / `end_time` semantics on `create_media_buy` before forwarding (reversed dates and past start times return `INVALID_REQUEST` directly). Every tool's inputSchema now declares `context` + `adcp_major_version` so MCP doesn't strip them from incoming args. Fixed a column-name bug in the storefront-source resolver (`source_kind` → `execution_type`) that was hiding the inventory sources from sync\_creatives + sync\_accounts fan-out. Storyboard runner moves from 25-passing/16-failing to 34-passing/8-failing on the same agent surface — schema conformance is now table stakes; the remaining failures cluster around behavioral seller errors (TERMS\_REJECTED, accept-buy returns media\_buy\_id) and a single security\_baseline assertion.
* Simplified `sync_accounts` on the storefront MCP surface. For embedded storefronts the storefront is the buyer agent, so the call now echoes the submitted `account_ref`s back as acknowledged rather than fanning out to underlying sources. Advertiser provisioning on the source side is deferred to `create_media_buy` and owned by each source's `upstream_advertiser_mode` config — the storefront does not remember per-source upstream account ids. The `storefront_account_routes` table was dropped (it was never referenced by approved code paths). `storefront_media_buy_routes` (the routing for `update_media_buy` / `get_media_buys` / `get_media_buy_delivery`) is unchanged.

## 2.116.0 — May 22, 2026 at 8:19 PM UTC

* Creative manifest list now includes `target_format_ids` — additional format IDs a creative covers beyond its primary format. The campaign creative assets page shows which formats are already covered (alongside which are still missing) and allows assigning an existing creative to a missing format without re-uploading assets.
* Fixed `apply_proposal` returning "No discovery results cached" when the discovery cache had expired. It now automatically re-runs discovery to repopulate the cache before retrying, matching the existing recovery behavior in other discovery operations. Also extended the discovery cache TTL from 30 minutes to 4 hours.
* Fix format selector missing format IDs (e.g. banner\_728x90) that are declared on products but not returned by the ADCP creative agent's listFormats call.

## 2.115.0 — May 22, 2026 at 11:51 AM UTC

* Child customers can now view their contract from Account Settings → Contract,
* Billing & Invoices. Rate cards inherited from a parent customer are surfaced
* under an "Inherited rate cards" label — when the parent has opted to share
* them the rates appear, otherwise the section indicates that rates are
* inherited from the parent.
* Fixed a race condition where simultaneous storefront inventory source auto-activations (e.g. a source creation and an agent-activation hook firing at the same time) could fire duplicate activation events. The auto-activation UPDATE is now idempotent and only emits a log/audit event for the writer that actually transitions the row from PENDING to ACTIVE.
* Fixed a bug where package budget, pacing, and bid\_price updates were not sent to the SSP when updating an active media buy. The SSP would receive the existing values instead of the requested changes, leaving the media buy stuck in PENDING\_APPROVAL. Also added Sentry capture for ADCP sync failures that were previously only logged to GCP.
* Fixed inventory sources backed by OAUTH sales agents being auto-activated before the OAuth token exchange completed. Sources now stay PENDING until the agent has a stored credential reference; only NO\_AUTH sources skip that check.
* Fixed a bug where verifying one storefront's operator domain would incorrectly mark all of the customer's other storefronts as verified. The auto-verification backfill is now scoped to the specific storefront whose domain was just verified, so storefronts with different operator domains remain unverified until each is independently checked.
* Fixed a server-side request forgery vector in the storefront discover-agents flow. The server-side fetch of `https://{domain}/.well-known/adagents.json` no longer follows redirects, so a third-party host cannot bounce the request to an internal address and have the response surfaced through the discover-agents response.
* Fixed `POST /api/v2/storefront/resolve-brand` and `GET /api/v2/storefront/discover-agents` to return the standard response envelope (`{ data, error }`) on both success and failure. Previously these endpoints returned raw bodies on validation errors, breaking clients that rely on the consistent wire format used everywhere else in the v2 API.
* Hardened Stripe Connect onboarding callback tokens by binding each token to the specific Stripe account and adding a 15-minute expiry. Leaked or replayed callback URLs can no longer be used to mark onboarding complete or mint fresh onboarding redirects.

## 2.114.0 — May 21, 2026 at 8:00 PM UTC

* Added duplicate creative endpoint. POST /campaigns/:campaignId/creatives/:creativeId/duplicate creates a copy of an existing creative manifest (including all assets) with a "Copy of" prefix on the name.
* Add domain auto-join setting for customer orgs. Admins can enable allowDomainAutoJoin on their customer to let users with a matching verified domain email join immediately as members without requiring admin approval.
* Added S3 as a supported Data Delivery destination. Data Delivery Credentials and Outputs can now target a buyer-owned S3 bucket, with cross-account access via AWS STS AssumeRole. Buyers create an IAM role that trusts the Scope3 AWS principal (with an optional `externalId`) and reference it in `credential.config.auth.roleArn`. Probe validation and per-cadence object delivery use the assumed role; no long-lived AWS access keys are stored.
* **Operator note:** the Temporal worker pod must provide a base AWS identity that the SDK's default credential provider chain can read, so that `STS AssumeRole` calls can be made. Supported options: (a) GKE Workload Identity Federation → AWS via OIDC (`AssumeRoleWithWebIdentity`); (b) `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` env vars for a Scope3 IAM principal with `sts:AssumeRole` permission; (c) IAM Roles Anywhere. The buyer IAM role's trust policy must trust whichever principal we use. Without one of these, the first delivery will fail with `CredentialsProviderError`.
* `GET /api/v2/accounts/current` now includes `customerDomain` so callers can tell whether the current customer has a registered organization domain (required before enabling domain auto-join).
* Fixed inventory source status badges and Activate/Disable actions always showing the wrong state. The UI was comparing lowercase status strings against the API's uppercase values (`PENDING`, `ACTIVE`, `DISABLED`), causing health indicators to always appear as "Pending" and status-toggle requests to be rejected by the server.
* Fixed CORS rejection for requests from the `https://interchange.io` apex domain to the PSA storefront proxy endpoints. The previous allowlist regex required at least one subdomain, causing fetch requests from the PSA admin iframe to be blocked in production.
* Fixed a gap where toggling `transacting: true` on a storefront could bypass the readiness check if the request went through the MCP storefront tool surface or any other internal caller that did not pre-check readiness. The gate now runs inside `StorefrontService.update()` itself, so every path returns the same blocker list when required setup is incomplete.
* Murph conversations are now persisted and retrievable. Added two member-scoped endpoints — `GET /v2/murph/conversations` and `GET /v2/murph/conversations/:conversationUid` — and a shareable `/$customerId/murph/c/:conversationUid` route in the UI so the chat history survives page refresh and can be linked to a teammate.
* Add Murph proactive surfaces: a digest endpoint that summarizes unread notifications, personalized starter prompts driven by user state, an online/health indicator, and a closed-set `?askMurph=<intent>&entity=<entityRef>` deep-link convention with "Ask Murph about this" buttons on campaign, advertiser, and sales-agent detail pages. The digest is automatically folded into the orchestrator's first-turn context so Murph can answer "what changed?" without an extra round-trip.
* Storefronts now carry a `capabilities` block on the v2 response declaring which AdCP extensions the storefront advertises to buyers: `offersCreativeReview`, `offersCampaignApproval`, `offersProductComposition`. A derived `advertiseAsAgent` boolean tells callers whether the storefront should be addressed as an AdCP agent (vs. pass-through to the underlying inventory source). Embedded (PSA-backed) storefronts have all three capabilities locked on with `capabilitiesLocked: true`; third-party storefronts default all off (pass-through). The `PATCH /api/v2/storefront` body accepts a `capabilities` patch — locked storefronts reject writes that would turn any capability off.
* Buyer-facing surfaces now display the storefront's name as the seller identity instead of the underlying sales agent's name. The storefront IS the agent buyers see in this product — underlying sales agents (third-party AdCP agents and embedded managed agents) are internal routing detail, not separate seller identities. Product cards, the discovery `productCard` modal, media-buy sections, and proposal badges all read from `storefrontName` now. Discovery responses stamp `storefrontId` / `storefrontName` on every Proposal and persist them through cached rails so the seller label is reliable across both fresh discovery and saved discoveries that get replayed. Cached rails group by storefront instead of sales agent — products from multiple underlying agents that belong to the same storefront collapse into one rail.

## 2.113.0 — May 20, 2026 at 11:19 PM UTC

* Measurement sources now expose an `outcomeTypes` array field listing all record-level outcome type slugs the source produces. This enables correct linkage between multi-metric sources (e.g. video reports delivering impressions, clicks, and video quartile events) and their individual measurement records.
* Fixed the Creatives tab being blank when "All advertisers" is selected on the buyer home page. The tab now auto-selects the first available campaign and loads creatives correctly.
* Fixed seat-scoped API tokens being rejected with `ACCESS_DENIED` ("No user context available for seat permission check") when calling endpoints scoped to their assigned advertiser. The token's seat role was set during authentication but not propagated into the service-layer context used by seat access checks.
* Reporting data now persists additional AdCP delivery metrics when sales agents report them: conversion value, ROAS, new-to-brand rate, cost per acquisition, cost per click, reach unit, viewed seconds, attention seconds, attention score, engagements, follows, saves, and profile visits. Package-level breakdowns also persist delivery status, paused state, and is-final flags. Previously these fields were dropped during ingestion; they are now stored alongside existing impression, click, view, and conversion metrics.
* Replace the storefront `status` enum (`PENDING / ACTIVE / DISABLED`) with two simpler stored fields: `transacting` (boolean) and `archivedAt` (timestamp). The API now returns a derived, read-only `displayStatus` with one of three values — `configuring`, `transacting`, or `archived` — computed from those two fields. Clients toggle live/paused by setting `transacting: true | false` on `PUT /storefront`; archiving is now a single explicit operation at `POST /api/v2/storefront/archive` that sets `archivedAt` and forces `transacting = false`. Archived storefronts are read-only — every mutation against an archived storefront is rejected. Existing rows are migrated automatically (`status = 'ACTIVE'` → `transacting = true`; everything else → `transacting = false`).

## 2.112.0 — May 19, 2026 at 10:42 PM UTC

* Property list file uploads now return 202 Accepted immediately and process identifier resolution in the background. Poll the GET endpoint for status updates. Large uploads no longer risk load balancer timeouts.
* Users who request access to an existing organization now see "Your access request is pending approval" on the signup screen instead of the misleading "An invitation is required" message. We also post a Slack notification listing the org's admins (and page oncall when there are none) so requests don't sit unanswered when an org's only admins are stale or unreachable.
* Grouped the `logEvent` endpoint under the **Event Sources** section in the Buyer API reference, alongside `listEventSources` and `syncEventSources`, so all event-source-related endpoints appear together.
* Improved ad-product retrieval on campaigns:
* `mediaBuys[].products[]` on `GET /campaigns/:id` now include `productName` and `publisherName` so callers no longer need to reconstruct names from reporting CSVs or audit logs.
* `GET /campaigns/:id/products` is now the authoritative list of every ad product attached to a campaign. It sources from the campaign's media buys (joined with the local products cache) and folds in any discovery-staged products not yet executed. Each entry includes `productName`, `publisherName`, `salesAgentName`, pricing, and the media buys it lives on.
* `GET /campaigns/:id/products` now accepts a `mediaBuyId` query param (single or repeated) to narrow the response to specific buys, avoiding context-window truncation on campaigns with many products.
* Property lists now create a local `Property` row for every uploaded site domain that didn't already have one (same shape as the canonical web property creation path: `DISPLAY-WEB` channel, `AUTO_SYNC`, `BROWSER`). Previously, identifiers without a matching Property fell into `unresolvedIdentifiers` and were silently dropped from the list, so they didn't take effect at bid time. Buyer-submitted exclusion and inclusion lists now honor the full domain set.
* Reframed the **Add inventory source** chooser around what storefront operators actually know about their setup. Two side-by-side cards — "I don't have a sales agent" (Managed) and "I have my own sales agent" (BYO/AdCP) — replace the title-cased "Connect an ad server / Connect an agent / Link a storefront" rows. Federation moves into a quiet "Coming soon" rail below the cards so it stops competing for attention before it ships. Downstream forms are unchanged.

## 2.111.0 — May 19, 2026 at 2:40 PM UTC

* Added `POST /api/v2/identity-match/targeting`, returning the seller-keyed audience targeting configuration for every package available to the authenticated token. System tokens receive every active package; customer tokens receive packages they own as a buyer or host as a seller. An optional `after` ISO-8601 cursor switches the response to delta mode, returning only configs whose package or owning media-buy was updated/archived since that instant. `targetSegments` is audience-only — `audience_include` maps to `anyOf`, `audience_exclude` to `noneOf`.
* Allow attaching a clickthrough URL alongside uploaded creative assets on every format. Previously the Clickthrough URL field was hidden (and the slot rejected by the API) when the resolved format spec didn't declare a `click_url` / `clickthrough_url` / `landing_page` slot, forcing buyers to choose between files OR a click URL. The slot is now accepted universally and stored on the manifest; formats that declare it continue to render it in the AdCP payload.
* The ADCP property list resolve endpoint (`GET /lists/{listId}`) now supports pagination via `max_results` and `cursor` query parameters and returns a `pagination` object with `has_more`, `cursor`, and (on the first page) `total_count`. Defaults to 1000 identifiers per page; max 5000.
* Storefront demand contact now enforces a both-or-neither rule: name and email must be set together or both cleared. The operator UI has an explicit "Remove contact" action, and partial updates that would leave the pair half-set are rejected with a validation error.

## 2.110.0 — May 19, 2026 at 3:31 AM UTC

* Added a demand-contact name and email to the storefront configuration. Operators can curate the person who fields buyer demand signals (RFPs, prospective briefs, weekly digests); the fields are surfaced via `GET /api/v2/storefront` as `demandContactName` and `demandContactEmail`, and can be edited any time through `PUT /api/v2/storefront`. Pass `null` to clear either value.
* Fixed two ways a customer's operator domain could be incorrectly auto-verified:
* 1. **Parent-fallback ignored the child's own domain.** The CHILD-customer verification fallback was returning `verified` whenever the parent customer had any active member matching the parent's registered domain, regardless of whether the child's own `customerDomain` matched the parent's. As a result, a child customer parented under (e.g.) Scope3 could appear `verified` for an unrelated operator domain because Scope3 employees match `scope3.com`. The fallback now only applies when the child's `customerDomain` equals the parent's `customerDomain`.
* 2. **Approval rows were keyed only by customer.** Each `customer_domain_approval` row is now bound to the specific domain it was issued for (`approved_domain` column). Previously the read path returned `verified` whenever any approval row existed for a customer, even if the customer had since changed `customerDomain` to a different value than the one originally approved. Legacy rows without `approved_domain` are no longer trusted; customers who still qualify via an active member's email re-verify automatically on the next read, otherwise a SuperAdmin must re-attest under the current domain.

## 2.108.0 — May 18, 2026 at 10:48 PM UTC

* Creatives now support promoting a different asset to "primary" (the renderable source). Pass `primary_asset_id` on the update endpoint to demote the current primary and promote the target asset. Only IMAGE, VIDEO, AUDIO, HTML, and VAST assets may be set as primary.
* Pre-launch campaigns can now be edited freely. Start date and pacing periods may be modified after the original start date has passed, as long as the campaign has no live media buys (any non-draft, non-archived buy blocks the edit). Pacing periods also accept a budget or weight of `0` so a single week can be skipped without removing the period.
* Cleaned up the campaign creative assets page: the upload modal no longer auto-opens when a creative has unresolved HTML asset refs (the missing-assets banner now has an inline upload button instead), and the Native copy tab is always visible across both the create-creative flow and the upload-to-existing-creative modal with clear empty states when a format hasn't been picked or doesn't declare native slots.
* The single-creative upload paths on the campaign creative assets page (both create-creative and add-files-to-existing) now accept `.zip` archives. Dropped zips are expanded client-side into their constituent files before upload, matching the behavior of the bulk upload modal. Nested zips are extracted recursively, so standard HTML5 ad bundles work in all upload spots.
* Embedded managed sales agents now support **SpringServe** and **FreeWheel** in addition to Google Ad Manager.
* When connecting an ad server you can pick the adapter type and supply the appropriate credentials:
* **Google Ad Manager** — Scope3 provisions a per-customer service account; you grant it access in your GAM admin console and supply your numeric network code.
* **SpringServe** — log-in email + password (the salesagent caches a 2-hour token and refreshes it automatically). An API token is also accepted for testing.
* **FreeWheel** — Publisher API username + password (auto-refreshing OAuth2 password grant). A 7-day temporary access key is also accepted under the advanced section for testing.
* Publisher-supplied credentials are forwarded to the upstream salesagent tenant at provision time and **never persisted by Scope3**. Only non-secret display fields (login, environment, default advertiser/demand-partner id) are stored so the UI can render "connected as ..." after provisioning. Rotating credentials on a live tenant preserves all tenant state (products, principals, sync history) via the new `PUT /api/v2/storefront/inventory-sources/{sourceId}/adapter-config` endpoint.
* Fixed the storefront card editor so selecting "North America" no longer renders as "Namibia". The region group code now uses `NORAM` (matching the signals subsystem) to avoid colliding with the ISO 3166-1 alpha-2 country code `NA` (Namibia); existing storefronts that stored `NA` for the North America group are transparently migrated on read.
* Fixed media buy updates being silently dropped by sellers that dedupe on the ADCP idempotency key. The key for `update_media_buy` previously stayed constant across every edit of the same media buy, so a spec-compliant seller would replay the response of the first update for every subsequent one and the new budget/pacing/bid\_price/targeting changes never reached the seller's ad server. The key now incorporates a fingerprint of the request body, so distinct edits get distinct keys while retries of the same edit still de-duplicate as intended. The same fix is applied to cascade pause/resume and to package-level cancellations.
* Storefront now surfaces inventory-sync state from the managed sales agent: an active PSA shows a dedicated "Inventory sync" row in the source detail dialog (with a Retry button when failed), and the setup-tasks checklist shows a blocker task when inventory sync has failed and an informational row while the first sync is running. Closes #2549.
* When a managed sales agent adapter probe fails, the storefront UI now shows a specific next step driven by the upstream's structured `remediation` hint:
* **`vendor_enables_role`** — your account doesn't have the API role this operation requires; contact your SpringServe / FreeWheel rep to enable it.
* **`customer_rebinds_account`** — re-enter your username (or email) + password.
* **`customer_rotates_token`** — paste a fresh temporary access key or API token.
* The full upstream message and any `vendor_fault` block continue to be surfaced as supporting detail so support engineers see exactly what the ad server returned.
* Storefront inventory-sync state is now webhook-backed. The salesagent's `sync_run.completed` / `sync_run.failed` events land on a new agentic-api receiver (`POST /webhooks/psa-sync/:customerId/:tenantId`, HMAC-signed) and update a persisted `inventorySync` block on each PSA connection — visible to the UI directly via `PsaConnection.inventorySync`. The per-PSA `/status` poll cadence drops from 30s to 5 min as a safety net for missed deliveries; the dialog and setup-tasks panel read the persisted state so they reflect sync changes within seconds.
* Set `PSA_WEBHOOK_SECRET` (shared HMAC secret) and `PSA_WEBHOOK_CALLBACK_BASE_URL` (defaults to `BASE_URL`) to enable the webhook path. When unset, the receiver returns 503 and the polling fallback alone keeps the state fresh. Closes the V2 of #2549.
* The Connect Ad Server dialog now shows the right copy when GAM rejects a managed-sales-agent setup. Typos point at the network code, propagation delays show the soft "wait a few minutes" affordance, and an invalid service account auto-pages the operator instead of confusing the publisher. The PSA connection's `lastErrorCode` carries the new typed values (`ADAPTER_NETWORK_NOT_FOUND`, `ADAPTER_PERMISSION_DENIED`, `ADAPTER_INVALID_CREDENTIALS`, `ADAPTER_INVALID_CONFIG`, `ADAPTER_CONNECTION_FAILED`) so external API consumers can branch on the failure class instead of parsing the message.

## 2.107.0 — May 17, 2026 at 9:26 PM UTC

* `POST /api/v2/storefront/psa` is now atomic: it provisions the managed sales agent tenant upstream and writes the local connection row in a single transaction. The connection is either fully `active` on response or no row is persisted, eliminating the in-between `pending` / `failed` states that previously required client-side retry plumbing.
* Removed `POST /api/v2/storefront/psa/{psaId}/provision` and `POST /api/v2/storefront/inventory-sources/{sourceId}/provision` — they are no longer needed. Retries are clean re-POSTs of the original create request.
* Added `POST /api/v2/storefront/psa/{psaId}/reactivate` and `POST /api/v2/storefront/inventory-sources/{sourceId}/reactivate` to bring a deactivated tenant back online without re-running the create flow.
* If the salesagent rejects provision with `EXTERNAL_ORG_ID_CONFLICT` and returns the conflicting tenant id, the agentic-api now adopts that tenant into a fresh local row instead of erroring. Self-healing when the local DB lost a row but the upstream tenant survived (and friction-free in local dev when a dev wipes the agentic DB but not the salesagent's).
* Fixed click and impression tracker URLs being generated against `/clk` and `/imp` paths, which return 404 on the tracking endpoint. Tracker URLs now point at `/agentic/clk` and `/agentic/imp` to match the routes the tracking service exposes. New creatives created after this change will produce working tracker URLs; existing creatives need their tracker URLs backfilled separately.

## 2.106.0 — May 15, 2026 at 10:57 PM UTC

* Storefront compliance checks are now cached for 30 minutes per agent, so the inventory sources page no longer re-runs the full AAO compliance suite on every load. Each agent tile shows a Retry button next to the health label to force an immediate re-check when you need a fresh answer. Tiles also wait for the compliance result before reporting "Healthy", which fixes a transient mismatch where a failing agent could briefly read as healthy while the check was still in flight.
* Fixed operator-domain verification status flipping between "Verified" and "Pending verification" depending on who was viewing the storefront. Verification is now decided entirely server-side based on whether any active member of the customer has an email matching the registered domain (no longer restricted to ADMIN role), and the decision is persisted with an audit reason so the chip stays stable across viewers.
* Fixed a flickering "Approve GAM service-account access" row on the storefront inventory-sources setup checklist. The row previously reappeared on every refetch of the managed-sales-agent status feed even when the PSA was already healthy and serving — provisioning success itself proves GAM honored the service account, so the row no longer renders once the connection is active. Later revocations continue to surface via the existing sync-failure row.
* Fixed dynamic HTML5 creative previews showing broken images for Google Web Designer (GWD) banners. The asset-reference rewriter now recognizes the `source=` attribute used by `<gwd-image>` custom elements, and template auto-detection picks the HTML template whenever an HTML wrapper is uploaded alongside sibling images (previously the first image in the upload list won, leaving the creative classified as a static image).

## 2.105.0 — May 15, 2026 at 7:14 PM UTC

* Creative manifests now accept `text_assets` and `url_assets` keyed by AdCP format slot `asset_id`, so structured formats like native can carry headline, description, business name, disclosure, and landing page copy without uploading text files. The creative dashboard exposes a Native copy form per format spec.
* Added storefront reporting endpoint `GET /api/v2/storefront/reporting/metrics`. Returns delivery metrics for every media buy that the storefront's sales agent(s) are a party to, organized as advertiser → media buy → package. Supports `summary` and `timeseries` views, date-range filters (`startDate`/`endDate`/`days`), optional `inventorySourceId` filter, `download=true` for CSV export, and `demo=true` for synthetic data.
* Storefront Communications: the per-event email/Slack toggle table is now hidden until at least one notification destination (notification email or Slack webhook) has been saved. The table's toggles cannot fire without a saved destination, so showing it beforehand suggested controls that didn't yet work.
* Validation errors for enum-like fields (e.g. `geo_metros.system`, `geo_postal_areas.system`, campaign status) now list the accepted values in the error message ("must be one of: nielsen\_dma, uk\_itl1, ...") instead of returning a generic "Invalid input".
* Storefront Communications: when no notification channel is configured, the page now shows a quiet placeholder card ("Connect a channel above to choose which events trigger a notification.") in place of the per-event toggle table, matching the design.
* The storefront Team page now lists pending invitations alongside accepted members, with Resend and Cancel actions so admins can manage stuck invites without leaving the workspace.

## 2.104.2 — May 15, 2026 at 2:14 PM UTC

* Company domain now shows as verified immediately when an admin on the account has an email at that domain — no extra approval step required. Previously, new sellers signing up with their own work email saw "unverified" until they created or edited a storefront, which blocked the "Connect an agent" path.
* Fixed `Forbidden: identity_org_mismatch` when opening a managed sales agent admin UI for storefronts with multiple sales agents. The proxy now stamps `X-Identity-Org-Id` with the exact value the upstream tenant was registered with, instead of the unsuffixed customer id.
* When provisioning a managed sales agent fails, the storefront UI now keeps the "Connect an ad server" dialog open and surfaces the actual error inline (previously the dialog closed silently and the publisher was bounced back to an unchanged storefront page with no signal). Provisioning failures against the upstream salesagent also fire a high-priority ops alert to Sentry + Slack so the on-call team is paged immediately instead of waiting for a customer escalation. User-fixable failures (e.g. bad GAM credentials) still surface to the publisher inline but do not page the ops channel.

## 2.104.1 — May 15, 2026 at 7:38 AM UTC

* Fixed "Connect an ad server" tile in the Add inventory source modal being incorrectly disabled when a storefront already had a managed sales agent. Multiple managed sales agents per storefront are supported, and the tile is now always enabled.

## 2.104.0 — May 15, 2026 at 2:49 AM UTC

* Campaign `constraints` now accept AdCP-shaped targeting fields directly: `geo_countries`, `geo_countries_exclude`, `geo_regions`, `geo_regions_exclude`, `geo_metros`, `geo_metros_exclude`, `geo_postal_areas`, `geo_postal_areas_exclude`, `language`, `device_type`, `device_type_exclude`, and `device_platform`. When set on a campaign, these flow into every media-buy package's `targeting_overlay` — include lists intersect with package targeting, exclude lists union. The legacy `countries` field is accepted as a deprecated alias and normalized to `geo_countries`.
* Storefronts can now add multiple managed sales agents (e.g. one GAM network per brand) instead of being limited to one per customer. The managed-sales-agent REST surface is now id-keyed: `GET /api/v2/storefront/psa` returns an array, `POST /api/v2/storefront/psa` creates a new connection, and per-PSA actions live under `/api/v2/storefront/psa/{psaId}/...`. Existing managed sales agents continue to work without any data migration.
* Customer context selected via `customer_switch` now stays scoped across short breaks. The stored selection slides its expiry forward each time it's applied, so an actively-used customer scope persists until the user is idle for more than 24 hours.
* The storefront card is now operator-curated. The `GET /api/v2/storefront` response and `PUT /api/v2/storefront` request body accept five new fields — `membershipStatus` (`AAO_FOUNDING_MEMBER` / `AAO_MEMBER` / `NONE`), `regions` (ISO 3166-1 alpha-2 country codes and group codes like `GLOBAL` / `EMEA`), `description`, `channels` (ADCP channel codes), and `website` — so operators can tune what buyers see on Interchange without re-publishing brand.json. brand.json still seeds identity (name, logo, colors, description, website); these overlays let publishers fill in fields brand.json doesn't reliably carry.

## 2.103.0 — May 14, 2026 at 11:20 PM UTC

* Added `DELETE /api/v2/accounts/{customerId}` to hard-delete a child customer account. The caller must be an admin on the parent (or a Scope3 SuperAdmin) and cannot delete the customer they are currently scoped into. The endpoint refuses with 409 Conflict if the child still has linked resources, so existing accounts with data continue to require a deactivation flow.
* Discovered products are now grouped by storefront instead of by sales agent. Each product carries `storefrontId` and `storefrontName` reflecting the storefront it was discovered through. A single sales agent that backs inventory across multiple storefronts now appears under each storefront's group with its own slice of inventory, so buyers see inventory the way they configure it — one group per storefront they've connected to.
* Documented the `POST /advertisers/{advertiserId}/log-event` endpoint in the v2 OpenAPI spec for logging conversion and marketing events (ADCP log\_event spec).
* Fixed a 404 on the embedded storefront's "Create product" flow caused by app-level salesagent JSON APIs (e.g. `/api/formats/list?tenant_id=…`) not being routed by the storefront proxy. The proxy now also forwards `/storefront/psa/api/*` to upstream `/api/*`, resolving the tenant from the `tenant_id` query parameter for session validation. This unblocks the format/targeting widget and the downstream 500 on `products/add` that resulted from posting with empty targeting data.
* Fixed an issue where users signing in through enterprise SSO could be silently rejected when the WorkOS access token didn't carry an exact-match email claim. User lookup by email now falls back to a case-insensitive match so a casing skew between the identity provider and the user record no longer blocks first-time login; subsequent API calls additionally fall back to the WorkOS user id, and the auth middleware logs a warning that names exactly which claims the token did carry, so the failure mode is no longer invisible.
* Fixed an SSO sign-in failure where users with accumulated duplicate auth cookies (for example, a host-only `staging.interchange.io` cookie alongside the parent-domain `.staging.interchange.io` cookie) were silently bounced back to the login page. The browser was sending both cookies on the same request and the server was reading the stale one, so the freshly minted session was unusable. Auth cookie writes now emit clear directives for every historical (domain, path=/) variant before setting the fresh value, so affected users self-heal on their next successful sign-in.

## 2.102.0 — May 14, 2026 at 2:20 AM UTC

* Reworked the campaign creative assets page: replaced the creative dropdown with a server-paginated list view of all creatives for the campaign (search, multi-select with bulk delete, per-row quick edit and delete) and added a back link from the creative detail view. The list also auto-picks the first advertiser and campaign on landing so you see content immediately instead of empty filters.
* Bulk re-uploading creatives no longer creates duplicates. When a creative manifest with the same name already exists in a campaign, the create endpoint returns the existing manifest with `already_exists: true` instead of inserting a duplicate. If the request carried files, the response also includes `ignored_files` with the count that was dropped (use the update endpoint to add or replace assets on the existing manifest). The bulk upload UI surfaces this as a distinct "Already uploaded" row state with an "N files ignored" hint when applicable, so users can safely re-run a partial upload to finish what was missed. The pre-batch row label changed from "Queued" to "Waiting" to avoid implying a server-side queue.
* Fixed a bug where a user invited as admin to a customer they already had a default permission for was silently kept at their lower role. Accepting an invitation now upgrades the existing permission to the invited role (never downgrades).
* Fixed an MCP session bug where switching into another customer would silently revert to the user's home customer whenever the session was recreated on a different pod. Subsequent writes (e.g. campaign creation) now consistently land in the customer the caller switched into.
* Added a way for admins to invite specific people (vendors, contractors, new teammates) to their customer's existing Slack or Teams support channel without changing seat membership. Available via the new `POST /api/v2/customer/communication-channel/invite-users` endpoint and the "Invite people to the channel" form in both the admin support-channels section and the storefront Communications settings. Newly invited seat members are now also automatically added to the communication channel when one is provisioned. The communication-channel POST endpoints (set provider, resend invite, invite users) now require an `ADMIN` or `SUPER_ADMIN` customer role.
* MCP clients (Claude Code, Claude Desktop, mcp-remote) can now auto-discover OAuth on the `/mcp/*` endpoints. Previously, 401 responses from these endpoints did not advertise the OAuth Protected Resource metadata, so clients without a pre-configured API key had no way to initiate the OAuth flow. They now include a standards-compliant `WWW-Authenticate: Bearer` challenge pointing at `/.well-known/oauth-protected-resource`.
* `POST /api/v2/buyer/campaigns` now rejects with `ACCESS_DENIED` when the request's customer context does not match the advertiser's owning customer. Previously, unscoped SuperAdmin sessions could create a campaign tagged to their home customer while pointing at another customer's advertiser, producing cross-customer data that was invisible to the advertiser's actual customer.

## 2.101.0 — May 14, 2026 at 12:20 AM UTC

* Disconnecting an external ADCP agent now keeps the source visible in the inventory list as "Deactivated" (mirroring the managed-sales-agent lifecycle) instead of archiving it. The source detail dialog shows a single "Reconnect" action for a deactivated agent. Reconnecting a `NO_AUTH` agent no longer fails with a spurious "Cannot activate agent without authentication configured" validation error.
* Extend org-admin-on-parent access to a few remaining surfaces that still required a direct user\_permission row on the target customer. The MCP customer\_switch tool, the stateless MCP current-customer overlay, and the accept-tos endpoint now all honor admin permission on a parent customer, matching the behavior introduced for service-token creation.
* Fix unsupported MIME types on creative uploads being rejected as ECONNRESET (connection reset) instead of a clean 400 Validation Error.
* Fixed creative file uploads failing with "Unsupported file type: application/octet-stream" when clients (such as Safari or generic HTTP tools) do not set an explicit MIME type. The server now resolves the actual content type from the file extension and returns a proper 400 validation error instead of a 500 when the MIME type cannot be determined.
* PSA provision now returns 503 (instead of 500) when the per-customer service account exists but its Secret Manager key is not yet retrievable. This matches the existing 503 surface for the "SA missing" case and tells the storefront UI to retry rather than showing a generic server error.
* Map upstream salesagent Tenant Management API failures (network errors, 5xx responses, wire-shape drift) to 503 Service Unavailable instead of 500. The storefront UI can now show a "retry" state when the PSA backend is briefly unhealthy instead of a generic server error.
* Added a multipart upload endpoint for property lists (`POST /advertisers/:advertiserId/property-lists/upload`) that accepts xlsx or csv files up to 100,000 identifiers per request. Removes the need to batch large exclusion or inclusion lists through repeated JSON calls.
* Added a campaign-scoped visibility endpoint (`GET /campaigns/:campaignId/property-lists`) and an `includePropertyLists=true` query flag on `GET /campaigns/:campaignId`. Both return the property lists actually applied to a campaign via its media-buy packages, so callers can verify exclusion / inclusion state at a glance without traversing media buys manually.
* Tightened agent guidance on `create_property_list` and `update_property_list`: directs the agent to the upload endpoint for large lists, and requires a server-confirmed verification step (`list_property_lists` after create, `get_property_list` after update) so a write is never reported successful without ground-truth confirmation.
* Removed the one-agent-per-storefront limit. Storefronts can now connect as many `AGENT` inventory sources as they need; `MANAGED_SALES_AGENT` rows remain slot-exempt as before.
* Storefront homepage now renders real data instead of stubs:
* **Inventory source responses** include two new optional fields, `reportingType` and `reportingPollingCadence`, projected from the underlying agent registration. Use them to show how each agent reports delivery (`polling` / `webhook`) and its cadence (`hourly`, `daily`, etc.) without a follow-up query.
* **Storefront setup checklist** in the UI now covers operator-domain verification, brand-profile completeness, billing connection, per-source OAuth handshakes, and the GAM service-account grant — each with a deep-linked CTA.
* **Source tiles** populate the *Open work* column from `PsaTenantStatus` for managed sales agents, *Reporting* from the new agent fields, and append the endpoint host and GAM network code as identity chips.

## 2.100.0 — May 13, 2026 at 6:17 PM UTC

* Adds the Data Delivery Credential entity and the data plane that delivers configured Data Delivery Outputs.
* **Credentials**: Buyers can now register reusable destination credentials per advertiser via `dataDelivery.credentials[]` on `POST/PUT /api/v2/buyer/advertisers`. Each credential carries the auth target (e.g., the GCS bucket) and is validated asynchronously by a destination-specific Probe. New and updated credentials are returned with `status: "PENDING"` while the Probe runs; clients should poll `GET /api/v2/buyer/advertisers/:id` (or call the dedicated revalidate endpoint) to observe terminal `VALIDATED` or `FAILED` status. Use `POST /api/v2/buyer/advertisers/:id/data-delivery-credentials/:name/validate` to re-run the Probe after fixing destination-side permissions.
* **Outputs now reference credentials by name**: `dataDelivery.outputs[].deliveryConfig` no longer carries the `bucket` field. Each Output instead specifies `credentialName` (referencing a credential within the same advertiser) and only the per-subscription address (e.g., `pathPrefix` for object stores). The credential's `destinationType` must match `deliveryConfig.type`.
* **Delivery**: Configured Outputs now actually ship. A reconciliation workflow materializes Output rows into Temporal schedules, which fire a delivery workflow that exports the data to a staged GCS location and transfers it to the buyer's destination. Each delivery is recorded in `data_delivery_log`. v1 supports GCS only; S3, Azure Blob, Snowflake, and Databricks land additively.
* Fix API key creation failing for org admins on child customers. When an admin accessed a child customer via parent-child hierarchy, creating a customer-scoped service token returned "User does not have access to this customer" because the user has no direct UserPermission row on the child. The token is now created as an org-level token in this case, mirroring how SuperAdmin acting on another customer is handled.
* Fixed the Personal API keys page so SuperAdmins impersonating a specific user see only that user's keys, instead of every personal key at the customer. SuperAdmins scoped to a customer (without user impersonation) keep the admin view that lists all users' personal keys with the User column.
* PSA provision now returns `503 SERVICE_UNAVAILABLE` (instead of `400 VALIDATION_ERROR`) when the per-customer service account is still being provisioned. The condition is transient — clients should retry — and the new status code reflects that.
* Sign-in with Google and SSO now respect the email you type. The login form forwards the typed email as a login hint and asks Google to show its account chooser, so you sign in as the account you typed instead of silently being signed in as whichever Google account your browser already has cached.
* The discovery card modal on `/storefront` has been polished: title is now "Your storefront card" with subtitle "This is how you appear to buyers on Interchange.", the primary action reads "Edit card" in the brand-primary color, and the floating "Verified" chip has been removed. Card-body typography has been tightened to match the directory rendering.
* Fixed `update_media_buy` and campaign-update flows incorrectly rejecting updates on media buys with multiple version history rows with "Media buy has no products. Cannot validate creative formats." Creative format validation now resolves against the live version of the media buy.
* Storefronts now get a dedicated GCP service account per customer instead of sharing a single global account. Service accounts are automatically created when a new seller customer is provisioned, with keys stored securely in Google Secret Manager. A SuperAdmin backfill endpoint is available to provision service accounts for existing sellers.
* `update_campaign` accepts `pacingPeriods` on each `mediaBuys[]` entry. Use this to shape spend on one specific media buy (e.g. a heavy-up on a publisher with seasonal or event-driven inventory) without affecting the other media buys under the campaign. The per-buy schedule replaces the campaign-level `pacingPeriods` shape for that buy and uses the same `mode` + `periods[]` shape. On `DRAFT` / `PENDING_APPROVAL` buys, the schedule is persisted and used at execute time. On `ACTIVE` / `PAUSED` paced buys, strict appends are sent to the seller via `update_media_buy.new_packages` (requires the seller to advertise `add_packages` in `valid_actions`). Bootstrapping pacing onto an unpaced live media buy is rejected, create a new media buy instead. Campaign `GET` responses surface `pacingPeriods` on each media buy with resolved budgets.
* Fixed campaign-level `pacingPeriods` cascades in `budget` mode: when appending a new period to a campaign with multiple paced media buys, each period's budget is now split across the buys proportionally to each buy's share of total budget. Previously each buy treated the period budget as its own, multiplying total spend by the number of paced buys.
* Managed sales agent actions (provision, launch, test connection, refresh, deactivate, status, ad-server config) are now exposed under the unified `/api/v2/storefront/inventory-sources/:sourceId/...` surface in addition to the legacy `/api/v2/storefront/psa/...` routes. New clients should target the inventory-sources path; the legacy `/psa/...` surface stays for one release while existing UIs migrate.
* The managed sales agent now surfaces through `/api/v2/storefront/inventory-sources` alongside external agents, and `executionType` values move to UPPER\_CASE: existing `'agent'` becomes `'AGENT'` and the new managed-sales-agent value is `'MANAGED_SALES_AGENT'`. Inventory-source responses include an embedded `managedSa` block (provisioning status, tenant id, ad-server config) when the source is managed.
* **Breaking change**: clients reading or writing `executionType` must use the new UPPER\_CASE values. Existing rows are migrated in place (no action required for stored data). The change aligns `executionType` with the other UPPER\_CASE wire enums on the storefront surface (`API_KEY`, `MCP`, `SALES`, etc.).
* Existing `/api/v2/storefront/psa/...` endpoints continue to work unchanged; subsequent releases will move actions under the inventory-sources surface.
* Disconnecting an inventory source from a storefront now archives the row instead of hard-deleting it, preserving the prior agent binding, original creation time, and audit-trail context. Archived rows are filtered from all list/lookup endpoints, and the same `source_id` can now be reconnected after disconnection.
* **Breaking:** the `status` field on inventory source responses now returns UPPERCASE values (`PENDING`, `ACTIVE`, `DISABLED`) instead of lowercase. This aligns with every other status field on the API (storefront, agent, media buy). Update any client code that compared `source.status` against lowercase strings. The DB column is also a real Postgres ENUM so dirty values can't be written through raw SQL.
* Storefronts can now federate with each other through "Link a storefront" — a buyer storefront asks a seller storefront to authorize surfacing the seller's inventory. Once the seller approves, buyer traffic can fan out through the seller's underlying agents and ad servers. New REST endpoints under `/api/v2/storefront/links` (buyer: create / cancel; seller: approve / reject / cancel), plus `/api/v2/storefront/storefronts/search` backing the "Link a storefront" picker. The link state lives inline on the buyer's `inventory_source` row — no separate sidecar — and the seller has permission to update the `link_*` fields when responding. The link is an authorization handshake only; economic terms (revenue share, scope, exclusivity) are negotiated per-transaction in `get_products` / `create_media_buy`, never at link time.
* The `/storefront` page now lives inside a two-tab shell: **Inventory sources** (the existing unified registry from Path B PR4) and **Settings**. A page-level header above the tabs surfaces the storefront identity (brand name + handle + "View storefront card" button), and a setup banner tracks the three preconditions to go live — Discovery card (resolved from `brand.json`), Inventory source (≥1 connected), and Billing (Stripe Connect). Each banner chip deep-links to the right surface.
* The Settings tab covers State (pause/resume), Identity (operator domain + brand.json status), API access (published MCP endpoint), and Billing (deep-linked to the existing `/storefront-billing` flow). Visibility, People, Channels, Locale, and Danger sections render as labelled placeholders until their backend wiring lands.
* The discovery card modal reads exclusively from the publisher's `brand.json` — if it doesn't resolve, the modal prompts the publisher to register at agenticadvertising.org (free) rather than offering a manual edit fallback. brand.json is the single source of truth for the discovery card.
* The Pause / Resume button in storefront settings is now wired to the API. Pause shows a confirmation dialog since it stops buyer agents from receiving responses to new briefs; resume goes through readiness checks so the same gates that block first-time go-live also block re-activation.

## 2.99.0 — May 11, 2026 at 8:54 PM UTC

* Add bulk creative upload to the campaign creative assets page. Drop a folder, multi-select files, or a zip and the UI groups them into proposed creatives (one per subfolder, one per loose file, with zips auto-extracted), lets you edit names and remove rows, then uploads them in parallel with per-row progress and retry-failed support.
* Fixed `media_product_list` returning `INTERNAL_ERROR` when an unknown `agent_id` is passed. The tool now returns a proper `NOT_FOUND` error instead.
* Password reset now forwards the Firebase `tenantId` from the reset-email URL to the backend, fixing `INVALID_CODE` errors for multi-tenant users.
* `get_campaign` now returns a `performance` snapshot for each media buy with `impressions`, `spend`, `clicks`, `views`, `completedViews`, `conversions`, `leads`, and `lastUpdated`. The snapshot is refreshed synchronously when sellers push webhook deliveries or when on-demand seller calls fetch fresh data — it represents the latest cumulative totals, not a billing-stable timeseries. For billing-stable daily metrics, continue to use the reporting endpoint.

## 2.98.0 — May 10, 2026 at 3:18 PM UTC

* Removed the unused `executionConfig` field from `POST/PUT /api/v2/storefront/inventory-sources`. The field was an opaque JSONB pass-through with no consumers; per-execution-type configuration will land as typed fields per integration type when needed. Requests that include `executionConfig` continue to succeed — the field is silently ignored at the schema boundary, matching today's behavior where it was nulled at the service layer.

## 2.97.1 — May 9, 2026 at 12:05 AM UTC

* Storefront Go Live checklist now shows agent connectivity/compliance status and hides the Prebid Sales Agent check when irrelevant.

## 2.96.0 — May 8, 2026 at 6:34 PM UTC

* Fixed a 500 error on `GET /api/v2/buyer/campaigns/:id/products` for campaigns that have an associated discovery session.
* Password reset links no longer auto-verify on page load. Users now click a "Continue to reset password" button before the reset code is checked against the backend. This prevents email security scanners (Microsoft Defender Safe Links, Mimecast, Proofpoint, etc.) from pre-fetching the link and causing the user to see an "expired link" error when they click through. Mirrors the existing signup email verification flow.

## 2.95.1 — May 8, 2026 at 3:46 AM UTC

* Clarified the Stripe billing copy on the storefront onboarding flow and "Go live" panel to better describe Scope3's role in consolidated payment processing when sellers opt in or out of Stripe Connect.

## 2.95.0 — May 8, 2026 at 2:13 AM UTC

* Made storefront billing setup always optional and aligned the buy-side `sync_accounts` payload with campaign type and seller billing state.
* **Seller (storefront):**
* `billing_setup` readiness check now starts as **optional** for new storefronts. It flips to **required (blocker)** automatically once a connected agent's capabilities advertise `agent` in `accounts.supported_billing` — that's the buyer-side toggle that asks Scope3 to clear payments, so Stripe Connect becomes mandatory before go-live.
* When billing is optional and Stripe is unconfigured the readiness check returns `status: optional` with description copy warning the seller their sales agent is limited to external agreements with buyers (Scope3 will not clear payments; seller must bill the buyer directly).
* When billing is required (some agent supports `agent` billing) the readiness check returns `status: missing`/`partial` with `isBlocker: true` and explains why.
* The storefront onboarding UI consumes the readiness check directly — the "Set up billing" step's required/optional label and copy track the server.
* **Buyer (media buy execution):**
* On every media buy execution, the `billing` field sent to `sync_accounts` is now resolved per buy:
* * `ROUTED` campaigns always send `billing: operator`.
* * `DECISIONED` campaigns against a Scope3-hosted seller without Stripe Connect are forced to `billing: operator` and an internal `no_seller_billing` flag is logged for ops; the seller's billing status is never echoed back to the buyer.
* * `DECISIONED` campaigns against a seller with billing honor the buyer's choice (`agent` or `operator`) when supplied via `executeMediaBuy` options. When the buyer doesn't specify, the default is `agent` (Scope3 clears) — the happy path on DECISIONED campaigns.

## 2.94.0 — May 7, 2026 at 7:01 PM UTC

* Storefront agent picker (`GET /storefront/discover-agents`) now only surfaces agents that are actually present in the canonical AAO agent registry. Agents that an operator self-claimed in their AAO operator profile but never registered are filtered out, so the modal can no longer offer agents that the connect call would reject.
* The connect-time AAO registry gate on `POST /storefront/inventory-sources` now applies uniformly to every caller — the SuperAdmin bypass and the `complianceBypassed` response field have been removed. Failing or pending AAO compliance still does not block connecting an agent (going-live continues to be gated by storefront readiness).
* Buyer storefronts and product discovery now line up around storefront-level visibility:
* `GET /api/v2/buyer/storefronts` accepts a `visibility` query parameter. The default `visibility=public` continues to return ACTIVE storefronts available to any buyer; `visibility=private` returns ALL storefronts (ACTIVE, PENDING, DISABLED) owned by customers in the caller's parent org. Buyers can set up credentials, link advertiser accounts, and discover products against any of their parent org's storefronts regardless of lifecycle state. List and detail responses now include a `status` field on each storefront.
* `GET /api/v2/buyer/storefronts/{storefrontId}` no longer 404s when an ACTIVE storefront has no active inventory source — it returns the storefront record with an empty `sources[]` array. Previously the detail endpoint required at least one wired-up source; that requirement only made sense when the list endpoint hid those rows, which is no longer the case.
* `POST /api/v2/buyer/discovery/discover-products` and `GET /api/v2/buyer/discovery/{discoveryId}/discover-products` now expose a storefront-level filter and **no longer accept** `salesAgentIds` / `salesAgentNames`. Use `storefrontIds` (integer array, IDs from `list_storefronts`) and `storefrontNames` (string array, case-insensitive substring) instead. An empty array on the request is treated the same as omitting the field — both mean "no request-level filter," and the campaign-level pin is used as the fallback when a `campaignId` is also provided.
* Campaigns can be **pinned** to a set of storefronts. `create_campaign` and `update_campaign` accept a new `storefrontIds` field. When set, every `discover_products` run for that campaign auto-applies the pinned filter — buyers don't need to resend it on each call. Pass an empty array on `update_campaign` to clear the pin. On the campaign response (`get_campaign`, `list_campaigns`, `create_campaign`, `update_campaign`) the pin is surfaced as a hydrated `storefronts` array — each entry has the storefront `id`, `platformId`, and `name` so the response is renderable without a follow-up lookup.
* The `CUSTOMER_SCOPE_REQUIRED` error from `api_call` now includes the user's available customers (id + company) and a directive suggestion in its structured payload, so agents can call `customer_switch` directly without first calling `customer_list`.
* Reporting endpoint cleanup:
* "All time" reporting (`days=0`) now returns the actual range of available data (first impression to today) instead of a hardcoded `2020-01-01` placeholder. The MCP reporting widget initializes from the requested range instead of always defaulting to the last 7 days.
* Removed the `breakdown` query parameter from `GET /api/v2/buyer/reporting/metrics`. It was a UI-only hint with no effect on the returned data; agents no longer have to ask the user a redundant "how do you want it broken down?" question. The MCP reporting widget's chart group-by dropdown still works interactively.
* CSV exports now round derived metrics (`Spend`, `eCPM`, `CPC`, `CTR`, `Completion Rate`) to at most 4 decimal places, eliminating JS floating-point artifacts like `50.00000000000001`.
* Fixed `/auth/sign-up` returning a misleading "Password is too weak" message when the failure was actually a backend validation error or other unrelated issue. The catch block now matches the structured WorkOS `password_strength_error` code instead of the substring "password" appearing anywhere in the error body.

## 2.93.1 — May 7, 2026 at 12:58 PM UTC

* Fixed ADCP webhook endpoint returning HTTP 500 when a sender's HMAC signature was invalid. Signature verification failures from the SDK now return HTTP 401 with `UNAUTHORIZED` instead of `INTERNAL_ERROR`. Added a fallback verification path that accepts the legacy raw `ADCP_WEBHOOK_SECRET` so sellers provisioned before the per-agent key derivation rolled out can keep delivering webhooks while their stored credentials are rotated.

## 2.93.0 — May 7, 2026 at 12:07 AM UTC

* Added managed Prebid Sales Agent (PSA) provisioning for storefronts. New endpoints under `/api/v2/storefront/psa` accept a GAM network code, expose the shared service-account email a publisher must grant access to, and provision a per-storefront PSA tenant against the upstream salesagent Tenant Management API. A new `psa_connection` readiness check appears in `/api/v2/storefront/readiness`. Provisioning, test-connection, and deactivation flows are end-to-end when `SALESAGENT_TENANT_API_URL` and `SALESAGENT_TENANT_API_KEY` are configured; without them the endpoints return 503 with a clear "not configured" message.
* Add buyer-advertiser routing rules to managed sales agent storefronts. Publishers can now map specific `(operator, brand_house, brand_id)` triples to dedicated GAM advertisers and see which buyers in recent traffic are still falling back to the tenant default. New REST endpoints under `/api/v2/storefront/psa`:
* `GET /mappings` — list routing rules
* `POST /mappings` — create a rule
* `PATCH /mappings/{id}` — update a rule
* `DELETE /mappings/{id}` — delete a rule
* `GET /recent-buyers` — distinct buyer triples seen in recent traffic, with the precedence step that won the resolution chain
* The storefront homepage gains a "Buyer routing" panel that surfaces both lists side-by-side, with a "Pin to rule" CTA on recent buyers that pre-fills the create dialog.
* Two storefront onboarding cleanups:
* **Sync state moves out of the agent card** into the dedicated `Importing your inventory` panel below. The card row now shows just operational metrics (workflows, products, packages, creatives) without sync controls squeezed in. The sync panel always renders when the tenant is active and adapts its title to state: `Inventory` (synced + non-empty), `Inventory sync needs attention` (synced + empty), or `Importing your inventory` (running). Refresh button + view-sync-details deep-link live in the panel header.
* **Setup tasks panel now filters out platform-managed publisher items** the upstream emits but the publisher can't act on in embedded mode (`ad_server_connected`, `tenant_name`, `tenant_cname`, `sso_configuration`, `multiple_currencies`, `currency_limits`, `gemini_api_key`, `slack_integration`, `signals_agent`). Stopgap until the sales agent suppresses these in `setup_tasks` for `is_embedded=true` tenants. Visible items now match what the publisher can actually do — products, principals, creative guidelines, naming conventions, etc.
* Hand buyer-advertiser routing back to the sales agent. The Storefront-side `Buyer routing` panel + create/edit dialog and their REST endpoints (`GET/POST/PATCH/DELETE /api/v2/storefront/psa/mappings`, `GET /api/v2/storefront/psa/recent-buyers`) are removed. The data lives in the sales agent and so does the management UI — publishers manage routing rules from inside the iframe's settings/advertisers surface. Storefront keeps the default-advertiser fallback (the one piece publishers commit to early during onboarding); per-buyer mapping work moves entirely upstream.
* Inventory sync visibility on the storefront homepage is now honest about empty syncs:
* **Item count totaled on the agent card.** "Last synced: just now · 0 items" tells the publisher at a glance when something went wrong, instead of "synced just now" implying success.
* **Sync progress panel keeps rendering** when sync completed but a stream imported 0 items (the "synced but empty" state). Title flips to "Inventory sync needs attention" with a warning explaining common causes and a `View sync details →` button that deep-links into the sales agent's inventory page for per-stream run history and re-trigger.
* **Per-stream errors surface inline** with a red message under the stream name when the upstream reports an error string.
* Storefront onboarding polish from the ad-ops audit:
* **Properties panel**: redesigned around two big counters (registered + authorized for the chosen agent) with a single gap-aware CTA whose copy adapts to the actual gap ("Authorize Interchange on N more properties", "Register your properties at AAO", or "Manage on AAO"). The AAO link now carries `?authorize={agentUrl}&return={currentUrl}` so the publisher's pre-fill and round-trip flow is preserved (assuming AAO honors those query params).
* **Connect Ad Server dialog**: spelled out the GAM service-account onboarding path (`Admin → Access & authorization → Users → New user`), the recommended role (Administrator, with Order Manager + Trafficker as a fallback), and the "don't add it under your personal user settings" gotcha that's the most common stumble.
* **House domain + public agent URL** are now stamped automatically on the upstream tenant on first provision (operator domain + canonical agent URL), so embedded tenants don't sit with null platform-managed config.
* **Sales agent iframe** drops the "Back to storefront" wrapper. The salesagent's embed-aware breadcrumbs (driven by an `X-Embed-Breadcrumb-Root` header pointing at the customer's storefront URL) provide a continuous nav lineage from our app into theirs.
* Properties panel on the storefront homepage now always deep-links to AAO's `/publisher/{domain}` page as the canonical "manage my inventory" CTA, regardless of whether the publisher self-hosts adagents.json or has AAO host it. AAO's publisher page handles the three-way fork (self-host instructions, AAO-hosted CNAME, not-configured) and surfaces the per-agent authorization rollup directly. The self-hosted manifest URL stays visible as informational text so publishers can see where their authoritative file lives.
* Storefront homepage now defers publisher and advertiser management to the salesagent's own screens. A single salesagent tenant can rep multiple publishers (Publisher Partners), and advertiser/principal mapping has its own UI on the salesagent (Principals); duplicating those surfaces on the storefront didn't fit the multi-publisher model. Removed: the AAO-derived "Properties" panel, the `GET /api/v2/storefront/properties-status` endpoint, the "Pick a default GAM advertiser" dialog, the `gamDefaultAdvertiserId` field on `PsaConnection`, and the corresponding REST endpoint and DB column. Per-publisher AAO state (property registration, adagents.json verification, agent authorization) and per-buyer advertiser mapping both happen in the salesagent now and surface via its `setup_tasks` block, which the storefront's Sales agent setup panel renders directly. Each setup-task CTA now correctly deep-links into the iframe at the path the salesagent provided.
* Polished the Products stat in the storefront homepage's agent card. The "Manage" CTA was rendering as a heavy filled button that overpowered the surrounding read-only stats (Workflows, Packages, Creatives). Replaced with a subtle underlined text-link beneath the count so the row stays visually consistent.
* Fixed product discovery returning zero products when sales agents emit responses that fail AdCP 3.0 schema validation. The ADCP SDK no longer silently filters partial-shape products out of `get_products` responses, and any schema violations on a sales agent response are surfaced as a structured warning log with agent name, product count, and the failing fields. Buyers see the actual products that came back even when an upstream agent omits newly required fields like `reporting_capabilities`.
* Two fixes for the inventory sync surface:
* The `View sync details →` button now deep-links to `/inventory/browse` instead of `/inventory`. The `/inventory` route is locked for embedded-mode tenants (Sprint 4 platform-managed-page rework); the actionable diagnostic + manual-sync surface lives at `/inventory/browse`.
* Dropped the `Refresh` button from the inventory panel header. The Tenant Management API's `/refresh` endpoint queues SyncJob rows but doesn't actually kick off the sync threads (salesagent bug). Pressing it produced a misleading "Refreshing... / last run just now / still pending" state. Until that's fixed upstream, the panel surfaces a single primary CTA (`Open sync page →` / `Manage sync →`) that takes the publisher to the salesagent's working "Sync All" button.
* Storefront onboarding now closes the post-provision dead zone:
* New **Importing your inventory** panel surfaces the three sync streams (inventory, custom targeting, advertisers) with per-stream status while sync is running. Self-hides once everything's caught up.
* **Default GAM advertiser** setup task no longer fires before the advertisers sync completes — picking from an empty cache was a dead-end. The task now waits for `syncs.advertisers.status === 'success'`.
* **Buyer routing** panel disables its "Add rule" button and shows a "we're still importing your advertisers" alert until the same sync finishes, so publishers don't tap into a form whose advertiser list is empty.
* Storefront customers using the managed Prebid Sales Agent now provision real tenants in the embedded sales agent backend. Previously the request lifecycle fell back to a stub client that returned `service unavailable`. Five new env vars (`SALESAGENT_TENANT_API_URL`, `SALESAGENT_TENANT_API_KEY`, `GAM_SHARED_SERVICE_ACCOUNT_EMAIL`, `GAM_SHARED_SERVICE_ACCOUNT_KEY_JSON`, `INTERCHANGE_CANONICAL_AGENT_URL`) wire the API to the salesagent service deployed in the same cluster.
* Surface managed sales agent product counts on the storefront homepage. The new `products` block on `/api/v2/storefront/psa/status` (active / draft / archived counts) flows into a clickable Products stat that deep-links the iframe directly to the sales agent's `/products` page. The launch endpoint now accepts an optional `path` for path-only deep links (sanitized server-side to prevent escaping the tenant prefix).
* Adopt the upstream sales agent's Sprint 1.8 wire-shape additions:
* `GET /api/v2/storefront/psa/status` now returns a `setupTasks` block whose `publisher`-scope items merge into the storefront homepage's setup task list. Items the upstream marks `platform`-scope are dropped — those represent provisioning gaps Scope3 owns.
* `PUT /api/v2/storefront/psa/default-advertiser` now round-trips the value to the sales agent before persisting locally. Upstream errors fail the request instead of being silently swallowed, so the publisher's chosen advertiser can't drift between surfaces.
* `POST /api/v2/storefront/psa/refresh` proxies straight through to the sales agent's now-live `/refresh` endpoint.
* `TENANT_NOT_ACTIVATED` ADCP errors raised by the sales agent's natural-key resolution are surfaced as "Publisher hasn't finished setup yet." instead of the raw upstream message.

## 2.92.0 — May 6, 2026 at 6:44 PM UTC

* Buyers can now configure standing log-level data subscriptions per advertiser and per campaign on the v2 advertiser/campaign endpoints. Use the new `dataDelivery.outputs[]` array on `POST/PUT /api/v2/buyer/advertisers` and `POST/PUT /api/v2/buyer/campaigns` to declare what log-level data to ship (`MB_DELIVERY`, `IMPRESSIONS`, `CLICKS`, `VAST_EVENTS`, `CAPI_ATTRIBUTION`, `MMP_POSTBACKS`, `MEASUREMENT`), the firing cadence (`HOURLY`, `DAILY`, `WEEKLY`), and the destination. v1 supports GCS only — additional destinations land in a follow-up release. Campaign-scoped outputs override advertiser-scoped outputs by `dataDeliveryType`. Pass an empty `dataDelivery.outputs` array to clear; omit `dataDelivery` entirely to leave existing outputs untouched.
* `customer_switch` called without a `customerId` (reset to home) now clears the user's persisted MCP customer selection instead of overwriting it with the home customer ID. Stateless clients fall back to the JWT-default customer when no overlay is present, so the persisted row was redundant on reset, and leaving the home id written there bypassed the multi-customer mutation guard for users who were exiting a switched context rather than committing to home.
* Fixed an issue where users who only had read access on their current customer could not accept an invitation to join another customer. Accepting and declining invitations now both require read-level access, matching the fact that invitation acceptance is a personal action authorized by the recipient's email.
* Fixed the org switcher hiding organizations the user belongs to as a child customer. When you only had a membership on a child organization (and not its parent), that organization was missing from the "Switch org" list, leaving you stranded after switching to a different org. The dropdown now surfaces those memberships directly so you can always navigate back.
* Fixed `customer_switch` MCP tool returning `INTERNAL_ERROR` when switching to a non-existent or inactive customer. The tool now returns a `NOT_FOUND` error for missing or inactive customers, and `ACCESS_DENIED` when the user lacks permission for the target customer.
* `media_buy_execute` now returns `NOT_FOUND` instead of `INTERNAL_ERROR` when the requested media buy ID does not exist.
* Fixed an org-settings navigation bug where users with hierarchical or SuperAdmin access to a parent organization could be redirected back to their child customer instead of landing on the org-settings page.
* Fixed SSO sign-in failures showing a misleading "isAuthError is not defined" message instead of the real authentication error. Failed SSO callbacks now display the actual cause returned by the server.
* Fixed an authentication issue where logging in on `staging.interchange.io` would log the user out on `interchange.io` (and vice versa). Auth cookies are now scoped per environment so sessions in one environment can no longer overwrite or invalidate sessions in the other.
* Existing buyer customers can no longer log into Interchange unless their customer is in the alpha-opt-in cohort. Buyers who are blocked at login are routed to an inline waitlist on the sign-in page; sellers and SuperAdmins are unaffected. New buyer accounts created via "Add account" by an already-enrolled parent are auto-added to the cohort, so child teammates inherit access without manual onboarding.
* ADCP delivery webhook (`POST /adcp/webhook/...`) now responds with `400 VALIDATION_ERROR` and a `details.validationErrors` array (`{ field, code, message }` per issue) when the payload fails schema validation, instead of the previous generic `500 INTERNAL_ERROR`. This lets sales agents self-diagnose payload mistakes (e.g. uppercase `pricing_model: "CPM"` when the spec requires lowercase `cpm`) without needing to contact support.
* Hid underlying-agent identifiers from the buyer-facing storefront and account-linking endpoints. Buyers now drive the full register-credentials → discover-accounts → link-account flow in `(storefrontId, sourceId)` terms — agent identifiers are never exposed.
* `BuyerStorefrontSource` no longer includes `protocol` (`MCP`/`A2A`). Use `requiresCredentials` to drive registration instead.
* `GET /api/v2/buyer/storefronts/credentials` — credentials no longer include `agentId`/`agentName`. Each credential exposes a `sources[]` array of `{ storefrontId, storefrontName, sourceId, sourceName }` listing the storefront sources it gives access to. `accountType` and `updatedAt` are now part of the documented response. `registeredBy` may be `null` for legacy credentials that predate registration tracking.
* `POST /api/v2/buyer/storefronts/:storefrontId/sources/:sourceId/credentials` — when the source uses OAuth, the response's `oauth` object contains `{ authorizationUrl, storefrontId, sourceId, sourceName }` instead of `{ authorizationUrl, agentId, agentName }`.
* `GET /api/v2/buyer/advertisers/:advertiserId/accounts`, `GET /api/v2/buyer/advertisers/:advertiserId/accounts/available`, and `POST /api/v2/buyer/advertisers/:advertiserId/accounts` accept `storefrontId` + `sourceId` to identify the source. `partnerId` is no longer accepted.
* `POST /api/v2/buyer/advertisers` and `PUT /api/v2/buyer/advertisers/:advertiserId` — each `linkedAccounts[]` entry takes `{ storefrontId, sourceId, accountId, billingType? }`. `partnerId` is no longer accepted.
* Account responses (`AccountOutput`, `AccountSummary`, `AvailableAccountOutput`, and the embedded `LinkedAccount` on the advertiser resource) no longer include `partnerId`/`partnerName`. They expose `sources[]` of `{ storefrontId, storefrontName, sourceId, sourceName }` listing the storefront sources that surface the account. The list can be empty when the underlying source has been deactivated — render those accounts as no longer reachable.
* Fixed `/auth/check-email-availability` so that when the backend rejects an email (for example a typo'd domain or a disposable address), the specific reason is surfaced to the caller as a 400 instead of being swallowed as a generic 500 with no detail.
* Fixed `sync_accounts` failing when a sales agent's capabilities were synthesized from its MCP tool list rather than served from a `get_adcp_capabilities` response. The call now retries against a v2-tolerant client instead of surfacing as an error.

## 2.91.2 — May 4, 2026 at 10:40 PM UTC

* Fixed `get_campaign` so the `mediaBuyId` query param actually narrows the embedded `mediaBuys[]` array when called via the MCP `api_call` tool. Previously the filter only worked over REST; through MCP it was silently ignored and the full media-buy tree was always returned.

## 2.91.1 — May 4, 2026 at 10:03 PM UTC

* Fixed duplicate buttons on the storefront Account setup card. The billing step previously showed both "Connect Stripe" and "Setup" side-by-side; now only the primary action renders while a step is in progress.
* Account discovery for advertisers no longer fails when a sales agent advertises AdCP v3 without declaring `adcp.idempotency.replay_ttl_seconds`. The platform now retries `sync_accounts` against a v2-tolerant client instead of surfacing the underlying version error.

## 2.91.0 — May 4, 2026 at 6:27 PM UTC

* `get_campaign` now returns a `mediaBuyRefs` array (`{ mediaBuyId, status }` per buy) placed early in the response so LLM clients can enumerate every media buy on a campaign even when the heavier nested `mediaBuys[]` tail is truncated by their context window. `get_campaign` also accepts a `mediaBuyId` query param (single value or repeated) that narrows the embedded `mediaBuys[]` to just the requested buys without changing the campaign object itself.

## 2.90.0 — May 4, 2026 at 5:00 PM UTC

* Cleaned up the Go live checklist copy on the storefront onboarding page so each item shows a single concise description instead of a redundant action + status pair.
* Fixed Go-live readiness check showing "Billing — Stripe Connect not configured" for child customers that inherit billing from a parent. The readiness check now resolves billing the same way the storefront billing endpoint does, walking up to the parent customer's `customer_billing` row when the child has none.
* Fixed storefront go-live readiness incorrectly flagging agents configured with `NO_AUTH` as missing authentication credentials. Only agents that actually require auth (API\_KEY, OAUTH, JWT) now gate go-live.
* Fixed three creative format pipeline bugs: the Asset requirements panel now recognizes the `primary` slot as satisfied when a CREATIVE\_SOURCE asset is uploaded (instead of always reading "Missing"); the creative preview endpoint normalizes assets before forwarding so the remote sales agent's `preview_creative` validator no longer rejects them for missing `asset_type`; and creatives built solely from a URL or webhook now correctly tag that asset as the primary creative source instead of leaving every manifest with no renderable primary asset.

## 2.89.0 — May 4, 2026 at 4:55 AM UTC

* Storefront onboarding and account configuration improvements.
* Documentation improvements.

## 2.88.1 — May 3, 2026 at 9:18 PM UTC

* Update SSO configuration page to be under account configuration, and improve documentation.

## 2.88.0 — May 3, 2026 at 7:26 PM UTC

* OAuth discovery metadata (`/.well-known/oauth-authorization-server`, `/.well-known/oauth-protected-resource`, `/.well-known/openid-configuration`) and the MCP `WWW-Authenticate` header now reflect the hostname the client used to reach the API. Requests to `api.interchange.io` get `interchange.io` issuer/endpoints; requests to `api.agentic.scope3.com` continue to get the legacy domain. Fixes Claude.ai connector setup at the new domain.
* Removed the following v2 endpoints and their corresponding MCP tool operations: `/hypotheses`, `/test-plans`, `/allocations`, `/human-feedback`, `/learning-cycle/run`, `/belief-state`, `/testability`, and `/learning-records`. Measurement source, measurement record, and freshness endpoints remain available.

## 2.86.0 — May 1, 2026 at 9:03 PM UTC

* Added content moderation guardrails on LLM inputs and outputs. User-supplied campaign briefs (`POST /v2/campaigns`, `PUT /v2/campaigns/:id`) are now screened for prompt-injection, jailbreak attempts, and critical content (hate speech, illegal content, violence uplift) before any LLM call. All LLM provider outputs (Claude, Gemini, Bedrock) pass through an output filter that blocks slurs, CSAM, weapons-uplift, and PII leaks, and counts refusal/identity leaks for monitoring. Content blocked by moderation returns `422 CONTENT_MODERATION_BLOCKED` with structured findings.
* The `mediaBuys[]` array returned on `GET /campaigns/:id` now includes each media buy's `startTime` and `endTime`, so buyers and agents can see the media buy's flight window without a separate call. The media buy `createdAt` is now stable across versions: editing a media buy no longer rewrites its creation date, and a backfill aligns existing rows so the live row reflects the original creation timestamp. Use `updatedAt` (and `valid_from` on historical version reads) to identify when a specific version was created. As part of this work, campaign `allocatedBudget` and `unallocatedBudget` are now correct while a media buy update is awaiting approval — previously both versions of the in-flight media buy would briefly count toward the allocated total.
* Fixed daily delivery webhooks failing with 403 "Agent does not have access to this resource" for buyers using open-auth partner sales agents (e.g. Ozone, CMI Media Group, Planet Nine VDS). The webhook agent↔customer binding check now allows a customer through when they have at least one media buy on the agent, in addition to the existing case where the customer owns the agent. Resource-level tenant scoping in the downstream handlers is unchanged.
* Versioned agreement URLs now follow a `/agreements/<document>/<version>` shape:
* `GET /agreements/terms-of-service/{version}` (e.g. `/agreements/terms-of-service/v3-0`)
* `GET /agreements/facilitated-agreement-terms/{version}` (e.g. `/agreements/facilitated-agreement-terms/v1-0`)
* The previous `/agreements/{version}/terms-of-service` and `/agreements/{version}/facilitated-agreement-terms` paths are kept as permanent aliases — they serve identical content (no redirect) so historical PSA links and external bookmarks stay valid. Responses on the legacy paths include a `Link: <canonical>; rel="canonical"` header pointing at the new shape, so log/analytics tooling can normalize on a single URL. Use the new shape for all new integrations.

## 2.85.0 — May 1, 2026 at 5:04 PM UTC

* Fixed several documentation bugs found in a follow-up audit. The buyer API reference now shows the correct request body for `POST /advertisers/:advertiserId/test-cohorts` (`cohortType` and `definition` instead of the non-existent `type`/`percentage`/`startDate`/`endDate`) and `PUT /advertisers/:advertiserId/measurement-config` (`mmmEnabled`, `mmmConfig`, `incrementalityTestingEnabled`, `brandLiftEnabled`). The reporting endpoint is correctly documented as `GET /reporting/metrics` (was `/advertisers/:id/reporting`, which doesn't exist), with the actual hierarchical response shape. The MCP tools section now accurately lists the six registered tools — including `accept_tos`, which buyers must call after their first `403 TOS_ACCEPTANCE_REQUIRED`. Removed the phantom `help` tool entry. Also fixed shared-router notification paths in both buyer and storefront skill files (`/api/v2/notifications/...`, not `/api/v2/buyer/notifications/...` or `/api/v2/storefront/notifications/...`). Removed phantom `POST /event-sources` (only `/sync` exists) and the `accountPolicy` ghost field from the storefront skill. Conversion API now correctly shows the required `account: { account_id }` field. Added five missing storefront routes to the OpenAPI generator (registered agents listing, agent detail, agent OAuth authorize endpoints, storefront audit logs, `PUT /billing` admin update, and `POST /billing/account-session`) and regenerated `storefront-api-v2.yaml`.
* Bump @adcp/sdk to 6.5.0.
* Pulls in two production-correctness fixes for buyer agents on top of the 6.1.0 pre-send AJV ordering fix:
* 6.4.1 strips top-level `null` envelope fields (`errors`, `context`, `ext`) before validating v2.5 seller responses, so Pydantic-based v2.5 sellers no longer fail discovery with `must be array` / `must be object`.
* 6.4.1 wraps `SingleAgentClient.executeTask` in a try/catch so pre-flight errors (feature validation, endpoint discovery, schema validation, version detection, request adaptation) return `{ success: false, status: 'failed', error }` instead of throwing — restores the declared `TaskResult` contract for callers like `list_authorized_properties` against v2.5 MCP sellers.
* 6.2.0 also ships `decideRetry` retry semantics for buyer agents (additive; no callers yet).
* Storefront compliance responses (`/storefronts/:id/readiness`) gain a new `silent` value on the per-track `status` enum: the track was wired but observation-based assertions saw zero resources to attest. Distinct from `pass` (verified) and `skip` (didn't run).
* Updates to v2 campaigns that target unsupported downstream sales-agent capabilities are now rejected at the API boundary with a `CAPABILITY_NOT_SUPPORTED` (HTTP 422) error, instead of failing mid-flight after partial state changes. The error response includes an `unsupported[]` array detailing each blocked media buy, the agent, and the missing capability.
* Added automatic cascade of appended pacing periods to live media buys via ADCP 3.0 `update_media_buy.new_packages`. The `update_campaign` response now includes a `pacingCascadeResult` block reporting per-media-buy outcomes (`updated`, `skipped`, `failed`, `unsupported`). Only strict appends to `pacingPeriods` are cascaded; insertions, modifications, and removals continue to require manual new media buys. Sellers that don't advertise `add_packages` in their `valid_actions` are reported as `unsupported`.
* V2 list endpoints (`list_*`) now return a fixed summary shape, while detail endpoints (`get_*`) continue to return the full resource. List rows include identity, display, state, categorization, and at-a-glance scalar signals — embedded child collections, long text, and nested configuration objects are no longer returned on lists.
* Summary contracts narrowed across the board. Fields that were previously on list responses but now appear only on `get_*`:
* `list_advertisers`: `description`, `optimizationApplyMode`, `campaignBudgetType`, `linkedAccounts`, `frequencyCaps`, `utmConfig`, `linkedBrand`
* `list_audiences`: `consentBasis`, `lastOperationStatus`
* `list_advertiser_accounts`: `advertiser`, `billingProxy`, `house`, `billing`
* `list_creatives`: `format_previews`, `auto_detected_template`, `message`, `tracking`, `html_processing`, `frequencyCaps`, per-asset details
* `list_campaigns`: `brief`, `mediaBuys`, `audiences`, `creativeFormats`, `frequencyCaps`, `pacingPeriods`, `performanceConfig`, `constraints`, `fees`, `mediaBudget`, `allocatedBudget`, `unallocatedBudget`, `products`, `discoveryId`, `catalogId`
* `list_buyer_storefronts`: full `sources[]` array (replaced by counts)
* `list_partner_agents`: `customerAccounts[]` array (replaced by count)
* New derived scalars on list responses (replace previously-embedded arrays): `linkedAccountCount` (advertisers), `sourceCount` and `connectedSourceCount` (buyer-storefronts), `customerAccountCount` (partner-agents), `asset_count` (creatives), `tagCount` (allocations).
* Behavior change on `list_advertisers`: the `includeAccounts`, `includeBrand`, and `includeFrequencyCaps` query parameters are removed (they remain available on `get_advertiser`).
* Wire change on `list_test_plans` and `list_hypotheses`: responses are now wrapped as `{ testPlans, total }` and `{ hypotheses, total }` respectively, to match the rest of v2 (both were previously bare arrays).
* Wire-format updates:
* `list_campaigns`: `budgetTotal` and `budgetCurrency` are replaced by nested `budget: { total, currency }` (matches `get_campaign`'s nested shape).
* `list_creatives`: `sync_synced` and `sync_agent_count` are replaced by nested `sync_status: { synced, agent_count }` (matches `get_creative`'s nested shape).
* `Campaign.campaignType` is now optional. Older campaigns where the type was never recorded will return `campaignType: undefined`. Code that narrowed against the previously-required field needs a null-check.
* Migration: callers that relied on `array.length` for child collections should switch to the corresponding `*Count` field; callers needing the full resource should switch from `list_*` to `get_*` for the resources they care about.
* Discover Products MCP widget: surface refine errors as a dismissable banner under the controls row (no longer hidden behind the dropdown), move the selection summary below the product cards, and tighten the radius hierarchy (cards 8px, buttons and nested chips/callouts 4px).
* Discovery sessions are now reused across multiple discovery runs within the same campaign. Each run creates a new search context with its own brief, and products are tagged to the run that discovered them. Added a new `GET /campaigns/:id/products` endpoint (and `get_campaign_products` operation for `api_call`) to view all staged products with their discovery context and media buy status.
* Links in emails, redirects, and UI navigation now resolve to the correct domain (interchange.io or scope3.com) based on where the user is accessing the platform.
* Fixed a crash on the campaign creative assets page when the manifest or format list responses were not arrays.
* Property lists now accept the full set of AdCP property identifier types — sourced directly from `@adcp/client/types` so the schema stays in lockstep with the AAO property registry. Create / update / check endpoints accept a typed `identifiers: [{type, value}]` array; the existing `domains: string[]` field remains supported as shorthand for `domain`-typed identifiers. Property list responses now include typed `identifiers`, `unresolvedIdentifiers`, and `registeredIdentifiers` arrays alongside the derived `domains`, `unresolvedDomains`, and `registeredDomains` views. The ADCP resolve endpoint (`GET /lists/:listId`) and `/property-lists/check` endpoint return the typed identifiers. Today the local DB resolves web (`domain`, `subdomain`) and mobile/CTV app identifiers (`ios_bundle`, `android_package`, `apple_tv_bundle`, `bundle_id`, `apple_app_store_id`, `google_play_id`, `roku_store_id`, `fire_tv_asin`, `samsung_app_id`); other AdCP types accepted by the schema (DOOH venues, podcast feeds, station IDs, etc.) pass validation but currently fall through to `unresolvedIdentifiers` until corresponding inventory data lands. Non-domain types short-circuit to the `assess` bucket on `/check` pending upstream AAO support.
* V2 storefront reporting is now driven end-to-end by AdCP 3.00 capabilities.
* Webhook dispatch on storefront media buys is driven by per-product `reporting_capabilities` (`supports_webhooks` / `available_reporting_frequencies` / `available_metrics`) and gated by the seller's `media_buy.reporting_delivery_methods`. If the seller doesn't advertise `"webhook"`, webhook dispatch is suppressed regardless of product-level capabilities.
* Offline (bucket) reporting is now configurable per linked partner account. New endpoint `PUT /advertisers/{advertiserId}/accounts/{linkId}/reporting-bucket` sets or clears the bucket; pass `reporting_bucket: null` to clear. After persisting, the seller is notified via `sync_accounts` using the spec-defined `preferred_reporting_protocol` field plus a Scope3 transitional `ext.scope3_reporting_bucket` extension; if that notification fails, the local row is still updated and the response is 503 with the persisted account in the error details. The same operation is exposed via the v2 MCP `api_call` tool as the new `update_account_reporting_bucket` operation. Seller-provisioned `account.reporting_bucket` values returned from `list_accounts` / `sync_accounts` are also persisted, with buyer-supplied buckets winning on conflict.
* When a seller advertises offline-only reporting and no `reporting_bucket` is configured for an account, media-buy creation now logs a warning and audit-log marker pointing at the configuration endpoint and proceeds (polling via `get_media_buy_delivery` is always available as a baseline per AdCP 3.0).
* The `reportingType` and `reportingPollingCadence` parameters on the agent register tool are deprecated.
* Product discovery now skips sales agents whose advertised channel coverage does not overlap with the requested channels, instead of fanning out a request the agent will reject. The skipped agents appear in the per-agent debug output (when `debug=true`) with a reason like `Agent does not sell requested channels (supports: display, ctv; requested: social)`. Failed-agent debug output also includes a new `skipReason` field carrying the human-readable rejection text from the agent, useful for the agents that still respond with an error after passing the pre-filter.

## 2.84.0 — April 29, 2026 at 11:47 PM UTC

* Customer admins can now remove a member from a customer via the admin members page. Removed members lose access immediately and must be re-invited to regain it.
* ADCP integration upgraded to `@adcp/client` 5.x with hardened webhook handling and new public discovery endpoints.
* New public endpoints `/.well-known/jwks.json` and `/.well-known/brand.json` for AdCP RFC 9421 request signing — sellers can verify our outbound calls and resolve our brand profile.
* `UpdateCampaignBody` now rejects explicit `null` (previously accepted); send omitted fields instead of `null` to indicate "no change".
* `billingType` vocabulary updated: `brand` is now `advertiser`. Existing data is migrated automatically.
* `ComplianceTrackResultSchema` no longer accepts `expected` — only the documented values are valid.
* `activate_signal` MCP tool now requires `destinations` (`minItems: 1`) per AdCP v3.
* Internal: webhook handlers gain per-tenant + per-agent scoping (`customer_id` + `sales_agent_id` in DB predicates), opportunistic RFC 9421 signing on outbound calls, and improved error surfaces (`adcpError`, `correlationId`) propagated from the SDK.
* Fixed creative attachment to media buys, which had been silently broken in three independent ways. (1) Uploading a creative to a campaign with existing DRAFT media buys was rejected by Postgres because the auto-link query referenced the UPDATE target inside a `LATERAL` subquery; the entire transaction rolled back, leaving `media_buy.creative_ids` and `media_buy_products.creative_assignments` unchanged, and execution then skipped sales-agent sync. Eligible product/buy pairs are now resolved in a CTE before the `UPDATE`. (2) The `autoPublishCreative` brand-domain lookup queried the `advertiser_brands` table (renamed to `advertiser_settings`) on a column that never existed, leaving `brand_domain` undefined on synced creatives — fixed and the silent catch replaced with an actual log line. (3) `update_campaign` accepted `mediaBuys[].creative_ids` in the request body but the service silently dropped it and overwrote with the campaign's auto-synced creatives, so buyers had no escape hatch when auto-sync was wrong; the field is now honored verbatim (with the existing format/customer/campaign validation in `updateMediaBuy` surfacing any errors) and only falls back to auto-sync when the field is omitted. The `mediaBuys[]`, `mediaBuys[].packages[]`, and `mediaBuys[].products[]` schemas now use Zod `.strict()` so unknown keys (typos, removed fields) fail validation instead of being silently stripped — closes the class of bug that hid #3.
* When a sales agent rejects `create_media_buy` with an `adcp_error` envelope, surface the agent's actual error code and message instead of the misleading "Sales agent returned completed status but no packages" protocol-violation error.

## 2.83.3 — April 29, 2026 at 2:59 AM UTC

* Fixed the campaign creative-upload flow so the "Creatives still required" banner clears once a matching creative is uploaded. Previously, a trailing-slash mismatch in `agent_url` between a product's required formats and the uploaded creative's format caused the requirement to never be marked satisfied.
* Fixed format previews not rendering on the creative detail page for some providers and creative types.
* The "Formatted previews" grid is now driven entirely by the format definition: it no longer hides the entire grid when the manifest has no creative-source asset (which happened for webhook- or URL-only creatives), and per-tile media fallbacks tolerate a missing source asset instead of throwing.
* The agent's `preview_creative` is now called whenever a format is selected, not just when there are no sized siblings. When both sized siblings (e.g. `display_300x250_html`, `display_728x90_html` for `display_html`) and agent-rendered previews are returned, the agent's `preview_url`/`preview_html` is merged into each sibling tile by matching dimensions so each size shows the actual rendered creative.
* Tile labels and iframe titles now show the format ID rather than the per-render ID.
* Fixed `sync_creatives` request validation error when syncing creatives to third-party sales agents. Per-package assignments are now sent as the spec-compliant array of `{ creative_id, package_id }` objects and forwarded on the ADCP request.

## 2.83.2 — April 28, 2026 at 11:49 PM UTC

* Keep the global navigation header (org/account switcher, notifications, account menu) interactive while the Terms of Service acceptance modal is showing. Previously, the modal blocked the entire page, so a stale ToS on the current org prevented users from reaching any other org or account they had access to. ToS is per-customer, so switching is now a valid path forward without accepting on the current org first.
* Block child accounts from accepting Terms of Service against the parent organization's contract. When a child account's effective contract resolves via parent fallback, ToS acceptance is refused unless the request comes from an organization admin. The user info response also surfaces a new `tosBlockedReason` field so the UI can render the right experience: organization admins see an "Accept for the organization" button, while non-admins see a sign-out modal explaining that an organization admin must accept first.
* Fixed creatives being rejected before sync to sales agents because the auto-publish flow was injecting domain assets (`brand_name`, `impression_tracker`, `click_url`) into the creative payload regardless of whether the format spec actually declared a slot for them. Strict sales agents (e.g. Wonderstruck) reject the creative for unrecognized asset keys, and the same hardcoded asset\_ids meant agents that name their slots differently (e.g. `brand_text`, `imp_pixel`, `clickthrough_url`) never got those slots filled.
* Replaced the per-field injection logic with a single asset-capability registry that walks the format spec, matches each slot by pattern (asset type + asset\_id shape), and writes the resolved value using the asset\_id the spec actually declared. Adding a new domain field is now one entry in the registry rather than another bespoke injection block.
* Invite-member error toasts now show only the human-readable message instead of the full JSON error blob (e.g. "Too many invitation requests. Please try again in 15 minutes." instead of `{"errorCode":"...","errorMessage":"..."}`).

## 2.83.1 — April 28, 2026 at 6:25 PM UTC

* Fixed the Terms of Service acceptance modal not appearing when switching into a member organization that has not yet accepted the latest ToS. The check now correctly distinguishes a SuperAdmin impersonating an unaffiliated customer (bypass ToS) from any user — including a SuperAdmin — switching into a customer they are a member of (must accept ToS for that customer).

## 2.83.0 — April 28, 2026 at 5:36 PM UTC

* Added public, unauthenticated endpoints to serve Scope3 legal agreements as markdown:
* `GET /agreements/terms-of-service` — latest pinned Terms of Service (currently v3.0)
* `GET /agreements/<version>/terms-of-service` — versioned Terms of Service (e.g. `v3-0`)
* `GET /agreements/facilitated-agreement-terms` — latest pinned Facilitated Agreement Terms (currently v1.0)
* `GET /agreements/<version>/facilitated-agreement-terms` — versioned Facilitated Agreement Terms (e.g. `v1-0`)
* `GET /agreements/privacy-policy` — Scope3 Privacy Policy
* Documents are checked into the repository and versioned in code, so the latest pointer is deterministic per release.
* Fixed two cases where creatives could be silently misrouted on media buys. Product format lookups during creative validation now correctly scope by sales agent and customer, so a creative that doesn't match the active agent's product is rejected upfront with a clear validation error instead of being silently dropped at the per-package boundary. Products without declared formats no longer receive every creative; they receive none, surfacing the misconfigured product to the buyer.
* Fixed broken endpoint URLs across the v2 docs and clarified how API versioning works.
* Buyer and storefront REST examples now use the canonical `/api/v2/buyer/...` and `/api/v2/storefront/...` base paths everywhere (previously a mix of `/api/buyer/...` and `/api/storefront/...`, which only worked via the 308 redirect alias). Shared endpoints — `/notifications`, `/notification-preferences`, `/notification-email`, `/slack-configuration`, `/service-tokens`, `/accounts`, `/accept-tos` — are now documented at their correct `/api/v2/...` (no `/buyer/` segment) paths. Skill-file and OpenAPI YAML download URLs were updated to the same versioned canonical paths.
* Added a Versioning section to the Authentication page explaining the difference between the canonical versioned URLs (`/api/v2/buyer`, `/mcp/v2/buyer`, etc. — pinned to v2 across future major versions) and the unversioned aliases (`/api/buyer`, `/mcp/buyer`, etc. — 308-redirect to whatever is currently stable). Corrected two notes in the migration guide and the "Built for Agents" page that previously claimed the versioned URLs auto-roll to latest stable, which is the opposite of how versioning actually works.
* Also corrected the discovery POST `budget` example (scalar number, not `{ total, currency }`), the creative manifest list endpoint (`/creativeManifest`), the format catalog endpoint (`/formats`, `/creatives/templates`), and the polling example for `GET /campaigns/:id/media-buy-status` (response shape uses `media_buys[]`, not a top-level `status`).

## 2.82.0 — April 28, 2026 at 2:14 PM UTC

* Added a storefront activity feed for sellers. A new `GET /api/v2/storefront/audit-logs` endpoint returns the recent config and inventory source changes for your storefront, and sellers can now access the feed from the home page under the Organization section.
* Exposed the activity feed through the MCP `api_call` tool on both the buyer and storefront surfaces. Buyers can now list audit log events via the new `list_activity` operation (`GET /api/v2/buyer/audit-logs`); the storefront `api_call` routes `GET /api/v2/storefront/audit-logs` to the same audit log dispatch.
* Synced the storefront API documentation with the live route surface. Removed the legacy Pylon-specific `POST /storefront/notifications/provision` and `GET /storefront/notifications/status` endpoints from the storefront skill file and OpenAPI spec, and removed `pylonAccountId` from any documented response. Communication channel provisioning is configured at the customer/account level and is not part of the storefront onboarding flow, so it is not advertised here. Also corrected the storefront API reference (no `DELETE /storefront`; clarified `POST /storefront` is idempotent), aligned `/api/storefront/...` examples to the canonical `/api/v2/storefront/...` form, replaced confidential customer placeholder values with `Acme`, and fixed the AAO builder URL and the agent compliance shape in the storefront skill file.
* Added `GET /api/stripe/payment-method-status` to check whether a customer has a payment method on file. The buyer billing page now surfaces a warning when no payment method is configured, so admins can add one before invoices fail to charge.
* Fixed six v2 storefront billing operations that returned "Endpoint not found" through the MCP dispatcher despite being documented: provision Stripe Connect account, get billing config, account status, transactions, payouts, and onboarding URL. The underlying REST endpoints were unaffected.

## 2.81.0 — April 27, 2026 at 9:05 PM UTC

* Added a customer communication channel flow for support: during signup (or via a new Admin → Support tab / home page prompt) customers can opt into a Slack Connect or Microsoft Teams channel (`ext-agentic-[env-]{customer-slug}-{customerId}`). The chosen provider, channel name, and invite state are persisted on the customer. For Slack, the channel is automatically linked to a Pylon account and tagged `Buyer` or `Sales agent` based on the customer role.
* New endpoints:
* `POST /api/v2/customer/communication-channel` — provision Slack/Teams, or pass `provider: null` to decline
* `GET /api/v2/customer/communication-channel` — read current provisioning state
* `POST /api/v2/customer/communication-channel/resend-invite` — re-send the invite without re-creating the channel
* On provisioning, the channel is auto-populated with configured Scope3 internal support staff (buyer or seller list) and all of the customer's admins. Same-workspace Slack users are added via `conversations.invite`, external admins via Slack Connect; Teams external emails are added as B2B guests via the backing M365 group with retries for Graph propagation lag.
* Clarified that the `views` metric (in reporting and as an optimization goal) refers to viewable impressions (the MRC-viewable subset of impressions, per AdCP), not raw rendered impressions. Documentation and schema descriptions for `views`, `completedViews`, and the `MetricGoal.metric` field have been updated to reflect this and to note that a viewability rate goal can be expressed as `metric: "views"` with a `threshold_rate` target.
* Embed Stripe invoices and pending transactions directly on the billing page for buyer accounts, storefront accounts, and per-storefront child accounts in collapsible sections.
* Fixed an issue where retrying or rapidly clicking "Connect Stripe" could create multiple orphaned Stripe Express accounts for the same client. Provisioning now uses a deterministic idempotency key per customer, so duplicate requests resolve to the same Stripe account.
* Fixed a duplicate-key error that blocked activating new media buy versions when a sales agent accepted an `update_media_buy` change. Status sync now performs the version transition atomically, superseding the old version instead of attempting two simultaneously active rows. New media buy versions also activate immediately when the sales agent's synchronous `update_media_buy` response shows the change is already live, instead of waiting up to an hour for the next status poll.
* Fixed inflated reporting metrics on `GET /api/v2/buyer/reporting/metrics` when a media buy had a pending update. Both the active and pending-approval versions were being returned in the breakdown, causing the media buy to appear twice and its metrics to be double-counted in the campaign, advertiser, and grand totals. Pending versions (which have no reporting data) are now excluded from the response.
* Notifications are now available to all authenticated customers at `GET /api/v2/notifications`. Previously the route was registered only under `/api/v2/buyer/notifications`, which returned `CUSTOMER_ROLE_DENIED` for storefront customers and broke the in-app notifications bell on storefront login. The legacy `/api/v2/buyer/notifications` REST path has been removed; MCP `api_call` paths are unchanged.
* Moved SSO Configuration from the user account dropdown to a new **SSO** tab on the organization settings page. Existing `/sso-config` links now redirect to the new tab.

## 2.80.0 — April 24, 2026 at 8:48 PM UTC

* The Connect agents dialog now offers a "Sign in with AAO" button. Signing in via OAuth adds private and member-only agents registered under your operator domain to storefront agent discovery alongside public agents. The token is used only for the active session and is not stored.
* Renaming a storefront no longer regenerates its `platform_id`. The identifier is now stable once assigned at creation, which prevents "A storefront with a matching platformId already exists" conflicts when renaming into a slug another storefront already uses.
* Added buyer-side frequency cap configuration (`frequencyCaps`) on advertiser, campaign, and creative endpoints. Each cap specifies a `maxExposure` and a rolling `window` (`interval` + `unit`). Single GET always includes active caps; LIST endpoints include them when `includeFrequencyCaps=true` is passed. CREATE/UPDATE bodies accept an optional `frequencyCaps` array — omit to preserve existing caps, pass an empty array to clear, or supply a new list to replace.
* ADCP webhook endpoint now returns proper HTTP status codes for each failure mode instead of a blanket 500. Malformed webhook payloads return 400 with the underlying error message so senders can see what's wrong, invalid URL path params return 400, and internal infrastructure failures still return 500.

## 2.79.0 — April 23, 2026 at 10:47 PM UTC

* Added a notification bell to the v2 app header: opens a dropdown of recent notifications with an unread count badge, mark-as-read on click, and mark-all-as-read.
* Tracking pixel URLs now include the advertiser (seat) ID as an `advid` query parameter alongside `cid` (creative) and `camp` (campaign). Applies to both ADCP asset tracker URLs and HTML-injected tracking pixels for v2 creatives.
* Fixed URL-based creative assets (VAST tags, clickthrough URLs, tracker pixels) so the stored filename is derived from the URL (e.g. `tag.xml` or `qawolf.com`) instead of the URL type label. Also aligned creative update so VAST URLs are stored with `asset_type: VAST`, matching creative create — previously updates always stored them as `asset_type: URL`.
* Fixed campaign updates failing with "Creative format validation failed" when a campaign has creatives in multiple formats (e.g. video and display) and is linked to format-restricted media buys. Creatives are now filtered per media buy based on product format compatibility before syncing.
* Fixed campaign creation failing with "No active contract found for customer" when a child customer inherits its contract from a parent. Pricing resolution now walks the parent hierarchy to match the same contract-lookup behavior as the rest of the API.
* Updating a property list now retroactively syncs active media buys for advertisers linked to that list, so sales agents receive the refreshed include/exclude properties without needing to recreate the campaign. The update response includes an optional `cascadeSummary` summarizing how many active media buys were notified.
* Fixed the `get_media_buy_status` operation on the v2 buyer MCP tool. It previously returned "Endpoint not found" through the MCP dispatcher despite being documented in the skill; the underlying REST endpoint was unaffected.

## 2.78.0 — April 23, 2026 at 12:16 AM UTC

* Campaigns now have a `campaignType` (DECISIONED or ROUTED) and the budget total includes Scope3 fees.
* `campaignType` is required when creating a campaign and immutable after creation. `DECISIONED` campaigns means Scope3 is applying real-time decisioning, optimization, or consolidated invoicing and payment processing operations. `ROUTED` campaigns means the buyer is directly connecting to the seller; they transact and settle directly and do not use Scope3's real-time decisioning or optimization.
* Response includes `mediaBudget` (allocatable to media buys) and a `fees` array with the Scope3 fee breakdown.
* Updating `budget` is rejected if the new media budget drops below the sum of existing media buy allocations, or if by reducing the budget the fee would no longer be payable.
* ROUTED campaigns only accept media buys whose sales agents require operator authentication; discovery results are filtered to match when a ROUTED campaign ID is supplied.
* Existing campaigns are grandfathered with `campaignType=DECISIONED`, an 8% fee rate or custom negotiated price, with `mediaBudget` set equal to the existing `budget` so previous spend capacity is preserved.
* Updated the "creatives still required" banner on campaign creative assets to group requirements by creative agent and show per-product "one of \[formats]" options, matching how products actually require coverage (at least one creative per product, not per distinct format).
* Corrected the v2 buyer skill and `update_campaign` schema descriptions for media buy `start_time` / `end_time`. Clarifies that a media buy cannot start before the campaign's `flightDates.startDate`, and that pacing periods do not strictly govern media buy dates — media buy dates MAY correspond to a pacing period's `start` / `end` when applicable, but are always allowed to be any dates within the campaign flight, with or without pacing periods.

## 2.77.0 — April 22, 2026 at 8:49 PM UTC

* Added measurement engine endpoints for managing hypotheses, test plans, measurement sources, measurement records, allocations, human feedback, learning cycles, belief state, testability analysis, measurement freshness, and learning records. Includes filtering by flight ID on hypotheses, date range and geo filters on measurement records, and paginated learning records.
* Fixed AAO compliance gating to handle the current registry contract, where `/compliance` returns `status: "unknown"` for both unregistered agents and registered-but-untested agents. Registered agents without a graded compliance status now pass through storefront source creation instead of being incorrectly rejected. Added handling for upstream 429 responses on property-list bulk resolution so clients see a retryable 503 instead of a 500.
* Fixed capability refresh failing for operator-auth sales agents (e.g. Snap) by always authenticating with the agent-level credential instead of resolving through the per-customer credential chain.
* Prevent agents from conflating campaign and media-buy end dates when a campaign has pacing periods. The v2 buyer skill now documents `pacingPeriods` and states that a media buy's `end_time` comes from its pacing period's `end`, not the campaign flight end date. Strengthened the `end_time` description in the v2 update-campaign schema to reinforce the same rule.
* Fixed format details endpoint returning an OAuth token resolution error by restricting the seat lookup for an agent to seats whose credential belongs to the calling customer, preventing a seat from another customer (e.g. a master account) from being selected.
* Fixed a bug in the product discovery MCP view where multiple pricing chips appeared selected on products with duplicate pricing option IDs. The selection state now tracks the option by position rather than ID, so products with identical-shape options (same pricing model) render and select correctly.
* Fixed property list endpoints (`POST`/`GET`/`PUT /advertisers/:advertiserId/property-lists[/:listId]`) to wrap the response in `{ propertyList: ... }` as documented in the OpenAPI spec. Previously the endpoints returned the bare property list object.
* Inventory source creation now requires the partner agent to pass AAO compliance testing. Agents that are not registered or not passing will be rejected with a validation error; temporary AAO outages return a service-unavailable error so the request can be retried.
* Added `optimization_goals` to media buys. Optimization goals (event-based CPA/ROAS targets or metric-based CPC/completion-rate targets) can now be set on a media buy and are applied to every package at execution time. Exposed via the v2 `update_campaign` → `mediaBuys` entries. Media buy responses now include `optimization_goals`.
* Property lists now accept up to 100,000 domains per create, update, and check request (previously capped at 10,000 for create/update and 1,000 for check). Large requests are chunked server-side against the AAO registry and local database, so clients no longer need to split their own batches. Create and update responses now include a `resolutionSummary` object — `totalRequested`, `resolvedCount`, `registeredCount`, `unresolvedCount`, `resolutionRate` — so buyers can see at a glance how many of their submitted domains will actually target. The check endpoint response adds a `reportIds` array containing every registry report generated (one per chunk); the existing `reportId` field remains and equals `reportIds[0]` for back-compat.
* Property list checks now retry once and surface a `503 Service Unavailable` when the AAO registry returns transient errors (429 or 5xx), instead of failing with a `500` on the first blip. Clients that retry on 503 will see fewer spurious failures during registry flakes.
* Property list checks now retry once when the AAO registry rate-limits a chunk (HTTP 429) instead of failing the whole request, making large bulk checks resilient to brief registry throttling. System service tokens now also pass SuperAdmin-gated checks so operators can drive admin-only flows (e.g. AAO compliance bypass) end-to-end.

## 2.76.0 — April 21, 2026 at 10:24 PM UTC

* Fixed storefront go-live button hanging when activating a storefront. Activation no longer runs a synchronous agent compliance probe (up to 60s per agent) and is gated only on setup readiness checks.
* Renamed the `VIDEO_VAST` URL asset type to `VAST` on the `url_type` field for creative URL assets. The UI label and backend enum value now both read `VAST`. Existing stored rows are migrated to the new value.
* Reading a storefront now re-evaluates operator-domain verification against the customer's (or parent's) registered domain, so storefronts that were saved before auto-verification was available no longer stay stuck as unverified.
* Storefronts operated by a child customer now auto-verify against the parent organization's registered domain when the child's own domain is absent or different, so partner-adapter storefronts no longer require manual verification.

## 2.75.2 — April 21, 2026 at 7:32 PM UTC

* Fixed a bug where the `description` field on advertisers was silently dropped on create and update, and was never returned from get or list endpoints.
* Fixed an issue where newly invited users could not see any seats after accepting their invitation. All users now have implicit access to all active seats within their customer, with permissions derived from their customer-level role.
* Show the Stripe Connect billing dashboard (Account / Balances / Payments / Payouts) for all parent and standalone customers on the Billing settings tab, regardless of customer role. Configure the Stripe publishable key so the embedded Connect components actually load, and surface a clear error if the key is missing instead of rendering empty section containers. Also return users to the Billing settings tab after completing Stripe Express onboarding instead of the legacy admin billing page.
* MCP `api_call` now rejects POST/PUT/PATCH/DELETE requests with `CUSTOMER_SCOPE_REQUIRED` when the session's user has access to more than one customer and has not called `customer_switch` first. This prevents mutating requests from silently landing on the wrong customer. GET requests are unaffected. Agents must call `customer_switch` with the intended customerId before any mutating request in multi-customer sessions. Applies to both `/mcp/v2/buyer` and `/mcp/v2/storefront`.
* Require `bidPrice` when adding auction-priced products to a discovery session, and reject unknown `pricingOptionId`s at add time. Catches these errors early instead of failing later at campaign execution.

## 2.75.0 — April 21, 2026 at 4:01 PM UTC

* Added an Activity page for buyers that shows a timeline of actions taken on your campaigns, media buys, and related resources (creations, edits, archives, executions, pauses). Filter the feed by time period, advertiser, and campaign. The `GET /api/v2/buyer/campaigns` endpoint now also supports an `includeArchived=true` query parameter for retrieving archived campaigns.
* Add pacing periods to campaigns. Campaigns can define time-based spend periods with weights or hard budgets. On execution, products are automatically split into per-period ADCP packages with proportional budgets and period-specific flight dates.
* Fixed a 500 error when deleting creative manifests by removing a reference to a non-existent `archived_at` column on the `creatives` table.
* Fixed creatives not propagating to media buys when an existing creative manifest is updated, and added cascade cleanup when a creative manifest is deleted. Non-DRAFT media buys now correctly create a new pending-approval version and notify the sales agent via ADCP when creatives are removed, so the change follows the normal approval flow instead of silently mutating the active version. An empty creative list is now propagated to the sales agent as a clear-all instruction rather than being skipped.
* Creative upload UI now shows the list of format IDs still required based on the products selected for the campaign. The `GET /campaigns/:campaignId/creatives/templates` response now returns `campaign_format_ids` populated from the campaign's products (sourced from media buys and the discovery session) instead of an empty array.
* The `update_campaign` and `list campaigns` responses now include the creatives assigned to each media buy and package, so callers can confirm which creatives are linked without issuing a follow-up query. Updating a media buy's creatives now also populates each package's `creative_assignments`, filtered by the formats accepted by that package's product.

## 2.74.0 — April 20, 2026 at 10:38 PM UTC

* Added `allocatedBudget` and `unallocatedBudget` computed fields to the `Campaign` resource returned by `GET /api/v2/campaigns` and `GET /api/v2/campaigns/:id`. These expose how much of the campaign budget is currently allocated to active media buys (including performance spend from archived media buys) and how much remains available for new media buys, without requiring clients to sum media buy budgets themselves.
* Added a new `GET /api/v2/buyer/campaigns/:campaignId/media-buy-status` endpoint that polls sales agents for the live status of all media buys within a campaign. Also available via the `api_call` MCP tool as operation `get_media_buy_status`. A background sync now periodically reconciles media buy statuses to catch transitions that may have been missed by webhooks.
* Fixed customer switching for non-admin users in the MCP integrations. The `customer_switch` tool is now available in the v2-buyer and v2-storefront MCP integrations, so any user can switch into a customer they have an active membership on (previously only SuperAdmin users could switch via the admin tool).
* Fixed MCP sessions being dropped after 4 hours of active use. Sessions now stay alive as long as there is ongoing activity, matching the intended idle-timeout behavior.
* Fixed `GET /api/v2/buyer/reporting/metrics?view=timeseries&download=true` so the generated CSV now matches the summary export columns plus a `Date` column, with one row per hierarchy leaf (advertiser → campaign → media buy → package) × day. Previously the export silently returned the summary (hierarchy) CSV with no date breakdown, regardless of the `view` parameter.

## 2.73.0 — April 20, 2026 at 4:14 PM UTC

* Added per-package breakdown to the reporting metrics response. Each media buy now exposes its packages with per-package metrics, and every package includes both `productId` and the human-readable `productName`.
* Added a `metadata` field to optimization suggestions, allowing arbitrary contextual data to be stored and returned alongside suggestion details.

## 2.72.0 — April 17, 2026 at 9:04 PM UTC

* Enforce campaign flight date guardrails on `PATCH /api/v2/buyer/campaigns/:id`. Updates now reject flight date changes that would conflict with non-DRAFT media buys (start before earliest active media buy, end before a media buy's start or end). Cascade failures to DRAFT media buys now fail the update instead of being silently logged.
* Tracking pixel URLs now always include `{MEDIA_BUY_ID}` and `{PACKAGE_ID}` as DSP-resolved macro placeholders, alongside existing `{AXEM}` and `{TMPX}` macros. These values are resolved by the publisher at impression time, allowing creatives and their trackers to be reused across multiple media buys and packages.
* Agents now auto-activate when authentication credentials are configured, removing the need for a separate activation step before going live. Added auth credential editing to the storefront seller onboarding flow.
* Exposed four v2 storefront onboarding endpoints through the MCP `api_call` dispatcher so AI agents can run the full onboarding flow: `POST /storefront/resolve-brand`, `GET /storefront/discover-agents`, `POST /storefront/notifications/provision`, and `GET /storefront/notifications/status`. `PUT /storefront` via MCP now also auto-verifies `operatorDomain` when it matches the caller's customer domain, matching the REST behavior.

## 2.70.0 — April 17, 2026 at 5:05 PM UTC

* Audience sync notification emails now name the specific audiences that were synced and summarise the outcome for each, so recipients can tell at a glance which audience the email is about.
* Campaign execution now returns an error when the linked discovery session is not found, instead of silently succeeding with no changes.
* Fixed media buy creation to default start\_time to today when not provided or when the date is in the past. Also auto-corrects stale start\_time at execution time to prevent errors from draft media buys created before their execution date.
* Made media buy start\_time optional — defaults to campaign start date (if future) or today.

## 2.69.0 — April 16, 2026 at 9:04 PM UTC

* Allow customers to configure an organization-wide notification email address and manage email notification type preferences from the org settings page.
* Redesigned the buyer reporting table with a "Show percentages" toggle, improved visual hierarchy for advertiser/campaign/media buy rows, and aligned empty states with the design system.
* Fixed an issue where creatives added to a campaign after media buy execution were not assigned to packages on the sales agent side.
* Increased per-audience member limits for the audience sync endpoint from 10,000 to 100,000 for both add and remove operations.

## 2.68.0 — April 16, 2026 at 3:09 PM UTC

* Fixed re-executing an active campaign with new products for the same sales agent now correctly creates additional media buys instead of silently skipping them.
* Fix customer switching for SELLER accounts by moving role-agnostic routes (accounts, service tokens, notification preferences, contracts, Slack configuration, ToS) from buyer-only router to a shared router accessible by all customer types.

## 2.67.0 — April 16, 2026 at 1:04 AM UTC

* Fixed an issue where the OAuth authorization popup window would not reliably close after completing authorization. The OAuth completion page now notifies the originating window when authorization is complete, allowing connected sessions to refresh automatically without a manual page reload.

## 2.66.0 — April 15, 2026 at 8:08 PM UTC

* The Buyer API has been migrated from Sales Agents to Storefronts. The new `GET /api/v2/buyer/storefronts` and `GET /api/v2/buyer/storefronts/:storefrontId` endpoints replace the previous sales agents endpoints, returning storefronts with their associated inventory sources and credential/connection status.
* Credentials for inventory sources are now registered via `POST /api/v2/buyer/storefronts/:storefrontId/sources/:sourceId/credentials`, replacing the previous per-agent credential registration endpoint.
* Registered credentials can now be listed via `GET /api/v2/buyer/storefronts/credentials`.
* API error responses now follow a consistent envelope format: `{ "data": null, "error": { "code": "...", "message": "...", "field": "...", "details": {} } }`. The `field` property identifies which specific input caused the error when applicable.
* MCP tool errors now return structured error objects with `code`, `message`, `field`, and `suggestion` fields in addition to a human-readable text message, making it easier to handle errors programmatically.
* Two new error codes are now documented: `INVALID_STATE` (400, operation not allowed in current resource state) and `INTERNAL_ERROR` (500, contact support).
* Fixed an issue where the `agentId` field was incorrectly included in buyer storefront API responses.
* Fixed an issue where buyer storefront queries used an incorrect column, which could cause incorrect results.
* Fixed a bug where users with an invalid customer ID in the URL were not properly redirected to their correct customer context.
* Fixed back navigation, password validation, and rate limiting behavior in the sign-up flow.
* Fixed an issue where parent customer accounts were incorrectly blocked by the buyer/seller role gate.
* Added `productId` to package-level reporting metrics.

## 2.65.0 — April 15, 2026 at 1:50 PM UTC

* Added new Slack webhook integration endpoints under `/api/v2/buyer/slack-configuration`, allowing buyer admins to connect a Slack channel to receive platform notifications.
* `GET /api/v2/buyer/slack-configuration` retrieves the current Slack configuration; the webhook URL is masked in the response for security.
* `PUT /api/v2/buyer/slack-configuration` creates or updates the Slack configuration, accepting a webhook URL, enabled state, and a list of notification event types to subscribe to.
* `DELETE /api/v2/buyer/slack-configuration` removes the Slack configuration and stops all Slack notifications.
* `POST /api/v2/buyer/slack-configuration/test` sends a test message to the configured Slack channel to verify connectivity.
* All Slack configuration endpoints require admin-level access; requests from non-admin users will receive a `403` response.
* Platform notifications are now automatically delivered to a customer's configured Slack channel when the relevant event type is enabled.
* Fixed an issue where seller and buyer access permissions were not correctly applied in certain authentication scenarios.

## 2.64.0 — April 14, 2026 at 10:53 PM UTC

* Added refinement support to the `POST /api/v2/buyer/discovery/discover-products` endpoint: you can now pass a `refine` array with a `discoveryId` to iteratively refine discovery results (e.g., "more video options", omit a product, or get more like a specific product). The response includes a `refinementApplied` field describing how each instruction was handled.
* Notification preferences have changed from opt-out to opt-in. The `GET` and `PUT` `/api/v2/buyer/notification-preferences` endpoints now use an `optIns` field instead of `optOuts`. Only explicitly opted-in notification types will be delivered.
* Fixed a bug where the OAuth callback for storefront partner integrations would show a generic error instead of the actual error message returned by the OAuth provider.
* Fixed an issue where the OpenAPI YAML spec was not resolved correctly in production, which could cause spec-serving endpoints to fail.
* Fixed an issue where trace IDs were being surfaced in user-facing error messages; errors now contain only relevant context.
* Improved error logging for campaign creation failures to surface more actionable debug information.

## 2.63.1 — April 14, 2026 at 5:01 PM UTC

* The user impersonation list now returns all available users instead of being capped at 50, making it easier to find and select users in larger organizations.
* Format group names in the creative format dropdown now display consistently using the format's source URL, improving clarity when working with multiple format sources.

## 2.63.0 — April 14, 2026 at 4:19 PM UTC

* When creating a creative, you can now provide a VAST tag URL directly as a primary asset by selecting the new "URL" tab and choosing the "Video VAST" type.
* Creative creation now supports a "Webhook" tab, allowing you to configure a webhook endpoint (with method, timeout, response type, and optional HMAC or API key security) as the primary creative asset source.
* The `VIDEO_VAST` value is now supported for the `url_type` field on URL assets when creating creatives via the API.
* Fixed an issue where media buy execution could fail incorrectly when the response contained an empty errors array rather than actual errors.

## 2.62.0 — April 14, 2026 at 3:20 PM UTC

* When a user signs up under an existing customer organization, the relevant customer admins are now notified automatically.
* Products can now be removed from completed discovery sessions, not just active ones.
* Fixed an issue where email notification suppression was not applied consistently across all token types.
* Fixed an issue with creative sync where assignment data was not being formatted correctly, which could cause sync requests to fail or behave unexpectedly.

## 2.61.0 — April 14, 2026 at 1:47 PM UTC

* The `ARCHIVED` storefront status has been removed. Storefronts that were previously archived have been migrated to `DISABLED` status. Valid statuses are now `PENDING`, `ACTIVE`, and `DISABLED`.
* Notification emails for user-initiated actions (such as optimization suggestions) are now sent only to the user who triggered the action, rather than to all users on the account.
* Campaign health events now trigger notifications when a campaign becomes active or transitions away from active status, replacing generic create/update/delete notification events.
* Users who are members of a child account can now see their parent organization and sibling accounts in the customer context list, providing complete hierarchy visibility.
* Tracking pixels now include the `tmpx={TMPX}` macro in addition to the existing `axem={AXEM}` macro on both impression and click tracker URLs.

## 2.60.0 — April 13, 2026 at 6:49 PM UTC

* The Storefront API now exposes a full set of signals management endpoints: create, list, get, update, delete, and discover signals (`POST/GET/PUT/DELETE /api/v2/storefront/signals` and `POST /api/v2/storefront/signals/discover`).
* The storefront `enabled` boolean field has been replaced with a `status` field supporting four lifecycle states: `PENDING`, `ACTIVE`, `DISABLED`, and `ARCHIVED`. Clients should update any code that reads or writes `enabled` to use `status` instead.
* Status transitions are now validated — for example, an `ARCHIVED` storefront cannot be transitioned to any other state.
* The `customerId` field on the delete user endpoint is now optional; requests without it will succeed rather than returning a validation error.
* The `ask_about_capability` tool now returns complete documentation sections without truncation, ensuring responses include the full context needed to answer capability questions.

## 2.59.0 — April 13, 2026 at 4:31 PM UTC

* The `api_call` tool now supports a named `operation` parameter (e.g., `"operation": "list_advertisers"`) as an alternative to specifying `method` and `endpoint` directly, reducing the chance of incorrect HTTP methods or malformed paths.
* When an `api_call` fails due to a malformed endpoint (missing path prefix, trailing slash, etc.), the API will now automatically attempt to correct and retry the request rather than returning an error immediately.
* OAuth is now supported when creating or editing inventory sources in the UI.
* Child customer users can now see their parent organization and sibling accounts in the customer selector, enabling easier navigation across accounts in a hierarchy.
* Fixed an issue where email notifications were not being delivered due to missing configuration in the API deployment.

## 2.58.0 — April 12, 2026 at 9:46 AM UTC

* During signup, the company name field is now pre-filled using a brand registry lookup based on your email domain, replacing the previous email domain parsing heuristic. When a match is found, a confirmation message ("We found your company in the brand registry.") is shown in the form.
* The `POST /auth/check-email-availability` endpoint now returns an optional `suggestedCompanyName` field in the response when a company name can be resolved from the email domain for new customers.
* Rate limiting has been applied to `POST /auth/check-email-availability`, consistent with other signup endpoints.
* Authentication status checks are now cached client-side for up to 2 minutes, reducing redundant network requests during navigation while maintaining session security.

## 2.57.2 — April 11, 2026 at 4:39 PM UTC

* OAuth and SSO users signing up will now automatically skip the personal details step, as their name and email are pre-filled from the identity provider.
* Fixed an issue where child accounts could fail to resolve their active contract correctly; child accounts will now properly fall back to the parent contract when needed.

## 2.57.1 — April 10, 2026 at 11:04 PM UTC

* The `accept_tos` tool is now available in the v2-buyer and v2-storefront MCP contexts, allowing organizations to accept the Terms of Service before making API calls.
* Advertiser API responses now correctly return the `id` field across all advertiser endpoints (list, create, get, update, restore).
* Validation error messages for tool inputs now consistently read "Validation error for tool" for clearer error reporting.
* Media buy status filtering now includes `pending_creatives` and `pending_start` statuses in addition to the existing `active`, `paused`, and `completed` states.

## 2.57.0 — April 10, 2026 at 10:21 PM UTC

* MCP tool calls now return clear, descriptive error messages immediately when required fields are missing or field values are invalid, rather than failing later with a less informative error.
* Advertiser API responses now consistently return the advertiser identifier as `id` across all endpoints (list, create, get, update, restore).

## 2.56.0 — April 10, 2026 at 7:58 PM UTC

* Administrators on a parent organization can now switch into and access child customer accounts without requiring explicit per-account permissions.
* The account list now includes child customers accessible through parent organization hierarchy, so all manageable accounts appear in the customer selector.
* A maintenance banner is now displayed in the application when scheduled or active maintenance windows are configured, showing relevant timing and status information.
* Fixed an issue where switching customer context could result in incorrect access permissions or an inconsistent impersonation state.
* Fixed an issue where child customers now correctly inherit their parent's contract and Terms of Service when they have no contract of their own.
* Fixed an issue where returning from an impersonated customer session now correctly restores the previous customer context and page location.
* Error messages shown in notifications now display the human-readable message instead of an internal error code when both are available.

## 2.55.0 — April 10, 2026 at 4:50 PM UTC

* Added notification preference opt-out controls: users can now manage which notification types they receive per channel via `GET /api/v2/buyer/notification-preferences` and `PUT /api/v2/buyer/notification-preferences`.
* In-app notifications now respect per-user opt-out preferences, automatically filtering out notification types the user has opted out of.
* Email notifications now respect per-user opt-out preferences, skipping delivery for users who have opted out of a given notification type.
* Signup flow now accepts only **Advertiser** and **Seller** as account types; previously accepted types such as "Agency" and "Other" are no longer valid.
* Invitation requirement for joining an existing organization is now enforced by default for all users, without requiring a feature flag to be enabled.
* The audience sync member removal schema has been aligned with the latest spec; the `externalId`, `hashedEmail`, `hashedPhone`, and `uids` fields are now consistently structured.
* Fixed a security issue where an OAuth re-registration could allow one customer's credentials to be overwritten by another customer using the same account identifier.
* Fixed an issue where switching to a customer account via the API could return users scoped to the wrong customer.
* Fixed authentication callback handling to correctly display a fallback for non-standard auth flows and handle missing customer state gracefully.
* Fixed cross-links on the authentication pages to use correct navigation behavior, preventing unintended full page reloads.
* Fixed Terms of Service and Privacy Policy links on the signup page to render as standard anchor links.
* Fixed the `customer_switch` MCP tool to return a clear validation error when a non-numeric or invalid customer ID is provided, rather than an internal database error.

## 2.54.0 — April 8, 2026 at 9:11 PM UTC

* Users now receive email notifications when new notifications are created, keeping teams informed of important updates without needing to log in.
* A new suggestion apply flow has been added with webhook status tracking, allowing optimization suggestions to be applied and their progress monitored end-to-end.
* Discovery session activity is now logged for analytics, enabling better insights into marketplace search and product interactions over time.
* The UI now preserves the intended destination path through account resolution, so users are correctly redirected to their original target after authentication.
* Packages are now associated with a single product via a direct relationship, improving consistency and reliability of package-product data.

## 2.53.0 — April 8, 2026 at 2:14 PM UTC

* Added a new endpoint `POST /api/v2/buyer/advertisers/:advertiserId/measurement-data/sync` for syncing advertiser performance measurement data to the ingestion pipeline.
* Unversioned API paths `/api/buyer` and `/api/storefront` now permanently redirect (308) to their versioned equivalents `/api/v2/buyer` and `/api/v2/storefront`.
* The `source` field on measurement data objects now accepts only the values `advertiser`, `mmp`, or `measurement_partner` instead of any free-form string.
* A new optional `source_metric_name` field is available on measurement data objects for mapping raw partner metric names.
* Trace context (`traceparent`) and MCP session ID headers are now propagated to all downstream service calls, improving end-to-end request traceability.
* Fixed a bug where customer-level API users were incorrectly blocked from updating or deleting campaigns that belong to a specific seat within their organization.
* Fixed a data corruption issue where brand profile URLs were being double-serialized, which could cause campaign execution to fail or send malformed data.
* Fixed a bug where the `brand_manifest` URL field was not validated, allowing invalid values to be stored and forwarded.
* Improved error messages when a tactic cannot be created because no brand is linked to the campaign, replacing a technical internal message with a clearer user-facing explanation.
* When creating an advertiser, the brand is now automatically saved without requiring a separate "Register & Create" action.

## 2.52.0 — April 7, 2026 at 4:18 PM UTC

* Added new optimization suggestion endpoints to the Buyer API, allowing you to list, view, approve, and reject AI-generated optimization suggestions for your media buys via the `api_call` tool.
* Expired OAuth tokens are now automatically refreshed when resolving agent accounts, reducing authentication failures for OAuth-connected integrations.
* API responses now include an `x-trace-id` header, making it easier to correlate requests with support when troubleshooting issues.
* Fixed a bug where the campaign optimizer job used an incorrect argument format, which could cause optimization runs to fail silently.
* MCP sessions are now reliably consistent across server instances, eliminating cases where customer switches or seat selections made on one server were not reflected when requests routed to a different server.

## 2.51.0 — April 6, 2026 at 5:38 PM UTC

* Added a new testing endpoint `POST /api/v2/testing/deleteSsoConnection` that allows deletion of all SSO connections for a given WorkOS organization ID, returning 204 whether connections existed or not (idempotent). Requires `SUPER_ADMIN` authentication.
* Seat-scoped API tokens now automatically infer the advertiser ID, allowing use of `/advertisers/me/` in endpoint paths as a shorthand that resolves to your token's advertiser. Explicit advertiser IDs in requests are validated against the token scope and will return a clear error on mismatch.
* Advertiser account linking now returns a validation error immediately if any requested account is not found or has a sandbox/production mismatch, rather than silently skipping the invalid accounts.
* Fixed a bug where the `deleteUser` cleanup endpoint would return a `502` error if the backend deletion step failed; the operation now completes successfully and reports the partial result.
* Non-OAuth inventory source agents are now created in `PENDING` status instead of being auto-activated on inventory source creation.
* Fixed the Terms of Service modal so the ToS link is now clickable and opens correctly.
* Fixed an issue where `isCustomerSwitched` was not correctly detected for member-level customer switches, ensuring contract and ToS enforcement behaves correctly when switching between customers.
* The measurement config API list endpoint now uses `limit` instead of `take` as the pagination parameter, and response data is accessed at `data.data.items`.

## 2.50.1 — April 3, 2026 at 6:50 PM UTC

* Fixed an issue where the `authConfigured` field on storefront agent responses could incorrectly reflect a non-existent configuration source, ensuring it now accurately indicates whether authentication is set up.

## 2.50.0 — April 3, 2026 at 5:58 PM UTC

* Inventory sources can now be edited after creation, including updating the endpoint URL, protocol, authentication type, and credentials.
* A new hosted sales agent setup flow is available when creating inventory sources, simplifying agent onboarding.
* Agents associated with non-OAuth inventory sources are now automatically activated upon source creation, removing the need for a manual activation step.
* A new `GET /billing/accounts` endpoint is available for parent customers to view billing status across all managed child accounts.
* Billing configuration is now scoped to the customer account rather than the storefront, enabling more consistent billing management across storefronts.
* Parent customers can now accept the Terms of Service directly without needing to switch accounts first.
* The Terms of Service acceptance flow now automatically provisions the required contract, removing a manual step that previously blocked new customers.
* The ToS enforcement error code has been unified: all cases where ToS acceptance is required now return `TOS_ACCEPTANCE_REQUIRED` instead of the previous `CONTRACT_REQUIRED` code.
* Fixed an issue where customer session context (including account type) was not correctly persisted when switching between parent and child accounts.
* Fixed a bug where parent-account access restrictions were incorrectly applied after switching away from a child account.
* Fixed a bug where a missing `bid_price` field in campaign execution returned an unformatted error; it now returns a clear validation error.
* Fixed an issue where products added via product IDs were missing the `bid_price` field.
* Fixed an issue where the `generation_prompt` asset status and creative brief were not resolving or clearing correctly.
* Fixed a bug where tactic creation failed when no agent was associated with the campaign.
* Fixed an issue where the SSO configuration feature flag was not evaluated for super admins and sellers.
* Fixed distributed tracing context propagation so tool call spans are correctly linked to their originating HTTP request.

## 2.49.0 — April 2, 2026 at 4:45 PM UTC

* The buyer campaigns list endpoint now supports an `includeMediaBuys` query parameter (`true`/`false`); when enabled, each campaign in the response will include its associated media buys with products, packages, and delivery data.
* The Creative Assets page filters (Advertiser, Campaign, Creative) have moved into the page header, and the Campaign dropdown no longer requires selecting an advertiser first — you can now search campaigns independently.
* Selecting a campaign in Creative Assets will automatically resolve and set the matching advertiser, improving navigation flow.
* The billing readiness check on the Storefront page is now clickable for admin users, navigating directly to the billing settings page.
* Org settings now support deep-linking to a specific tab via a `?tab=` query parameter (e.g. `?tab=billing`), and tab changes update the URL accordingly.
* Fixed an issue where media buys were missing from the buyer campaigns list response.
* Fixed an issue where accounts with a `restricted` billing onboarding status were not shown the onboarding card to complete their Stripe setup.
* Fixed a loading state issue on the billing page where content would not show a skeleton placeholder immediately on load.
* The onboarding card for billing now shows a different message for accounts that have a partially connected Stripe account, prompting them to finish setup.

## 2.48.0 — April 2, 2026 at 2:13 PM UTC

* Storefront readiness status now surfaces partial states and failure details, giving you clearer visibility into why a storefront check did not fully pass.
* Creative assignments are now reliably tracked per product based on format compatibility, ensuring the correct creatives are associated with each product in a media buy.
* Super admins now correctly bypass the alpha opt-in feature flag, giving them full API access without needing explicit flag enrollment.
* Compliance track results now include an optional `failureReason` field in the API response, explaining why a track failed or only partially passed.

## 2.47.0 — April 1, 2026 at 8:10 PM UTC

* When creating a storefront, the `platformId` is now automatically generated from the storefront name (e.g. "CVS Media" becomes `cvs-media`), so you no longer need to provide it manually.
* Campaign creatives are now automatically synchronized to media buys when a campaign is updated, removing the need to manage creative assignments manually.
* Product discovery now uses your storefront's configured inventory sources first, with a fallback to the broader agent catalog, so buyers see a more curated and relevant set of products.
* Storefront compliance checks now load asynchronously, reducing wait times when accessing storefront readiness information.
* A new endpoint `GET /api/v2/buyer/creative-dashboard-url?advertiserId={advertiserId}&campaignId={campaignId}` returns a fully-resolved URL for managing creative assets, replacing the previous two-step lookup flow.
* Fixed an issue where the contract page incorrectly displayed "No active contract" even when an active contract existed.
* Fixed the discover products selection bar and recommended plan flow to behave correctly.
* Fixed an issue where switching customers did not redirect to the homepage; role-based route guards are now enforced on navigation.
* The advertiser status filter has been moved to the page header dropdown for easier access.

## 2.46.0 — April 1, 2026 at 1:09 AM UTC

* Non-admin users can now list accessible customers and switch between customer contexts via the MCP `customer_list` and `customer_switch` tools, without requiring administrator privileges.
* Media buys can now be canceled or archived directly through the campaign update endpoint (`PUT /api/v2/buyer/campaigns/{id}`) using the new `action` field (`"cancel"` or `"delete"`) in the `mediaBuys` array.
* The `/tools` endpoint now enforces Terms of Service acceptance, returning a `TOS_ACCEPTANCE_REQUIRED` or `CONTRACT_REQUIRED` error if the organization has not completed onboarding requirements.
* Localhost URLs are now permitted for storefront agent registration when running in a development environment, enabling local agent testing.
* Fixed an issue where account API keys were not displaying correctly and new key creation was failing.
* Fixed a bug where the storefront MCP endpoint was not mounting correctly following a recent rename.
* Fixed an issue where switching organizations from the org settings page did not navigate to the home page as expected.
* Fixed a bug where the admin portal could be incorrectly redirected to a customer-scoped URL.
* Fixed an issue where media buy cache was not invalidated after product budget updates, causing stale data to be returned.
* Fixed a bug where Terms of Service enforcement could be bypassed when switching accounts.
* Fixed format previews not displaying for certain creative types.
* Fixed upstream error details not being forwarded correctly in event logging responses.
* The `confirmStandaloneConversion` field has been removed from the child account creation request body; standalone conversion now happens automatically.
* The Storefronts section has been renamed to "Storefront" in the UI and now includes an edit dialog.

## 2.45.0 — March 31, 2026 at 3:46 PM UTC

* When a new seller account is created, a default storefront is now automatically provisioned for that account.
* Existing seller accounts with a single active sales agent have been retroactively provisioned with a default storefront.
* When a sales agent is registered, a storefront and inventory source are now automatically created for the seller if one does not already exist.
* Product discovery responses now include empty result groups for sales agents that were successfully queried but returned no matching inventory, making it clear the agent was reached but had no products to offer.
* When a sales agent returns zero products during discovery, the response now includes a message indicating no matching inventory was found and suggests adjusting the brief, budget, or filters.
* Fixed an issue where empty results from a sales agent during product discovery were indistinguishable from a null or failed response.
* Failed sales agent queries are no longer surfaced to end users in discovery summaries; only successful agent results are shown.

## 2.44.0 — March 31, 2026 at 2:19 PM UTC

* OAuth redirect URIs can now be managed dynamically, enabling faster onboarding of new integration partners without requiring a service deployment.
* Access to MCP and API features is now gated behind an alpha opt-in flag, allowing gradual rollout to eligible users.
* The buyer assistant AI has been updated with additional guardrails to reduce inaccurate or fabricated responses.
* Fixed an issue where an empty dropdown in the Creatives section was not labeled clearly and could not be clicked.
* Fixed an issue where the Creatives card was incorrectly visible to seller users on the home page.

## 2.43.1 — March 30, 2026 at 10:19 PM UTC

* The Event Sources API has been streamlined: individual create, get, update, and delete endpoints have been removed in favour of the sync (`POST /api/v2/buyer/advertisers/:advertiserId/event-sources/sync`) and list (`GET /api/v2/buyer/advertisers/:advertiserId/event-sources`) endpoints only.
* Fixed an error on the reporting page that caused it to fail to load metrics data correctly.

## 2.43.0 — March 30, 2026 at 9:15 PM UTC

* The Partner API has been renamed to the **Storefront API**. All endpoints previously under `/api/v2/partner/` are now available at `/api/v2/storefront/`, and requests to the old path will be automatically redirected.
* The MCP endpoint for the Storefront API has moved from `/mcp/v2/partner` to `/mcp/v2/storefront` (and `/mcp/partner` to `/mcp/storefront`).
* A new `GET /api/v2/buyer/advertisers/{advertiserId}/events/summary` endpoint is available, returning hourly-aggregated event counts (impressions, clicks, conversions, measurements, and MMP events) for an advertiser. Supports optional filtering by event type and custom date ranges.
* The events summary endpoint defaults to the last completed UTC hour when no date range is specified, and event data may take up to 1 hour to appear after being reported.
* Two new audience notification event types (`audience.synced` and `audience.sync_failed`) are now supported and will be delivered via the notifications system.
* All authenticated pages now include the customer ID in their URLs (e.g., `/208/reporting`), making links shareable across users and customer contexts.

## 2.42.0 — March 30, 2026 at 3:32 PM UTC

* The default UTM parameters applied to advertiser landing page URLs have been updated to better align with GA4 standards: `utm_medium` is now included with the value `agentic`, and the creative parameter now uses the standard `utm_content` key instead of `utm_creative`.
* Fixed an issue where the Advertisers management table appeared empty even when data was successfully returned by the API.

## 2.41.0 — March 30, 2026 at 3:50 AM UTC

* The Creative Manifest API (v2) is now available, enabling campaign-scoped management of creative assets including HTML processing, format previews, ADCP template detection, and tracking pixel support. Manifests are created and uploaded via the dashboard UI; list, get, update metadata, and delete operations are available via the API.
* Audience sync now delivers a push notification webhook to the buyer upon completion. Provide a `pushNotificationConfig` (with `url`, `authentication`, and `token`) in the sync request body to receive the callback.
* Storefronts now enforce a readiness gate before going live: setting `enabled: true` returns a `400` error if required readiness checks are not yet passing. Setting `enabled: false` is always allowed without restriction.
* Inventory source registration now makes `sourceId` optional. When omitted, a `sourceId` is automatically generated from the `name` field (e.g. `"Auto Generated Source"` becomes `"auto-generated-source"`).
* The Conversion Events API (`/advertisers/{advertiserId}/conversion-events`) has been removed. Conversion tracking is now handled via event sources; use `GET /advertisers/{advertiserId}/events/summary` with `type: "conversion"` to view available events for optimization.
* Fixed a bug where property list responses contained incorrect data and missing entries. Properties are now sourced from an updated registry for improved accuracy.
* Fixed an issue where per-agent discovery errors were silently swallowed; they are now surfaced in debug output for easier troubleshooting.
* Fixed an issue where the Create Storefront modal opened automatically on page load.

## 2.40.0 — March 27, 2026 at 12:26 AM UTC

* The `POST /api/v2/buyer/accounts/create-child` endpoint now requires a `customerRole` field (`BUYER` or `SELLER`) when creating a child account.
* Creating a storefront no longer requires a `platformId` — if omitted, one is automatically generated from the storefront name.
* A new storefront billing page is available, providing Stripe Connect integration for sellers to manage payments, payouts, and balances.
* A new storefront management page is available, showing readiness checks and configuration status for your storefront.
* Discovery card product listings now include biddable pricing indicators and updated fonts and styling.
* The `advertiser_id` field has been removed from the measurement data request body; it is now taken from the URL path parameter and injected automatically.
* Pricing option data now includes a `priceGuidance` object with floor, p25, p50, p75, and p90 price percentile fields when available.
* Fixed an issue where media buy requests were not compatible with older publisher versions; the `buyer_ref` field is now sent in the expected format for all publisher versions.
* Fixed an issue where the customer dropdown was disabled and not properly visible during superadmin impersonation sessions.
* Fixed an issue where the billing page did not prompt users to set up a storefront when none existed.
* The OAuth redirect URI for `bayes.fly.dev` is now supported.

## 2.39.0 — March 26, 2026 at 1:19 PM UTC

* Added a new `POST /api/v2/buyer/advertisers/:advertiserId/log-event` endpoint for ingesting conversion and marketing events (purchases, leads, page views, etc.) with support for user matching, custom data, and test event codes.
* Added a new `POST /api/v2/buyer/accounts/create-child` endpoint allowing admin users to create child accounts under their organization hierarchy, including support for converting standalone accounts.
* The `GET /api/v2/buyer/campaigns` endpoint now accepts a `mediaBuyStatus` filter parameter (single value or array) to narrow campaign results by the status of their associated media buys.
* The `resolve-account` response now includes `endpointUrl` and `authenticationType` fields.
* Users with pending invitations are now automatically routed to the correct customer organization during signup, and the email availability check response now surfaces `pendingInvitations` when applicable.
* Added a `POST /api/v2/buyer/campaigns/:id/reactivate` endpoint to reactivate a paused or stopped campaign and cascade the update to its associated media buys.
* The property list resolve endpoint has moved from `GET /api/v2/buyer/property-lists/:listId/resolve` to `GET /lists/:listId` to align with the expected URL convention used by sales agents.
* Audience webhook payloads now use `camelCase` field names consistently.
* Fixed an issue where users signing up for an existing domain with a pending invitation could be incorrectly blocked from completing registration.
* Reduced the per-agent discovery timeout from 90 seconds to 30 seconds, resulting in faster error responses when an agent is unreachable.
* The `MediaBuyStatus` enum now includes `CANCELED` and `INPUT_REQUIRED` as valid values across relevant API responses and filters.

## 2.38.0 — March 25, 2026 at 11:36 AM UTC

* Advertisers now support configurable UTM parameters (`utmConfig`) at creation and update, allowing you to define custom tracking parameters appended to landing page URLs during clickthrough. Defaults (`utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_media_buy`, `utm_package`) are applied automatically if no config is provided.
* Campaigns now support a `utmConfig` field to set campaign-level UTM parameter overrides, which take precedence over advertiser-level defaults for matching parameter keys. Use `deleteMissing: true` for replace mode, or omit it for additive updates.
* Storefront readiness checks now include live agent compliance results, giving you richer diagnostics on agent connectivity and compliance status.
* Discovery product browsing now caches enrichment results (descriptions and relevance summaries) across requests, so repeated browses within the same session return consistent, faster results.
* Fixed an issue where media buy validation errors (such as invalid dates, missing fields, or budget problems) were incorrectly treated as server errors instead of client errors, resulting in cleaner, more actionable error messages.
* Fixed signal tools failing when no seat was selected.
* Fixed an issue where the tracking endpoint used an incorrect authentication key, which could cause measurement sync requests to fail.

## 2.37.1 — March 24, 2026 at 5:48 PM UTC

* The Storefront API endpoints have been simplified: all storefront and billing routes now use `/storefront` (singular) instead of `/storefronts/:platformId`, since each customer has exactly one storefront. The `platformId` path parameter is no longer required for any storefront, billing, or inventory source operations.
* The `GET /storefront` endpoint now serves as the single way to retrieve your storefront, replacing both the previous `GET /storefronts` and `GET /storefronts/:platformId` endpoints.
* Billing endpoints (`/storefront/billing`, `/storefront/billing/connect`, `/storefront/billing/status`, etc.) no longer include `platformId` in their responses.
* Fixed an issue where users who had already been migrated to the new authentication system would receive an unhelpful error during login; they now correctly receive an "invalid credentials" response instead of being sent through a redundant migration flow.
* Improved the error message shown when account setup fails during login migration — the message now suggests resetting your password and no longer references internal migration processes.
* System tokens now have full administrative access when using the `customer_switch` tool, resolving an issue where those operations were incorrectly restricted.

## 2.37.0 — March 24, 2026 at 12:28 PM UTC

* Added a new `POST /api/v2/buyer/syndicate-audience` endpoint that triggers an audience syndication backfill. On success, it returns a `202 Accepted` response with an `operationId` (UUID) that can be used to track the operation.
* Fixed the request body format sent to the audience sync endpoint to use camelCase field names, aligning with standard API conventions.

## 2.36.0 — March 24, 2026 at 8:14 AM UTC

* Added a new suggestion data structure to support optimization recommendations linked to campaigns and media buys.
* Fixed an issue where product selection in the media planning interface could break due to a field naming mismatch, causing pricing options and biddable products to not display or behave correctly.
* Clarified API documentation to distinguish between using the `demo` flag (to return synthetic demo data) versus filtering reporting results by an advertiser or campaign whose name contains "demo".
* Fixed incorrect endpoint references in the v2 partner API documentation to match the actual available endpoints.

## 2.35.1 — March 24, 2026 at 1:06 AM UTC

* Reporting CSV exports are now available via the REST API using the `?download=true` query parameter on the reporting metrics endpoint; the response includes a `downloadUrl`, `fileName`, and an expiration timestamp valid for 7 days.
* Fixed a bug where the `offset` (and `limit`) pagination parameters were being ignored when listing advertisers through the API; pagination now correctly respects these values.
* Fixed MCP session errors that could cause requests to fail when a client reconnected or sent requests before completing the initialization handshake.
* Fixed MCP App UI rendering issues related to how widget display domains are resolved for different AI client types.

## 2.35.0 — March 23, 2026 at 3:59 PM UTC

* Storefront billing is now available via Stripe Connect. Partners can provision a connected account, complete onboarding, and view account status, balance transactions, and payouts through new endpoints under `/api/v2/partner/storefronts/{platformId}/billing`.
* Storefronts now accept an optional `publisherDomain` field (e.g. `"cvs.com"`) on create and update, used for Stripe Connect business profile setup.
* Notifications now include a `status` field (`success`, `error`, `warning`, or `info`) and can be filtered by status when listing.
* Service tokens can no longer be created using another service token — token creation now requires a user context. Requests authenticated with a service token will receive a `400` error if they attempt to mint new tokens.
* Fixed an issue where seat invitations were not visible immediately after login. Invitation processing now completes before the auth response is returned.
* Fixed an issue where seat auto-assignment was not triggered when inviting a new customer member via the v1 invite flow.
* Fixed an OAuth session loop and stuck callback page that could occur during MCP authentication.
* Fixed an issue where MCP session IDs provided in an invalid format were silently accepted, which could cause sessions to fail to persist correctly. Invalid session IDs are now rejected early with a warning.
* Fixed a race condition in SSE connections where heartbeat writes could trigger a headers-already-sent error.
* Fixed MCP request IDs not being consistently propagated across the full session lifecycle, improving log correlation.
* The advertiser list endpoint now returns more results per page, matching what the UI displays.
* ChatGPT plugin OAuth now correctly supports dynamic redirect URIs, resolving authentication failures for ChatGPT-initiated OAuth flows.

## 2.34.1 — March 21, 2026 at 12:52 AM UTC

* Improved reliability of real-time streaming (SSE) connections by reducing the frequency of keepalive signals, preventing unexpected disconnections that some clients were experiencing during MCP sessions.

## 2.34.0 — March 20, 2026 at 11:12 PM UTC

* The List Advertisers endpoint (`GET /api/v2/buyer/advertisers`) now returns a paginated response with `items`, `total`, `hasMore`, and `nextOffset` fields instead of a flat array with separate `meta.pagination` wrapper.
* Pagination parameters for the List Advertisers endpoint have changed from `take`/`skip` to `limit`/`offset`, with a maximum page size of 10.
* The user management API now supports multi-customer views, returning each user's memberships across all accessible child customers instead of a single permission level per user.
* Inviting a user to a specific child customer is now supported via the optional `targetCustomerId` field on the invite endpoint.
* Updating a team member's role now accepts an optional `customerId` field, allowing parent account admins to update roles on child customer accounts.
* The measurement data sync endpoint (`POST /api/v2/buyer/advertisers/{id}/measurement-data/sync`) has updated field names: `start_date`/`end_date` are now `start_time`/`end_time`, and `event_id`/`event_value` are now `metric_id`/`metric_value`.
* The measurement data sync endpoint now requires `metric_id` (from a fixed set of supported metrics), `unit` (currency, count, ratio, or percentage), and at least one entity identifier (`advertiser_id`, `campaign_id`, `media_buy_id`, `package_id`, or `creative_id`). Currency code is required when `unit` is `"currency"`.
* Fixed an issue where campaigns in terminal states could be incorrectly re-executed; campaign status is now preserved correctly on failure.
* Fixed incorrect data returned by the measurement configuration API.
* The `POST /api/v2/buyer/accounts/create-child` endpoint has been removed.

## 2.33.0 — March 20, 2026 at 9:06 PM UTC

* The List Advertisers endpoint (`GET /api/v2/buyer/advertisers`) now returns a paginated response with `items`, `total`, `hasMore`, and `nextOffset` fields instead of a flat array with separate pagination metadata.
* Pagination parameters for List Advertisers have changed from `take`/`skip` to `limit`/`offset`, with a maximum page size of 10.
* The Measurement Data Sync endpoint now uses updated field names: `start_time`/`end_time` (replacing `start_date`/`end_date`), `metric_id`/`metric_value` (replacing `event_id`/`event_value`), and requires a `unit` field (`currency`, `count`, `ratio`, `percentage`). When `unit` is `currency`, a 3-letter ISO 4217 `currency` code is required.
* Measurement Data Sync now accepts additional optional fields: `source`, `source_platform`, `external_row_id`, and `advertiser_id`. At least one of `advertiser_id`, `campaign_id`, `media_buy_id`, `package_id`, or `creative_id` must be provided per measurement object.
* The `POST /api/v2/buyer/accounts/create-child` endpoint has been removed.
* Fixed an issue where campaign execution could be triggered when a campaign was already in a terminal state; campaign status is now correctly preserved on failure.
* Fixed an issue where completed media buys had an incorrect `valid_to` value set, which could affect versioning and data accuracy.
* Fixed MCP session authentication so that session state is reliably consistent across server instances, improving stability for multi-turn agentic workflows.
* The User Management tool now supports multi-customer access, allowing parent account admins to view and manage users across their child accounts in a single call.
* Member invitation now accepts a `targetCustomerId` parameter, allowing parent admins to invite users directly to a specific child customer.
* Updating a member's role now accepts an optional `customerId` parameter, allowing parent admins to update roles on child customer memberships directly.

## 2.32.0 — March 20, 2026 at 3:31 PM UTC

* Added a new `POST /api/v2/buyer/accounts/create-child` endpoint that creates a child account under the authenticated user's organization. Requires ADMIN role; automatically promotes standalone accounts to parent accounts and grants the requesting user admin access on the new child.
* The customer switcher in the application now includes a "New Account" option for eligible admin users, allowing child account creation directly from the navigation menu.
* The API keys page has been updated with an improved layout, clearer section titles and descriptions, and tabs for switching between personal and organization keys.
* Dialog titles for API key actions have been updated to use consistent casing (e.g. "Edit API key", "Delete API key", "API key created successfully").
* The "Delete API key" confirmation dialog now displays a cleaner confirmation message and uses a more appropriate button style.
* The API key secret dialog now shows a "Copied" confirmation tooltip when the token is copied to clipboard, and displays a clearer security warning message.
* The API keys list now displays up to 50 keys per page, up from 20.
* Fixed a layout issue on the API keys page where the list could overflow the screen; it now sizes to fit its content correctly.

## 2.31.0 — March 20, 2026 at 11:56 AM UTC

* The `GET /api/v2/buyer/campaigns/{campaignId}` response now includes `discoveryId`, `products`, and `productCount` fields for campaigns in **DRAFT** status, reflecting the products selected during the discovery workflow. These fields are not present on campaigns that have been executed.
* API requests to v2 REST routes are now blocked with a `403` error if your organization has not accepted the Terms of Service or does not have an active contract. Affected responses will include an error code of `TOS_ACCEPTANCE_REQUIRED` or `CONTRACT_REQUIRED` respectively. Account and contract management endpoints remain accessible regardless.
* Fixed an issue where pricing type detection could behave incorrectly in certain v2/v3 pricing scenarios, which may have caused errors when creating or executing campaigns with some pricing configurations.

## 2.30.0 — March 20, 2026 at 8:42 AM UTC

* Added a new `POST /campaigns/{campaignId}/auto-select-products` endpoint that automatically selects products and allocates budget for performance campaigns using AI-driven scoring, returning selected products, budget context, and a rationale explaining the selection strategy.
* API fields across campaigns, discovery, syndication, and catalog endpoints have been standardized to camelCase (e.g., `bid_price` → `bidPrice`, `is_fixed` → `isFixed`, `resource_type` → `resourceType`, `adcp_agent_ids` → `adcpAgentIds`, `publisher_domain` → `publisherDomain`). Update any requests and response parsing that reference the old snake\_case field names.
* Error responses from API tools now include a `recovery` field (`correctable`, `transient`, or `terminal`) to help clients determine whether to retry, prompt the user to fix input, or stop. HTTP status codes are also more precise (e.g., 404 for not found, 409 for conflicts, 429 for rate limiting).
* Validation error messages throughout the v2 API are now more descriptive and human-readable, making it easier to identify and correct invalid request payloads.
* Fixed a bug where duplicate products could appear in media buy queries.
* Fixed an issue where campaign update requests could incorrectly send conflicting identifier fields simultaneously, which caused update failures.
* Fixed enforcement of operator authentication requirements during agent authorization flows.

## 2.29.0 — March 19, 2026 at 7:38 PM UTC

* Added a new measurement data endpoint (`POST /advertisers/{advertiserId}/measurement-data/sync`) for syncing advertiser performance data as time-series events, supporting upsert semantics with up to 1,000 measurements per request.
* Added property list management endpoints (`/advertisers/{advertiserId}/property-lists`) for curating include/exclude lists of publisher domains that automatically apply to all campaigns under an advertiser.
* Added a domain validation endpoint (`POST /property-lists/check`) that checks domains against the AAO Community Registry, identifying blocked domains, normalizing URLs, and flagging unknowns.
* Added storefront management endpoints (`/partner/storefronts`) enabling partners to create and configure storefronts with inventory sources and an agent lifecycle, replacing the previous partner/agent registration flow.
* Added SCD Type 2 versioning for media buys — updating an active media buy now creates a `PENDING_APPROVAL` version; the original remains active until the publisher approves the change.
* Added a `debug` parameter to the product discovery endpoints (`POST /discovery/discover-products` and `GET /discovery/{id}/discover-products`) that returns detailed per-agent request/response logs when set to `true`.
* Added support for multiple credential sets per sales agent — customers can now register more than one set of credentials for the same agent, with a `credentialId` parameter on the account discovery endpoint to specify which credential to use.
* Added multi-account support with endpoints to list accounts (`GET /buyer/accounts`), get the current account (`GET /buyer/accounts/current`), and switch between accounts (`POST /buyer/accounts/switch`).
* The sales agent list endpoint now returns a maximum of 10 results per page and includes a `nextOffset` field in the response for easier pagination.
* Fixed an issue where child accounts incorrectly required users to accept terms of service when the parent account had already accepted.
* Fixed media buy budget calculations in v1 to correctly sum all products and round spend values.
* Fixed a sync failure that occurred after media buy versioning where associated packages could not be found.
* Removed partner CRUD endpoints (`GET/POST/PUT/DELETE /partner/partners`) from the v2 API; partner management is now handled through the storefront onboarding flow.

## 2.28.0 — March 18, 2026 at 8:11 PM UTC

* Campaigns now support an optional `catalogId` field on both create (`POST`) and update (`PUT`) requests, allowing you to attach a catalog to a campaign. Pass `null` to detach an existing catalog.
* The signal `keyType` enum has been updated: `liveramp` is renamed to `rampid`, and three new values are added — `uid2`, `euid`, and `pairid`.
* Parent customer accounts are now restricted from accessing most REST API endpoints directly. Affected requests will receive a `403 PARENT_ACCOUNT_RESTRICTED` error. Switch to a child account to regain access.
* When connecting an MCP client, users with an existing valid session are no longer shown a redundant login page — they are redirected directly to the callback, preventing duplicate browser tabs from opening.
* Media buys are now automatically transitioned to `COMPLETED` status once their end time has passed, keeping campaign and media buy statuses consistent without manual intervention.
* Fixed an issue where switching customer accounts in an MCP session did not correctly update permission checks for the new account's type.
* Fixed a bug where the MCP connector flow could display multiple OAuth pages during authentication.
* Resolved an issue where signals were being polled for media buys that had already passed their end time.

## 2.27.0 — March 13, 2026 at 9:49 PM UTC

* Added support for partner seats when creating organization-level API keys, allowing users to select both advertiser and partner seats with appropriate type disambiguation
* Enhanced audience sync processing to integrate with real-time syndication services, improving audience delivery performance
* Fixed dependency issues with Google Cloud services to ensure reliable BigQuery and Secret Manager operations

## 2.26.0 — March 13, 2026 at 6:06 PM UTC

* Added multi-currency support in product pricing displays, now showing proper currency symbols (€, £, ¥) based on product currency instead of defaulting to USD
* Added SSO configuration page for admin users to self-service setup single sign-on with their identity providers
* Fixed discovery endpoint performance issues that could cause timeouts during product searches
* Fixed data accuracy issues in V2 reporting by removing duplicate entries that could inflate metrics
* Improved load balancer timeout handling by increasing from 2 minutes to 4 minutes for better reliability
* Enhanced discovery session lookups by removing redundant filters that could slow down searches

## 2.25.0 — March 12, 2026 at 6:04 PM UTC

* Added advertiser name field to query responses for better identification and filtering
* Fixed media buy creation process to ensure proper validation order and prevent errors
* Improved authentication to support additional Google Cloud Platform credential types
* Fixed API response format to remove unnecessary internal fields and ensure consistent parameter forwarding
* Updated service token creation to allow organization-level tokens without requiring individual user assignment
* Improved credential management system with enhanced security and updated terminology
* Increased API timeout limits to reduce connection errors and improve reliability
* Enhanced deployment stability with longer grace periods for service updates

## 2.24.0 — March 12, 2026 at 5:20 PM UTC

* Added advertiser name to ADCP queries for improved query context and results
* Fixed service token creation for organization-level tokens to work without requiring a specific user ID
* Updated API response terminology from "credential registration" to "account linking" for better clarity
* Removed deprecated accountResolution field from API responses to streamline data structure
* Fixed query parameter forwarding for MCP queries to ensure proper request handling
* Increased API timeout limits to prevent request interruptions and improve reliability
* Updated API response format to v2 specification for consistency across endpoints

## 2.23.0 — March 11, 2026 at 8:16 PM UTC

* Added campaign audience targeting functionality to campaigns API - allows targeting and suppressing specific audiences when creating or updating campaigns
* Added timeframe selection controls to reporting metrics - users can now select custom date ranges and preset timeframes (7 days, 14 days, 30 days, all time) when viewing campaign performance data
* Added new suggestion history tracking table to store campaign suggestion status and transitions
* Fixed signal creation tool to make agent ID and access parameters optional for more flexible signal registration
* Fixed issue where certain table formatting was incorrectly triggering interactive UI detection
* Fixed Docker builds by properly scoping gitignore patterns for output directories
* Improved authentication model to enforce stricter security checks across customer boundaries

## 2.22.1 — March 11, 2026 at 1:43 AM UTC

* Temporarily disabled webhook signature verification to resolve compatibility issues with upstream client libraries
* Fixed linkedAccounts field to return an empty array instead of undefined when includeAccounts=true is specified but no accounts exist
* Improved CSV export reliability by using a dedicated storage bucket for report downloads
* Fixed reporting data lookups to use the correct media buy identifiers for more accurate BigQuery results
* Removed creative sets endpoints from the API specification

## 2.22.0 — March 10, 2026 at 11:48 PM UTC

* Added push notification configuration support to the audience sync API endpoint to enable real-time updates when sync operations complete.
* Fixed advertiser list responses to properly return the `advertiserId` field instead of incorrect field mapping.
* Enhanced observability functions to handle edge cases more gracefully and prevent potential API errors.

## 2.21.0 — March 10, 2026 at 7:02 PM UTC

* Added signal groups for audiences, allowing you to organize and manage multiple signals together for better audience targeting
* Added optimization apply mode setting that controls whether AI model optimizations to media buys are applied automatically or require manual approval - can be set at advertiser level (default for all campaigns) or overridden per campaign
* Fixed text formatting issues in sales agent and advertiser list responses to ensure all account status, credential requirements, and linked account information is properly displayed
* Improved production deployment reliability by fixing Docker build issues that could occur during retry scenarios

## 2.20.0 — March 10, 2026 at 4:56 PM UTC

* Added `sandbox` field to media buy API responses to indicate when a media buy belongs to a sandbox advertiser
* Moved audience management endpoints from separate "Audiences" tag to "Advertisers" tag in API documentation for better organization
* Fixed button text readability issues in dark mode across the UI
* Added enriched brand preview functionality when creating or editing advertisers with unregistered domains
* Increased API timeout from 30 seconds to 3 minutes for acceptance tests to handle longer-running operations
* Improved production deployment reliability by fixing retry scenario handling

## 2.19.0 — March 10, 2026 at 3:37 AM UTC

* Added comprehensive product detail view showing detailed manifest information including formats, reporting capabilities, optimization goals, setup requirements, and targeting approach
* Added publisher domain filter to product discovery allowing filtering of products by specific publisher domains
* Added audience syndication endpoint to distribute audiences to sales agents with status tracking
* Implemented audience syndication status query endpoint with filtering by resource type, status, agent, and other parameters
* Added product detail endpoint for retrieving full product specifications and manifest data
* Enhanced product descriptions with formatted display showing bold labels for structured information
* Fixed cross-sandbox linking prevention to ensure data isolation between different sandbox environments
* Improved product discovery service integration for more reliable product recommendations
* Enhanced UI formatting for better readability of product information and descriptions

## 2.18.0 — March 9, 2026 at 8:48 PM UTC

* Added `pricingModel` filter to product discovery endpoints to filter inventory by pricing type (cpm, vcpm, cpc, cpcv, cpv, cpp, flat\_rate)
* Added `sandbox` parameter to advertiser creation for testing campaigns without real spend - all operations for sandbox advertisers use test accounts
* Added `sandbox` query parameter to advertiser listing to filter by sandbox/production advertisers
* Enhanced product discovery UI to support multiple pricing options per product with interactive price selection
* Fixed OAuth credential storage to prevent cross-customer account linking security issue
* Fixed malformed JSON responses from AI services that could cause discovery failures
* Improved streaming connection reliability for real-time updates with automatic resumption on disconnect
* Fixed budget field conversion issues that could cause campaign creation errors

## 2.17.1 — March 6, 2026 at 9:47 PM UTC

* Renamed `bundleId` to `discoveryId` across all API endpoints for better terminology clarity
* Updated `/api/v2/buyer/bundles/*` endpoints to `/api/v2/buyer/discovery/*` to reflect the product discovery workflow
* Campaign creation and updates now use `discoveryId` instead of `bundleId` to reference product selections
* All API responses now return `discoveryId` instead of `bundleId` for consistency
* Updated product selection workflow terminology from "bundle" to "discovery session" throughout the API

## 2.17.0 — March 6, 2026 at 8:03 PM UTC

* Added multi-provider AI service with automatic fallback and circuit breaker protection for improved reliability and faster response times
* Added new notification event types for optimization suggestions (received, approved, rejected, applied, failed)
* Fixed product discovery view to display actual pricing models (CPM, vCPM, CPC, etc.) instead of hardcoded "CPM" labels
* Fixed pricing consistency issues in product recommendations by including pricing options in product data
* Improved bundle descriptions by deprioritizing pricing information to focus on key features
* Enhanced customer domain handling by using database values instead of deriving from email addresses

## 2.16.0 — March 6, 2026 at 6:59 PM UTC

* Multi-provider AI service with automatic failover for improved reliability and reduced downtime when generating content
* Added new optimization suggestion notification event types for campaign optimization workflows
* Fixed pricing model display in product discovery to show actual model (vCPM, CPC, etc.) instead of always showing "CPM"
* Fixed pricing options data consistency in product listings and API responses
* Improved pricing display logic to show appropriate labels based on actual product pricing models
* Enhanced bundle descriptions by reducing emphasis on pricing information for better readability
* Fixed customer domain resolution to use database values instead of deriving from email addresses

## 2.15.0 — March 6, 2026 at 12:46 AM UTC

* New audience management endpoints: sync CRM audiences with hashed identifiers, list stored audiences, and track processing status
* New task status endpoint to poll async operation progress when webhooks aren't available
* New notification system with endpoints to list, mark as read, and acknowledge notifications about campaigns, agents, and other resources
* New contract information endpoint for platform admins to view contract details
* New user invitation management for admins: approve, reject, resend, or cancel pending invitations
* Enhanced product discovery with AI-generated "why" explanations for recommended media plans
* Bundle management now supports replacing all products instead of just adding new ones
* Bundle apply-proposal endpoint to automatically add products from recommended plans with budget allocations
* Interactive product selection UI improvements with better handling of existing bundle products and confirmation flows
* Added parent-child customer hierarchy support allowing parent account users to access child accounts via header
* Sales agent status transitions now properly enforced - disabled agents cannot be updated
* Fixed campaign budget calculations to exclude archived media buys
* Fixed sales agent manifest resolution during campaign execution
* User access request flow for existing organizations when invitation system is enabled
* Enhanced MCP session management with cross-pod synchronization and better impersonation persistence

## 2.14.0 — March 5, 2026 at 11:15 PM UTC

* Added new audience management endpoints for syncing first-party CRM data with hashed customer identifiers for targeting
* Added notification system with endpoints to list, mark as read, and acknowledge notifications about campaigns, agents, and other resources
* Added task polling endpoints to check status of asynchronous operations like audience syncing and media buy creation
* Added contract information endpoint for admin users to view their organization's contract details
* Added parent-child customer hierarchy support allowing parent users to access child organization data via header
* Added user invitation system with request access flow for existing organizations
* Added bundle proposal application endpoint to automatically apply recommended media plans with budget allocations
* Enhanced bundle product selection to support replace mode instead of just adding products
* Enhanced product discovery with AI-generated explanations for recommended plan allocations and budget guidance
* Enhanced signup flow to require invitations for joining existing organizations when enabled
* Fixed campaign budget calculations to properly exclude archived media buys
* Fixed media buy retrieval to work without seat filtering restrictions
* Fixed brief updates in product discovery to show current information
* Fixed cross-pod session synchronization to prevent stale data when switching between servers

## 2.13.0 — March 5, 2026 at 4:40 PM UTC

* Added new audience management endpoints for syncing first-party customer data with hashed identifiers
* Added new notification system with endpoints to list, mark as read, and acknowledge system notifications
* Added contract information endpoint for admin users to view agreement details and status
* Added task status endpoint for tracking asynchronous operations like audience syncing
* Added LLM-enhanced recommendation logic that provides detailed rationale for suggested media plans
* Fixed media buy retrieval to work properly without seat-based filtering
* Fixed campaign budget calculations to exclude archived media buys from active budget totals
* Fixed brief updates in product discovery to work more reliably
* Fixed audience data type handling to properly support large seat ID values

## 2.12.0 — March 4, 2026 at 9:41 PM UTC

* Enhanced media buy creation and updates to automatically extend campaign end dates when media buy end times exceed the campaign timeline
* Added start\_time and end\_time fields to media buy responses, allowing independent scheduling within campaign bounds
* Improved webhook signature validation to return 401 errors instead of 500 errors for authentication failures
* Fixed session state persistence issues that could cause seat selection and customer switching to fail silently
* Enhanced brand agent ID validation in API tools to provide clearer error messages when invalid IDs are provided
* Improved error handling for session state changes to ensure consistency between local and stored state

## 2.11.0 — March 4, 2026 at 7:59 PM UTC

* Added support for media buy-level start and end dates that can be set independently from campaign dates
* Media buy end dates that exceed campaign end dates will now automatically extend the campaign end date
* Enhanced webhook security with HMAC signature verification for improved request authentication
* Fixed webhook signature validation errors that were previously returning HTTP 500 instead of HTTP 401
* Fixed session state persistence issues that could cause seat and customer switches to fail silently
* Improved brand agent ID validation to require numeric values and provide clearer error messages when invalid IDs are used

## 2.10.0 — March 4, 2026 at 1:12 AM UTC

* Added new `POST /api/v2/buyer/advertisers/{advertiserId}/event-sources/sync` endpoint for bulk syncing event sources with upsert functionality
* Fixed OAuth redirect URI validation to support dynamic query parameters for Microsoft Copilot Studio integrations
* Resolved build warnings in the user interface that could affect page loading performance

## 2.9.0 — March 3, 2026 at 11:14 PM UTC

* Added Microsoft Copilot OAuth support with OpenID Connect discovery endpoint for seamless integration
* Fixed UI v2 flag to automatically grant app access, simplifying feature flag management
* Improved MCP session reconnection reliability by preserving session state across API deployments
* Fixed authentication credential lookup to use the correct database table for improved connection stability

## 2.8.0 — March 3, 2026 at 4:46 PM UTC

* Improved error reporting when media buy submissions fail - you'll now receive more specific error messages to help diagnose issues
* Streamlined seat management by consolidating description storage, improving performance for advertiser and partner operations
* Fixed automatic installation of pre-archive hooks during workspace setup to ensure proper workflow execution

## 2.7.0 — March 3, 2026 at 5:52 AM UTC

* Catalog sync and listing endpoints moved to new paths: `POST /api/v2/buyer/advertisers/{advertiserId}/catalogs/sync` and `GET /api/v2/buyer/advertisers/{advertiserId}/catalogs` (replacing previous `/sync_catalogs` and `/list_catalogs` endpoints)
* Account linking now supports soft-delete functionality to preserve historical account assignments for better media buy attribution
* Improved account resolution logic ensures more reliable account identification across different sales agent configurations
* Fixed account assignment workflow to properly handle account reassignment scenarios when advertisers switch to new accounts
* Enhanced catalog sync validation to ensure advertiser ID consistency between URL path and request body
* Improved database query performance and reliability for account-related operations

## 2.6.0 — March 2, 2026 at 10:07 PM UTC

* Added new endpoint `POST /api/v2/advertisers/:id/restore` to restore archived advertisers (admin users only)
* Added support for filtering advertisers by status with new `ALL` option to retrieve both active and archived advertisers
* Fixed webhook processing to maintain backward compatibility with legacy systems that don't include HMAC signature headers

## 2.5.0 — March 2, 2026 at 5:56 PM UTC

* Added new catalog management endpoints for syncing and listing product catalogs via `/api/v2/buyer/sync_catalogs` and `/api/v2/buyer/list_catalogs`
* Added comprehensive account linking workflow for advertisers with new endpoints to discover and link partner platform accounts
* Added new `/api/v2/buyer/sales-agents/accountCredentials` endpoint to list all registered sales agent credentials
* Enhanced advertiser creation and updates to support linking partner accounts at creation time
* Added `includeAccounts` parameter to advertiser list endpoint to embed linked partner account information
* Fixed JSON response formatting for AI assistants to use proper structured output mode
* Added new `url` value to signal key types for expanded targeting capabilities
* Enhanced platform monitoring with comprehensive metrics, dashboards, and alerting for better service visibility

## 2.4.0 — February 27, 2026 at 4:23 AM UTC

* Fixed an issue where default channels and country codes were being automatically injected into product discovery requests, ensuring that empty channel and country filters are now respected as intended.

## 2.3.1 — February 27, 2026 at 12:56 AM UTC

* Performance campaigns now support multiple optimization goals with priority ordering, allowing more sophisticated targeting strategies
* Event-based optimization goals now support multiple event sources and improved targeting options including maximize value and threshold rate targets
* Metric-based optimization goals introduced for optimizing seller-native delivery metrics like clicks, views, and engagement
* Fixed issue where production deployment notifications were not properly marked as skipped for staging-only releases
* Fixed version bumping process to correctly include all application components during production releases
* Improved campaign execution workflow to properly handle new optimization goal structure

## 2.3.0 — February 26, 2026 at 9:54 PM UTC

* Added new event source validation that enforces valid IAB ECAPI event types at the database level
* Added organization-level API key management with role-based permissions and advertiser scoping
* Enhanced service token API to support revealing token secrets via `includeSecret` query parameter
* Improved partner and advertiser management UI with updated styling and navigation
* Fixed changelog display by replacing accordion layout with plain bullet lists for better readability
* Enhanced OAuth token refresh flow with better error tracking and logging for MCP clients
* Improved Stripe billing portal session creation with better customer ID persistence and deduplication
* Fixed product discovery to work correctly even when campaign briefs are not provided
* Enhanced service token creation and management workflows with improved validation and user experience

## 2.2.0 — February 26, 2026 at 2:16 PM UTC

* Added seat-scoped service tokens with full CRUD support via the V2 REST API
* Added ability to bypass Terms of Service acceptance for customers with custom contracts
* Fixed service token creation to make the name field optional with a sensible default
* Fixed brand agent listing to correctly filter by customer for SuperAdmin users

## 2.1.5 — February 25, 2026 at 1:18 PM UTC

* Fixed request timeout handling for AI model requests to prevent hanging operations and improve response reliability.
* Resolved an issue where certain aborted AI generation requests would unnecessarily retry, reducing API latency.
* Updated AI model version for more consistent response quality and performance.

## 2.1.4 — February 25, 2026 at 3:58 AM UTC

* Internal improvements and maintenance

## 2.1.3 — February 25, 2026 at 1:30 AM UTC

* Improved compatibility with partner integrations by retrying failed requests using an alternative brand identification format
* Improved error detection to correctly identify and handle validation failures during brand identification

## 2.1.2 — February 24, 2026 at 8:13 PM UTC

* Improved product discovery reliability with automatic fallback when brand identification fails
* Fixed documentation site routing to correctly serve versioned API docs
* Updated advertiser form field naming for consistency
* Updated homepage copy and messaging

## 2.1.1 — February 24, 2026 at 3:00 AM UTC

* Fixed documentation homepage returning 401 errors and broken routing for v2 API docs

## 2.1.0 — February 23, 2026 at 11:10 PM UTC

* Added reporting page with hierarchical metrics table for campaign performance visualization
* Fixed budget currency handling to use the actual currency from product pricing options instead of defaulting to USD
* Fixed creative format assignment to ensure each product only receives creatives that match its supported formats
* Added stable versioned documentation URLs with dark mode branding
* Improved metrics grid layout for better responsiveness across different screen sizes
