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

# Update storefront

> Update the storefront configuration.



## OpenAPI

````yaml /v2/storefront-api-v2.yaml put /storefront
openapi: 3.0.0
info:
  title: Scope3 Storefront API
  version: 2.0.0
  description: >-
    REST API for partners to manage Seller Accounts, inventory sources, and
    billing.


    ## Authentication


    All endpoints require a Bearer token in the Authorization header:

    ```

    Authorization: Bearer your-api-key

    ```


    ## Base URL


    `https://api.interchange.io/api/v2/storefront`


    ## For AI Agents


    AI agents can use the MCP endpoint at `/mcp/v2/storefront` with three tools:

    - `initialize`: Start an MCP session

    - `api_call`: Make REST API calls

    - `ask_about_capability`: Learn about API features
servers:
  - url: https://api.interchange.io/api/v2/storefront
    description: Production server
security: []
tags:
  - name: Account
    description: Account management, service tokens, and preferences
  - name: Asks
    description: >-
      What you are waiting on Scope3 for — support, product, and supply asks in
      one list
  - name: Storefront
    description: Manage storefront and inventory sources
  - name: Storefront Agents
    description: List and manage registered sales, signals, and outcomes agents
  - name: Storefront Activity
    description: Audit log of configuration and inventory changes on the storefront
  - name: Storefront Billing
    description: Payout bank details and billing configuration for Seller Accounts
  - name: AI Usage
    description: Seller Account AI token usage visibility by model
  - name: MCP
    description: Model Context Protocol endpoints
paths:
  /storefront:
    servers:
      - url: https://api.interchange.io/api/v2
        description: Production server
    put:
      tags:
        - Storefront
      summary: Update storefront
      description: Update the storefront configuration.
      operationId: updateStorefront
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  description: Updated display name
                  example: Acme Media Network
                  type: string
                  minLength: 1
                  maxLength: 255
                publisherDomain:
                  description: >-
                    Deprecated legacy singular publisher domain. Use
                    businessProfile.publisherDomains / publisher-domain sync
                    state for the storefront publisher-domain set.
                  type: string
                  minLength: 1
                  maxLength: 255
                plan:
                  description: Updated plan tier
                  type: string
                  enum:
                    - basic
                transacting:
                  description: >-
                    Deprecated compatibility alias for the inverse of
                    `isPaused`. It is not effective transaction availability.
                  type: boolean
                isPaused:
                  description: >-
                    Compatibility-named seller intake hold. True hides product
                    discovery and blocks new media buys and buyer edits;
                    approved unsent buys wait until it is false. It does not
                    pause existing ad-server delivery. New storefronts default
                    to false; effective transaction availability also depends on
                    readiness and archival state.
                  type: boolean
                marketplaceParticipation:
                  description: >-
                    Seller publication choice for an otherwise eligible
                    Storefront. OPTED_OUT removes it from buyer discovery and
                    automatic selection without changing Scope3 eligibility
                    review; PUBLISHED cannot make an ineligible Storefront
                    eligible.
                  type: string
                  enum:
                    - PUBLISHED
                    - OPTED_OUT
                sellsThirdPartyInventory:
                  description: >-
                    Set to `true` to also resell third-party inventory from
                    other Interchange storefronts; `false` to sell only the
                    storefront’s own inventory sources.
                  type: boolean
                defaultCurrency:
                  description: >-
                    Seller-confirmed settlement currency (ISO-4217). Required
                    before go-live for Interchange-cleared Seller Accounts;
                    never defaulted silently. Direct sales adapter Seller
                    Accounts run by our expert agents skip settlement-currency
                    readiness checks because Interchange does not pay the seller
                    on that path.
                  example: EUR
                  type: string
                  pattern: ^[A-Z]{3}$
                paymentCurrencies:
                  description: >-
                    ISO-4217 currencies this Seller Account will be paid in (the
                    payout set). A media buy settles in one of these (the
                    primary defaultCurrency is always included). The buyer
                    payment currency is the seller payout currency unless the
                    marketplace accepts the buyer currency via cross-currency
                    FX, in which case the source cost is converted to the buyer
                    currency at the platform spot rate while the source is still
                    paid in one of these currencies. A pricing option may not
                    use a settlement currency outside this set. Empty falls back
                    to defaultCurrency, so a single-currency Seller Account need
                    not set it. Duplicates are ignored.
                  example:
                    - USD
                    - GBP
                  maxItems: 25
                  type: array
                  items:
                    type: string
                    pattern: ^[A-Z]{3}$
                acceptedCountries:
                  description: >-
                    Replace the operator-confirmed exhaustive country allowlist
                    used to route briefs. This is acceptance policy, not listing
                    merchandising. Pass null to mark the scope unconfigured.
                  example:
                    - FR
                  nullable: true
                  minItems: 1
                  maxItems: 249
                  type: array
                  items:
                    type: string
                    pattern: ^[A-Z]{2}$
                acceptsAllCountries:
                  description: >-
                    Set true to accept briefs from every country. Set false with
                    acceptedCountries: null to clear routing scope to
                    unconfigured.
                  type: boolean
                advertisingPolicyDisclosure:
                  description: >-
                    AI Business Rules sections to publish as Advertising
                    Policies on the listing. Empty hides the disclosure.
                    Approval routing, review mode, and revision notes are never
                    published. Listing and Merchandising storefronts can select
                    local disclosure; source-native upstream policies remain
                    independently applicable.
                  maxItems: 2
                  type: array
                  items:
                    type: string
                    enum:
                      - brief_acceptance
                      - creative_policy
                    description: >-
                      An AI Business Rules section the seller elects to disclose
                      publicly as Advertising Policies on its listing.
                supportedLanguages:
                  description: >-
                    Languages (BCP-47) the co-branded join/signup surface may
                    localize within.
                  example:
                    - nl
                    - fr
                    - en
                  type: array
                  items:
                    type: string
                    minLength: 2
                    maxLength: 35
                operatorDomain:
                  description: >-
                    Canonical brand domain for AAO registry lookup. Changing it
                    invalidates description, channels, membershipStatus, and
                    website values curated for the prior identity. Resupply
                    valid values in the same request or acknowledge their
                    removal with confirmOperatorDomainProfileReset.
                  example: scope3.com
                  type: string
                  minLength: 1
                  maxLength: 255
                confirmOperatorDomainProfileReset:
                  description: >-
                    Required when changing operatorDomain would clear profile
                    fields curated for the previous identity: description,
                    channels, membershipStatus, or website. Fields explicitly
                    resupplied in the same request are preserved/replaced.
                    Ignored when the domain is unchanged or no populated fields
                    would be cleared.
                  type: boolean
                operatorDomainConfirmationToken:
                  description: State-bound confirmation from a V3 seller identity preview.
                  type: string
                  minLength: 64
                  maxLength: 64
                brandName:
                  description: Brand name resolved from AAO registry
                  example: Scope3
                  type: string
                  maxLength: 255
                logoUrl:
                  description: Logo URL resolved from brand.json
                  type: string
                  maxLength: 2048
                  format: uri
                logoBackground:
                  description: >-
                    Backdrop the resolved logo is designed for, from brand.json.
                    Drives the storefront card tile color. Pass null to clear.
                  nullable: true
                  type: string
                  enum:
                    - dark-bg
                    - light-bg
                    - transparent-bg
                membershipStatus:
                  description: >-
                    AAO membership tier displayed on the storefront card. Use
                    `NONE` to hide the badge.
                  type: string
                  enum:
                    - AAO_FOUNDING_MEMBER
                    - AAO_MEMBER
                    - NONE
                regions:
                  description: >-
                    Compatibility write alias for legacy businessProfile.regions
                    merchandising context. It does not route briefs or define
                    listing country coverage. Prefer businessProfile.regions
                    when maintaining legacy context.
                  example:
                    - NL
                    - BE
                    - WORLDWIDE
                  maxItems: 64
                  type: array
                  items:
                    type: string
                    pattern: ^[A-Z0-9_-]{2,32}$
                description:
                  description: >-
                    Operator-curated description shown on the storefront card.
                    Overrides brand.json when set.
                  nullable: true
                  type: string
                  maxLength: 2000
                channels:
                  description: >-
                    AdCP MediaChannel codes the storefront offers, or the legacy
                    `audio`/`video` aliases. Surfaced on the storefront card.
                  example:
                    - display
                    - olv
                    - ctv
                  maxItems: 22
                  type: array
                  items:
                    type: string
                    enum:
                      - display
                      - olv
                      - social
                      - search
                      - ctv
                      - linear_tv
                      - radio
                      - streaming_audio
                      - podcast
                      - dooh
                      - ooh
                      - print
                      - cinema
                      - email
                      - gaming
                      - retail_media
                      - influencer
                      - affiliate
                      - product_placement
                      - sponsored_intelligence
                      - audio
                      - video
                    description: Channel.
                website:
                  description: >-
                    Operator-curated website URL shown on the storefront card.
                    Overrides brand.json when set.
                  type: string
                  maxLength: 2048
                  format: uri
                subtitle:
                  description: >-
                    Short operator-authored tagline for the storefront. A single
                    fact projected by every marketplace channel listing (e.g.
                    the ChatGPT app), truncated to a shorter cap only where a
                    channel enforces one. Pass null to clear.
                  nullable: true
                  type: string
                  maxLength: 160
                supportUrl:
                  description: >-
                    Operator-curated support/contact URL for this storefront.
                    Projected by every marketplace channel listing; not entered
                    separately per channel. Pass null to clear.
                  nullable: true
                  type: string
                  maxLength: 2048
                  format: uri
                privacyUrl:
                  description: >-
                    Operator-curated privacy policy URL for this storefront.
                    Projected by every marketplace channel listing; not entered
                    separately per channel. Pass null to clear.
                  nullable: true
                  type: string
                  maxLength: 2048
                  format: uri
                termsUrl:
                  description: >-
                    Operator-curated Terms of Service URL for this storefront.
                    Projected by every marketplace channel listing; not entered
                    separately per channel. Pass null to clear.
                  nullable: true
                  type: string
                  maxLength: 2048
                  format: uri
                demandContactName:
                  description: >-
                    Name of the person at the publisher who fields buyer
                    inquiries (RFPs, prospective briefs, weekly digests). Must
                    be set together with `demandContactEmail`. Pass null to
                    clear (both fields must be cleared together).
                  example: Pia Eberhardt
                  nullable: true
                  type: string
                  minLength: 1
                  maxLength: 255
                demandContactEmail:
                  description: >-
                    Email address for the demand contact. Must be set together
                    with `demandContactName`. Pass null to clear (both fields
                    must be cleared together).
                  example: pia@nrcmediagroep.com
                  nullable: true
                  type: string
                  maxLength: 320
                  format: email
                  pattern: >-
                    ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
                capabilities:
                  description: >-
                    Legacy v2 capability object. All flags remain persisted for
                    compatibility, but the effective `offersProductComposition`
                    response and runtime behavior are derived from merchandising
                    access and ready Source product paths. V3 publishes the
                    optional deprecated boolean as a typed no-op, strips it
                    before dispatch, and reports it as ignored.
                  type: object
                  properties:
                    offersCreativeReview:
                      default: false
                      description: >-
                        Surfaces the creative review protocol surface to buyers.
                        `sync_creatives` returns review-status fields; inline
                        creatives in `create_media_buy` / `update_media_buy`
                        flow through the storefront review gate. The operator
                        policy (auto-approve vs manual queue) is separate config
                        — this flag only governs whether the capability is
                        advertised.
                      type: boolean
                    offersCampaignApproval:
                      default: false
                      description: >-
                        Surfaces the campaign approval protocol surface to
                        buyers. `create_media_buy` and material-change
                        `update_media_buy` may return a submitted-task envelope
                        until the operator decides. The operator policy
                        (auto-approve vs manual queue, material-change
                        threshold) is separate config.
                      type: boolean
                    offersProductComposition:
                      default: false
                      deprecated: true
                      description: >-
                        Read-only compatibility projection. True only while the
                        customer has merchandising access and at least one
                        active Source has a ready Storefront-built product path
                        (`WHOLESALE`).
                      type: boolean
                setupIntent:
                  description: >-
                    Record the operator's declared selling intent. This is
                    descriptive state only: it does not change Source product
                    paths or effective capabilities. Both 'sell_through_scope3'
                    and 'third_party_connect' are accepted regardless of current
                    Source types.
                  type: string
                  enum:
                    - third_party_connect
                    - sell_through_scope3
                operatingMode:
                  description: >-
                    Select the organization's mutable seller product. Listing is
                    included in both choices; Agentic Media Company adds
                    Scope3's hosted Merchandising Agent. This does not change
                    admission, package entitlement, Source treatment, or
                    software ownership.
                  type: string
                  enum:
                    - LISTING_ONLY
                    - AGENTIC_MEDIA_COMPANY
                compositionPricing:
                  description: >-
                    Replace storefront composition pricing settings: fallback
                    pricing percentile plus seller pricing facts extracted from
                    rate cards, media kits, or operator instructions.
                  allOf:
                    - $ref: '#/components/schemas/StorefrontCompositionPricing'
                creativeApproval:
                  description: >-
                    Operator setting: how creatives buyers submit are handled on
                    ad-server-backed inventory sources. `manual` queues each for
                    review; `auto` approves without review. External sales
                    agents and linked Storefronts keep their own approval
                    settings.
                  type: string
                  enum:
                    - auto
                    - manual
                mediaBuyApproval:
                  description: >-
                    Operator setting: how new media buys are handled on
                    ad-server-backed inventory sources. `manual` queues each for
                    review; `auto` lets the buy start without review. External
                    sales agents and linked Storefronts keep their own approval
                    settings.
                  type: string
                  enum:
                    - auto
                    - manual
                businessProfile:
                  description: >-
                    Whole-document replacement for the operator-supplied
                    business profile captured during Murph-led setup. New
                    evidence URLs must use HTTP(S); a previously stored legacy
                    URI may be submitted unchanged so read/modify/write clients
                    can round-trip the profile. Pass null to clear.
                  nullable: true
                  allOf:
                    - $ref: '#/components/schemas/BusinessProfile'
                confirmCurrencyCatalogImpact:
                  description: >-
                    Required when changing `defaultCurrency` on a transacting
                    Seller Account would hide products currently visible to
                    buyers (operator fixed prices are only shown in the Seller
                    Account's settlement currency). The request is rejected with
                    the affected product count unless this is `true`. Ignored
                    when the Seller Account is not transacting or the currency
                    change has no buyer-visible impact.
                  type: boolean
                acknowledgeNoHumanReview:
                  description: >-
                    Required to move `creativeApproval` or `mediaBuyApproval` to
                    `auto`. In `auto`, work proceeds without human review. Brief
                    Acceptance qualifies product discovery; automatic media-buy
                    creation adds no second evaluator gate. The request is
                    rejected unless this is `true`. Ignored when tightening to
                    `manual`, or when the setting is already `auto`.
                  type: boolean
              description: Request body for updating a storefront
              allOf:
                - $ref: '#/components/schemas/UpdateStorefrontBody'
      responses:
        '200':
          description: Update storefront
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StorefrontResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearerAuth: []
components:
  schemas:
    StorefrontCompositionPricing:
      type: object
      properties:
        targetPercentile:
          default: p75
          type: string
          enum:
            - p50
            - p75
            - p90
          description: >-
            Deprecated. Historical auction-clearing percentile, retained for
            explainability only — it no longer sets the price. Pricing is
            value-led: the Merchandising Agent prices each brief to its value,
            bounded by wholesale floors and seller ceilings, never anchored to a
            clearing percentile.
        rateCard:
          default:
            facts: []
          description: >-
            Seller product-pricing facts. Separate from Scope3 contract rate
            cards.
          type: object
          properties:
            currency:
              description: >-
                Default ISO 4217 currency for pricing facts in this Seller
                Account rate card.
              example: USD
              type: string
              minLength: 3
              maxLength: 3
            facts:
              default: []
              maxItems: 500
              type: array
              items:
                $ref: '#/components/schemas/StorefrontPricingFact'
      description: >-
        Storefront composition pricing settings: fallback guidance percentile
        plus lightly structured seller pricing facts.
    BusinessProfile:
      type: object
      properties:
        summary:
          description: >-
            One-paragraph natural-language summary of the business (e.g. "30
            properties across web, mobile, and CTV, primarily UK, sports and
            entertainment focus").
          type: string
          maxLength: 2000
        agentName:
          description: >-
            Deprecated agent-name field, kept for legacy compatibility only.
            Prefer the Storefront display name for buyer-facing naming; do not
            use this to create a separate persona.
          type: string
          minLength: 1
          maxLength: 80
        agentPersonality:
          description: >-
            Deprecated. An agent has no personality of its own — voice belongs
            to the brand, and is read from the brand manifest (`tone`). Nothing
            consumes this field; pass null to remove an existing legacy value.
          type: string
          minLength: 1
          maxLength: 1000
        propertyCount:
          description: Approximate number of owned properties / domains.
          type: integer
          minimum: 0
          maximum: 10000
        channels:
          description: >-
            Channels the operator sells across — the full AdCP MediaChannel
            vocabulary (e.g. display, olv, ctv, social, streaming_audio, dooh,
            ...), plus the legacy `audio`/`video` aliases.
          maxItems: 22
          type: array
          items:
            type: string
            enum:
              - display
              - olv
              - social
              - search
              - ctv
              - linear_tv
              - radio
              - streaming_audio
              - podcast
              - dooh
              - ooh
              - print
              - cinema
              - email
              - gaming
              - retail_media
              - influencer
              - affiliate
              - product_placement
              - sponsored_intelligence
              - audio
              - video
            description: Channel.
        regions:
          description: >-
            Primary regions the business operates in (ISO 3166-1 alpha-2 country
            codes or group codes).
          example:
            - UK
            - EMEA
          maxItems: 64
          type: array
          items:
            type: string
            pattern: ^[A-Z0-9_-]{2,32}$
        verticals:
          description: Topic/vertical focus areas, free-text.
          example:
            - sports
            - entertainment
          maxItems: 32
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 80
        publisherDomains:
          description: >-
            Publisher domains/properties the Merchandising Agent should be
            authorized to sell through this Storefront. Omit when unknown;
            omission does not mean all domains are authorized. Domains are
            normalized to lowercase and deduplicated.
          example:
            - pitchside.co.uk
            - football.pitchside.co.uk
          maxItems: 128
          type: array
          items:
            type: string
            maxLength: 253
            pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$
        evidenceUrls:
          description: >-
            URLs the operator pointed Murph at (media kits, about pages, etc.)
            so a future conversation can re-read the source material. New values
            must use HTTP(S).
          maxItems: 16
          type: array
          items:
            type: string
            maxLength: 2048
            format: uri
        notes:
          description: >-
            Free-form Murph-captured notes that did not fit into the structured
            fields.
          type: string
          maxLength: 4000
        updatedBy:
          description: >-
            Identifier of the agent or user that last wrote this profile (e.g.
            "murph" or a userId). Audit-only.
          type: string
          maxLength: 120
      description: >-
        Operator-supplied business profile captured by Murph during storefront
        setup.
    UpdateStorefrontBody:
      type: object
      properties:
        name:
          description: Updated display name
          example: Acme Media Network
          type: string
          minLength: 1
          maxLength: 255
        publisherDomain:
          description: >-
            Deprecated legacy singular publisher domain. Use
            businessProfile.publisherDomains / publisher-domain sync state for
            the storefront publisher-domain set.
          type: string
          minLength: 1
          maxLength: 255
        plan:
          description: Updated plan tier
          type: string
          enum:
            - basic
        transacting:
          description: >-
            Deprecated compatibility alias for the inverse of `isPaused`. It is
            not effective transaction availability.
          type: boolean
        isPaused:
          description: >-
            Compatibility-named seller intake hold. True hides product discovery
            and blocks new media buys and buyer edits; approved unsent buys wait
            until it is false. It does not pause existing ad-server delivery.
            New storefronts default to false; effective transaction availability
            also depends on readiness and archival state.
          type: boolean
        marketplaceParticipation:
          description: >-
            Seller publication choice for an otherwise eligible Storefront.
            OPTED_OUT removes it from buyer discovery and automatic selection
            without changing Scope3 eligibility review; PUBLISHED cannot make an
            ineligible Storefront eligible.
          type: string
          enum:
            - PUBLISHED
            - OPTED_OUT
        sellsThirdPartyInventory:
          description: >-
            Set to `true` to also resell third-party inventory from other
            Interchange storefronts; `false` to sell only the storefront’s own
            inventory sources.
          type: boolean
        defaultCurrency:
          description: >-
            Seller-confirmed settlement currency (ISO-4217). Required before
            go-live for Interchange-cleared Seller Accounts; never defaulted
            silently. Direct sales adapter Seller Accounts run by our expert
            agents skip settlement-currency readiness checks because Interchange
            does not pay the seller on that path.
          example: EUR
          type: string
          pattern: ^[A-Z]{3}$
        paymentCurrencies:
          description: >-
            ISO-4217 currencies this Seller Account will be paid in (the payout
            set). A media buy settles in one of these (the primary
            defaultCurrency is always included). The buyer payment currency is
            the seller payout currency unless the marketplace accepts the buyer
            currency via cross-currency FX, in which case the source cost is
            converted to the buyer currency at the platform spot rate while the
            source is still paid in one of these currencies. A pricing option
            may not use a settlement currency outside this set. Empty falls back
            to defaultCurrency, so a single-currency Seller Account need not set
            it. Duplicates are ignored.
          example:
            - USD
            - GBP
          maxItems: 25
          type: array
          items:
            type: string
            pattern: ^[A-Z]{3}$
        acceptedCountries:
          description: >-
            Replace the operator-confirmed exhaustive country allowlist used to
            route briefs. This is acceptance policy, not listing merchandising.
            Pass null to mark the scope unconfigured.
          example:
            - FR
          nullable: true
          minItems: 1
          maxItems: 249
          type: array
          items:
            type: string
            pattern: ^[A-Z]{2}$
        acceptsAllCountries:
          description: >-
            Set true to accept briefs from every country. Set false with
            acceptedCountries: null to clear routing scope to unconfigured.
          type: boolean
        advertisingPolicyDisclosure:
          description: >-
            AI Business Rules sections to publish as Advertising Policies on the
            listing. Empty hides the disclosure. Approval routing, review mode,
            and revision notes are never published. Listing and Merchandising
            storefronts can select local disclosure; source-native upstream
            policies remain independently applicable.
          maxItems: 2
          type: array
          items:
            type: string
            enum:
              - brief_acceptance
              - creative_policy
            description: >-
              An AI Business Rules section the seller elects to disclose
              publicly as Advertising Policies on its listing.
        supportedLanguages:
          description: >-
            Languages (BCP-47) the co-branded join/signup surface may localize
            within.
          example:
            - nl
            - fr
            - en
          type: array
          items:
            type: string
            minLength: 2
            maxLength: 35
        operatorDomain:
          description: >-
            Canonical brand domain for AAO registry lookup. Changing it
            invalidates description, channels, membershipStatus, and website
            values curated for the prior identity. Resupply valid values in the
            same request or acknowledge their removal with
            confirmOperatorDomainProfileReset.
          example: scope3.com
          type: string
          minLength: 1
          maxLength: 255
        confirmOperatorDomainProfileReset:
          description: >-
            Required when changing operatorDomain would clear profile fields
            curated for the previous identity: description, channels,
            membershipStatus, or website. Fields explicitly resupplied in the
            same request are preserved/replaced. Ignored when the domain is
            unchanged or no populated fields would be cleared.
          type: boolean
        operatorDomainConfirmationToken:
          description: State-bound confirmation from a V3 seller identity preview.
          type: string
          minLength: 64
          maxLength: 64
        brandName:
          description: Brand name resolved from AAO registry
          example: Scope3
          type: string
          maxLength: 255
        logoUrl:
          description: Logo URL resolved from brand.json
          type: string
          maxLength: 2048
          format: uri
        logoBackground:
          description: >-
            Backdrop the resolved logo is designed for, from brand.json. Drives
            the storefront card tile color. Pass null to clear.
          nullable: true
          type: string
          enum:
            - dark-bg
            - light-bg
            - transparent-bg
        membershipStatus:
          description: >-
            AAO membership tier displayed on the storefront card. Use `NONE` to
            hide the badge.
          type: string
          enum:
            - AAO_FOUNDING_MEMBER
            - AAO_MEMBER
            - NONE
        regions:
          description: >-
            Compatibility write alias for legacy businessProfile.regions
            merchandising context. It does not route briefs or define listing
            country coverage. Prefer businessProfile.regions when maintaining
            legacy context.
          example:
            - NL
            - BE
            - WORLDWIDE
          maxItems: 64
          type: array
          items:
            type: string
            pattern: ^[A-Z0-9_-]{2,32}$
        description:
          description: >-
            Operator-curated description shown on the storefront card. Overrides
            brand.json when set.
          nullable: true
          type: string
          maxLength: 2000
        channels:
          description: >-
            AdCP MediaChannel codes the storefront offers, or the legacy
            `audio`/`video` aliases. Surfaced on the storefront card.
          example:
            - display
            - olv
            - ctv
          maxItems: 22
          type: array
          items:
            type: string
            enum:
              - display
              - olv
              - social
              - search
              - ctv
              - linear_tv
              - radio
              - streaming_audio
              - podcast
              - dooh
              - ooh
              - print
              - cinema
              - email
              - gaming
              - retail_media
              - influencer
              - affiliate
              - product_placement
              - sponsored_intelligence
              - audio
              - video
            description: Channel.
        website:
          description: >-
            Operator-curated website URL shown on the storefront card. Overrides
            brand.json when set.
          type: string
          maxLength: 2048
          format: uri
        subtitle:
          description: >-
            Short operator-authored tagline for the storefront. A single fact
            projected by every marketplace channel listing (e.g. the ChatGPT
            app), truncated to a shorter cap only where a channel enforces one.
            Pass null to clear.
          nullable: true
          type: string
          maxLength: 160
        supportUrl:
          description: >-
            Operator-curated support/contact URL for this storefront. Projected
            by every marketplace channel listing; not entered separately per
            channel. Pass null to clear.
          nullable: true
          type: string
          maxLength: 2048
          format: uri
        privacyUrl:
          description: >-
            Operator-curated privacy policy URL for this storefront. Projected
            by every marketplace channel listing; not entered separately per
            channel. Pass null to clear.
          nullable: true
          type: string
          maxLength: 2048
          format: uri
        termsUrl:
          description: >-
            Operator-curated Terms of Service URL for this storefront. Projected
            by every marketplace channel listing; not entered separately per
            channel. Pass null to clear.
          nullable: true
          type: string
          maxLength: 2048
          format: uri
        demandContactName:
          description: >-
            Name of the person at the publisher who fields buyer inquiries
            (RFPs, prospective briefs, weekly digests). Must be set together
            with `demandContactEmail`. Pass null to clear (both fields must be
            cleared together).
          example: Pia Eberhardt
          nullable: true
          type: string
          minLength: 1
          maxLength: 255
        demandContactEmail:
          description: >-
            Email address for the demand contact. Must be set together with
            `demandContactName`. Pass null to clear (both fields must be cleared
            together).
          example: pia@nrcmediagroep.com
          nullable: true
          type: string
          maxLength: 320
          format: email
          pattern: >-
            ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
        capabilities:
          description: >-
            Legacy v2 capability object. All flags remain persisted for
            compatibility, but the effective `offersProductComposition` response
            and runtime behavior are derived from merchandising access and ready
            Source product paths. V3 publishes the optional deprecated boolean
            as a typed no-op, strips it before dispatch, and reports it as
            ignored.
          type: object
          properties:
            offersCreativeReview:
              default: false
              description: >-
                Surfaces the creative review protocol surface to buyers.
                `sync_creatives` returns review-status fields; inline creatives
                in `create_media_buy` / `update_media_buy` flow through the
                storefront review gate. The operator policy (auto-approve vs
                manual queue) is separate config — this flag only governs
                whether the capability is advertised.
              type: boolean
            offersCampaignApproval:
              default: false
              description: >-
                Surfaces the campaign approval protocol surface to buyers.
                `create_media_buy` and material-change `update_media_buy` may
                return a submitted-task envelope until the operator decides. The
                operator policy (auto-approve vs manual queue, material-change
                threshold) is separate config.
              type: boolean
            offersProductComposition:
              default: false
              deprecated: true
              description: >-
                Read-only compatibility projection. True only while the customer
                has merchandising access and at least one active Source has a
                ready Storefront-built product path (`WHOLESALE`).
              type: boolean
        setupIntent:
          description: >-
            Record the operator's declared selling intent. This is descriptive
            state only: it does not change Source product paths or effective
            capabilities. Both 'sell_through_scope3' and 'third_party_connect'
            are accepted regardless of current Source types.
          type: string
          enum:
            - third_party_connect
            - sell_through_scope3
        operatingMode:
          description: >-
            Select the organization's mutable seller product. Listing is
            included in both choices; Agentic Media Company adds Scope3's hosted
            Merchandising Agent. This does not change admission, package
            entitlement, Source treatment, or software ownership.
          type: string
          enum:
            - LISTING_ONLY
            - AGENTIC_MEDIA_COMPANY
        compositionPricing:
          description: >-
            Replace storefront composition pricing settings: fallback pricing
            percentile plus seller pricing facts extracted from rate cards,
            media kits, or operator instructions.
          allOf:
            - $ref: '#/components/schemas/StorefrontCompositionPricing'
        creativeApproval:
          description: >-
            Operator setting: how creatives buyers submit are handled on
            ad-server-backed inventory sources. `manual` queues each for review;
            `auto` approves without review. External sales agents and linked
            Storefronts keep their own approval settings.
          type: string
          enum:
            - auto
            - manual
        mediaBuyApproval:
          description: >-
            Operator setting: how new media buys are handled on ad-server-backed
            inventory sources. `manual` queues each for review; `auto` lets the
            buy start without review. External sales agents and linked
            Storefronts keep their own approval settings.
          type: string
          enum:
            - auto
            - manual
        businessProfile:
          description: >-
            Whole-document replacement for the operator-supplied business
            profile captured during Murph-led setup. New evidence URLs must use
            HTTP(S); a previously stored legacy URI may be submitted unchanged
            so read/modify/write clients can round-trip the profile. Pass null
            to clear.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/BusinessProfile'
        confirmCurrencyCatalogImpact:
          description: >-
            Required when changing `defaultCurrency` on a transacting Seller
            Account would hide products currently visible to buyers (operator
            fixed prices are only shown in the Seller Account's settlement
            currency). The request is rejected with the affected product count
            unless this is `true`. Ignored when the Seller Account is not
            transacting or the currency change has no buyer-visible impact.
          type: boolean
        acknowledgeNoHumanReview:
          description: >-
            Required to move `creativeApproval` or `mediaBuyApproval` to `auto`.
            In `auto`, work proceeds without human review. Brief Acceptance
            qualifies product discovery; automatic media-buy creation adds no
            second evaluator gate. The request is rejected unless this is
            `true`. Ignored when tightening to `manual`, or when the setting is
            already `auto`.
          type: boolean
      description: Request body for updating a storefront
    StorefrontResponse:
      type: object
      properties:
        storefrontId:
          type: string
          description: Surrogate id (BIGINT serialized as string)
          example: '1234'
        platformId:
          type: string
          description: Public-facing slug
          example: acme-media
        name:
          type: string
          description: Display name
          example: Acme Media
        publisherDomain:
          nullable: true
          description: Publisher domain for the storefront's business profile
          example: acme.com
          type: string
        operatorDomain:
          nullable: true
          description: Canonical brand domain
          example: scope3.com
          type: string
        brandName:
          nullable: true
          description: Brand name from AAO registry
          example: Scope3
          type: string
        logoUrl:
          nullable: true
          description: Logo URL from brand.json
          type: string
        logoBackground:
          description: >-
            Backdrop the logo is designed for, from brand.json. Null or absent
            when unknown; the storefront card falls back to a dark tile.
          nullable: true
          type: string
          enum:
            - dark-bg
            - light-bg
            - transparent-bg
        membershipStatus:
          nullable: true
          description: AAO membership tier. Null when the operator has not set a value.
          type: string
          enum:
            - AAO_FOUNDING_MEMBER
            - AAO_MEMBER
            - NONE
        regions:
          type: array
          items:
            type: string
          description: >-
            Legacy merchandising-region context projected from businessProfile.
            This does not govern brief acceptance or listing country coverage.
        acceptedCountries:
          nullable: true
          description: >-
            Operator-confirmed exhaustive country allowlist for brief routing.
            Null means routing scope has not been confirmed.
          type: array
          items:
            type: string
            pattern: ^[A-Z]{2}$
        acceptsAllCountries:
          type: boolean
          description: Whether the operator explicitly accepts briefs from every country.
        advertisingPolicyDisclosure:
          type: array
          items:
            type: string
            enum:
              - brief_acceptance
              - creative_policy
            description: >-
              An AI Business Rules section the seller elects to disclose
              publicly as Advertising Policies on its listing.
          description: >-
            Seller-selected AI Business Rules sections disclosed publicly as
            Advertising Policies. Empty means no local disclosure.
        advertisedCountries:
          type: array
          items:
            type: string
            pattern: ^[A-Z]{2}$
          description: >-
            Standard primary countries advertised by backing AdCP sales agents.
            Authoritative for the listing on a pure pass-through storefront;
            inventory evidence otherwise.
        advertisedChannels:
          type: array
          items:
            type: string
          description: >-
            Standard primary channels advertised by backing AdCP sales agents.
            Authoritative for the listing on a pure pass-through storefront;
            inventory evidence otherwise.
        description:
          nullable: true
          description: Operator-curated description (overrides brand.json).
          type: string
        channels:
          type: array
          items:
            type: string
          description: ADCP channel codes the storefront offers.
        website:
          nullable: true
          description: Operator-curated website URL (overrides brand.json).
          type: string
        subtitle:
          nullable: true
          description: >-
            Short operator-authored tagline, projected by every marketplace
            channel listing. Null when unset.
          type: string
        supportUrl:
          nullable: true
          description: >-
            Operator-curated support/contact URL, projected by every marketplace
            channel listing. Null when unset.
          type: string
        privacyUrl:
          nullable: true
          description: >-
            Operator-curated privacy policy URL, projected by every marketplace
            channel listing. Null when unset.
          type: string
        termsUrl:
          nullable: true
          description: >-
            Operator-curated Terms of Service URL, projected by every
            marketplace channel listing. Null when unset.
          type: string
        discoveryCard:
          description: >-
            Canonical buyer-visible storefront identity and coverage. This is
            distinct from the legacy Business Profile merchandising inputs and
            seller policies.
          allOf:
            - $ref: '#/components/schemas/DiscoveryCard'
        demandContactName:
          nullable: true
          description: Demand contact name. Null when the operator has not set one.
          type: string
        demandContactEmail:
          nullable: true
          description: Demand contact email. Null when the operator has not set one.
          type: string
        operatorDomainVerified:
          type: boolean
          description: >-
            Whether the brand domain has been verified (email match or manual
            KYC)
        routingMode:
          type: string
          enum:
            - CHEF
            - ADAPTER
          description: >-
            Which backend function the buyer-facing storefront dispatches to:
            the Merchandising Agent or an expert-run adapter.
        adapterProviderType:
          nullable: true
          description: >-
            Expert-run adapter provider when routingMode is `ADAPTER`; null
            otherwise.
          type: string
          enum:
            - amazon
            - audiostack
            - elevenlabs
            - fal
            - gemini
            - google
            - linkedin
            - meta
            - openai
            - openai_ads
            - pinterest
            - reddit
            - snap
            - spotify
            - tiktok
            - veo
        adapterSourceKind:
          nullable: true
          description: Adapter role when routingMode is `ADAPTER`; null otherwise.
          type: string
          enum:
            - sales
            - creative
            - signals
            - measurement
            - optimization
            - composite
        adapterCredentialMode:
          nullable: true
          description: >-
            Adapter credential mode when routingMode is `ADAPTER`; null
            otherwise.
          type: string
          enum:
            - BYOK
        plan:
          type: string
          enum:
            - basic
          description: Legacy v2 Seller Account plan tier
        transacting:
          type: boolean
          description: >-
            Deprecated compatibility projection of `!isPaused`; not proof that
            the storefront currently satisfies readiness.
        isPaused:
          type: boolean
          description: >-
            Compatibility-named seller intake hold. True blocks discovery, new
            buys, and buyer edits but does not pause existing delivery. False is
            neutral; it does not by itself make the storefront live.
        archivedAt:
          nullable: true
          description: >-
            When the storefront was archived (read-only thereafter). Null for
            non-archived storefronts.
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
        displayStatus:
          type: string
          enum:
            - configuring
            - transacting
            - archived
            - neutral
            - paused
          description: >-
            Deprecated stored-control display status. This is never proof that
            the storefront can transact; use the readiness projection.
        capabilities:
          description: >-
            Effective buyer-facing AdCP capabilities. Product composition
            derives from merchandising access and ready Source product paths; it
            is not locked to the legacy configured flag.
          allOf:
            - $ref: '#/components/schemas/StorefrontCapabilities'
        merchandisingEntitled:
          type: boolean
          description: >-
            Whether the Seller Account commercial plan entitles it to
            Merchandising. This is a server-derived commercial fact, separate
            from needing a connected source that is ready to supply products
            your storefront can sell, such as an ad server.
        listingDistributionEntitled:
          type: boolean
          description: >-
            Whether the Seller Account commercial plan entitles it to Listing +
            Distribution. This is independent from Merchandising and from the
            connected sales agent that fulfills the listing.
        configuredCapabilities:
          description: >-
            Persisted operator capability flags before source-topology
            derivation. Compare this field for declarative writes;
            `capabilities` is the effective buyer-facing projection.
          allOf:
            - $ref: '#/components/schemas/StorefrontCapabilities'
        setupIntent:
          description: >-
            Compatibility record of the reversible signup package choice, or
            null when none was selected. It is not a behavioral mode: what the
            storefront exposes is always the derived `capabilities` and its
            Source treatment.
          nullable: true
          type: string
          enum:
            - third_party_connect
            - sell_through_scope3
        operatingMode:
          description: >-
            Derived display value for the mutable supply operating capabilities.
            Null means a legacy account has not selected a mode yet.
          nullable: true
          type: string
          enum:
            - LISTING_ONLY
            - AGENTIC_MEDIA_COMPANY
        operatingCapabilities:
          description: >-
            Mutable account capabilities for listing and Scope3 merchandising.
            Listing is always enabled after selection; null means a legacy
            account has not selected a product yet.
          nullable: true
          type: object
          properties:
            listingSelected:
              type: boolean
              enum:
                - true
            scope3MerchandisingSelected:
              type: boolean
          required:
            - listingSelected
            - scope3MerchandisingSelected
          additionalProperties: false
        compositionPricing:
          description: >-
            Composition pricing settings: fallback pricing percentile plus
            seller pricing facts. Separate from Scope3 contract/billing rate
            cards.
          allOf:
            - $ref: '#/components/schemas/StorefrontCompositionPricingOutput'
        creativeApproval:
          type: string
          enum:
            - auto
            - manual
          description: >-
            Stored operator setting for creative submissions. It applies at
            Interchange-managed review checkpoints; a connected sales agent or
            downstream source may enforce additional source-native review.
        mediaBuyApproval:
          type: string
          enum:
            - auto
            - manual
          description: >-
            Stored operator setting for new media buys. It applies when the
            storefront exposes an Interchange-managed campaign-approval
            checkpoint; a connected sales agent or downstream source may enforce
            additional source-native review.
        capabilitiesLocked:
          type: boolean
          description: >-
            Legacy topology projection: true when the storefront has at least
            one active ad-server-backed inventory source
            (`executionType=MANAGED_SALES_AGENT`). Product composition is now
            Source-derived, so this value does not authorize or lock capability
            writes.
        advertiseAsAgent:
          type: boolean
          description: >-
            Derived: true when the Storefront has an active Inventory Source, an
            active embedded Sales Agent, adapter routing, or an advertised
            Storefront-owned capability. Every active Source remains behind the
            buyer-facing Storefront AdCP endpoint, including COMPOSING-only
            Sources.
        sellsThirdPartyInventory:
          description: >-
            Operator toggle: when true, the storefront also resells third-party
            inventory from other Interchange storefronts (composition draws from
            the marketplace in addition to its own sources). When false/absent
            (default), the storefront sells only its own inventory sources.
          type: boolean
        createdAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          description: Creation timestamp (ISO 8601)
        updatedAt:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          description: Last update timestamp (ISO 8601)
        businessProfile:
          nullable: true
          description: >-
            Operator-supplied business profile captured during Murph-led setup.
            Null when the operator has not shared one.
          allOf:
            - $ref: '#/components/schemas/BusinessProfileOutput'
        defaultCurrency:
          description: >-
            Seller-confirmed primary settlement currency (ISO-4217). Null until
            confirmed; required before go-live for Interchange-cleared Seller
            Accounts. Direct sales adapter Seller Accounts run by our expert
            agents skip settlement-currency readiness checks because Interchange
            does not pay the seller on that path.
          nullable: true
          type: string
        paymentCurrencies:
          description: >-
            ISO-4217 currencies the Seller Account will be paid in (the payout
            set). A media buy settles in one of these. Empty falls back to
            defaultCurrency. The marketplace may additionally accept buyer
            currencies outside this set via cross-currency FX, converting each
            source cost to the buyer currency at the platform spot rate.
          type: array
          items:
            type: string
      required:
        - storefrontId
        - platformId
        - name
        - publisherDomain
        - operatorDomain
        - brandName
        - logoUrl
        - membershipStatus
        - regions
        - acceptedCountries
        - acceptsAllCountries
        - advertisingPolicyDisclosure
        - advertisedCountries
        - advertisedChannels
        - description
        - channels
        - website
        - subtitle
        - supportUrl
        - privacyUrl
        - termsUrl
        - discoveryCard
        - demandContactName
        - demandContactEmail
        - operatorDomainVerified
        - routingMode
        - adapterProviderType
        - adapterSourceKind
        - adapterCredentialMode
        - plan
        - transacting
        - isPaused
        - archivedAt
        - displayStatus
        - capabilities
        - merchandisingEntitled
        - listingDistributionEntitled
        - configuredCapabilities
        - compositionPricing
        - creativeApproval
        - mediaBuyApproval
        - capabilitiesLocked
        - advertiseAsAgent
        - createdAt
        - updatedAt
        - businessProfile
      additionalProperties: false
      description: Storefront configuration response
    ErrorResponse:
      type: object
      properties:
        data:
          type: string
          nullable: true
          enum:
            - null
        error:
          $ref: '#/components/schemas/ApiError'
      required:
        - data
        - error
      additionalProperties: false
      description: Standard error response
    StorefrontPricingFact:
      type: object
      properties:
        id:
          type: string
          minLength: 1
          maxLength: 120
          pattern: ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
          description: >-
            Stable operator-facing id for this pricing fact. Murph should
            preserve ids across rewrites when the fact is semantically the same.
        label:
          type: string
          minLength: 1
          maxLength: 160
          description: Short display label for this pricing fact.
          example: Rich media packages
        appliesWhen:
          type: string
          minLength: 1
          maxLength: 2000
          description: >-
            Natural-language applicability condition. This is intentionally not
            a rigid product template; the Merchandising Agent uses it as
            reasoning context.
        hints:
          default: {}
          description: >-
            Optional structured hints for deterministic matching. Missing hints
            are fine.
          allOf:
            - $ref: '#/components/schemas/StorefrontPricingFactHints'
        pricing:
          $ref: '#/components/schemas/StorefrontPricingFactPrice'
        strength:
          default: default
          type: string
          enum:
            - hard_floor
            - default
            - guidance
          description: >-
            `hard_floor` is a must-not-go-below seller constraint. `default` is
            the preferred value-pricing anchor. `guidance` is advisory context
            only.
        provenance:
          description: >-
            Where this pricing fact came from, such as "Uploaded 2026 rate card,
            page 3" or "Operator statement on setup call".
          type: string
          maxLength: 500
        notes:
          description: Human-readable rationale or caveats for operators and Murph.
          type: string
          maxLength: 2000
      required:
        - id
        - label
        - appliesWhen
        - pricing
      description: >-
        Lightly structured seller value-pricing fact. Pricing facts anchor
        prices and floors; they are not product assembly templates.
    DiscoveryCard:
      type: object
      properties:
        storefrontId:
          type: string
        platformId:
          type: string
        storefrontKind:
          type: string
          enum:
            - managed
            - external_pass_through
        displayName:
          type: string
        logoUrl:
          nullable: true
          type: string
        logoBackground:
          nullable: true
          type: string
          enum:
            - dark-bg
            - light-bg
            - transparent-bg
        description:
          nullable: true
          type: string
        website:
          nullable: true
          type: string
        brandColors:
          nullable: true
          type: object
          additionalProperties:
            type: string
        channels:
          type: array
          items:
            type: string
          description: >-
            Aggregate channel facets for search and display. Do not combine
            these with aggregate countries as a cross-product coverage promise.
        countries:
          type: array
          items:
            type: string
            pattern: ^[A-Z]{2}$
          description: >-
            Aggregate ISO 3166-1 alpha-2 country facets for search and display.
            Do not combine these with aggregate channels as a cross-product
            coverage promise.
        acceptsAllCountries:
          type: boolean
          description: >-
            True only when the storefront explicitly accepts briefs from every
            country.
        coverageDeclarations:
          type: array
          items:
            type: object
            properties:
              channels:
                type: array
                items:
                  type: string
                description: Channels accepted by this correlated source declaration.
              countries:
                type: array
                items:
                  type: string
                  pattern: ^[A-Z]{2}$
                description: >-
                  ISO 3166-1 alpha-2 countries accepted by this correlated
                  source declaration.
              acceptsAllCountries:
                type: boolean
                description: >-
                  True only when this correlated source declaration explicitly
                  accepts every country.
            required:
              - channels
              - countries
              - acceptsAllCountries
            additionalProperties: false
            description: >-
              One source-level coverage claim. Channels and countries are
              correlated within this declaration; an empty dimension is unknown,
              not unrestricted.
          description: >-
            Channel and country coverage claims preserved at their source
            boundaries. A combined filter matches only when one declaration
            satisfies both dimensions.
        advertisingPolicies:
          nullable: true
          type: string
          maxLength: 10000
        coverage:
          type: object
          properties:
            channels:
              type: string
              enum:
                - declared
                - partial
                - unknown
            countries:
              type: string
              enum:
                - declared
                - partial
                - unknown
          required:
            - channels
            - countries
          additionalProperties: false
        provenance:
          type: object
          properties:
            identity:
              type: object
              properties:
                displayName:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
                logoUrl:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
                description:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
                website:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
                brandColors:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
              required:
                - displayName
                - logoUrl
                - description
                - website
                - brandColors
              additionalProperties: false
            coverage:
              type: object
              properties:
                channels:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
                countries:
                  type: string
                  enum:
                    - operator
                    - registry
                    - upstream_capabilities
                    - unknown
              required:
                - channels
                - countries
              additionalProperties: false
            advertisingPolicies:
              type: string
              enum:
                - operator
                - registry
                - upstream_capabilities
                - unknown
          required:
            - identity
            - coverage
            - advertisingPolicies
          additionalProperties: false
      required:
        - storefrontId
        - platformId
        - storefrontKind
        - displayName
        - logoUrl
        - logoBackground
        - description
        - website
        - brandColors
        - channels
        - countries
        - acceptsAllCountries
        - coverageDeclarations
        - advertisingPolicies
        - coverage
        - provenance
      additionalProperties: false
      description: >-
        Canonical buyer-visible storefront identity, coverage declaration, and
        optional Advertising Policies disclosure. Unknown coverage never means
        worldwide or all channels.
    StorefrontCapabilities:
      type: object
      properties:
        offersCreativeReview:
          default: false
          description: >-
            Surfaces the creative review protocol surface to buyers.
            `sync_creatives` returns review-status fields; inline creatives in
            `create_media_buy` / `update_media_buy` flow through the storefront
            review gate. The operator policy (auto-approve vs manual queue) is
            separate config — this flag only governs whether the capability is
            advertised.
          type: boolean
        offersCampaignApproval:
          default: false
          description: >-
            Surfaces the campaign approval protocol surface to buyers.
            `create_media_buy` and material-change `update_media_buy` may return
            a submitted-task envelope until the operator decides. The operator
            policy (auto-approve vs manual queue, material-change threshold) is
            separate config.
          type: boolean
        offersProductComposition:
          default: false
          deprecated: true
          description: >-
            Read-only compatibility projection. True only while the customer has
            merchandising access and at least one active Source has a ready
            Storefront-built product path (`WHOLESALE`).
          type: boolean
      required:
        - offersCreativeReview
        - offersCampaignApproval
        - offersProductComposition
      additionalProperties: false
      description: >-
        Which AdCP capabilities the storefront advertises to buyers. Product
        composition is derived from Source product-path readiness and
        entitlement.
    StorefrontCompositionPricingOutput:
      type: object
      properties:
        targetPercentile:
          default: p75
          type: string
          enum:
            - p50
            - p75
            - p90
          description: >-
            Deprecated. Historical auction-clearing percentile, retained for
            explainability only — it no longer sets the price. Pricing is
            value-led: the Merchandising Agent prices each brief to its value,
            bounded by wholesale floors and seller ceilings, never anchored to a
            clearing percentile.
        rateCard:
          default:
            facts: []
          description: >-
            Seller product-pricing facts. Separate from Scope3 contract rate
            cards.
          type: object
          properties:
            currency:
              description: >-
                Default ISO 4217 currency for pricing facts in this Seller
                Account rate card.
              example: USD
              type: string
              minLength: 3
              maxLength: 3
            facts:
              default: []
              maxItems: 500
              type: array
              items:
                $ref: '#/components/schemas/StorefrontPricingFactOutput'
          required:
            - facts
          additionalProperties: false
      required:
        - targetPercentile
        - rateCard
      additionalProperties: false
      description: >-
        Storefront composition pricing settings: fallback guidance percentile
        plus lightly structured seller pricing facts.
    BusinessProfileOutput:
      type: object
      properties:
        summary:
          description: >-
            One-paragraph natural-language summary of the business (e.g. "30
            properties across web, mobile, and CTV, primarily UK, sports and
            entertainment focus").
          type: string
          maxLength: 2000
        agentName:
          description: >-
            Deprecated agent-name field, kept for legacy compatibility only.
            Prefer the Storefront display name for buyer-facing naming; do not
            use this to create a separate persona.
          type: string
          minLength: 1
          maxLength: 80
        agentPersonality:
          description: >-
            Deprecated. An agent has no personality of its own — voice belongs
            to the brand, and is read from the brand manifest (`tone`). Nothing
            consumes this field; pass null to remove an existing legacy value.
          type: string
          minLength: 1
          maxLength: 1000
        propertyCount:
          description: Approximate number of owned properties / domains.
          type: integer
          minimum: 0
          maximum: 10000
        channels:
          description: >-
            Channels the operator sells across — the full AdCP MediaChannel
            vocabulary (e.g. display, olv, ctv, social, streaming_audio, dooh,
            ...), plus the legacy `audio`/`video` aliases.
          maxItems: 22
          type: array
          items:
            type: string
            enum:
              - display
              - olv
              - social
              - search
              - ctv
              - linear_tv
              - radio
              - streaming_audio
              - podcast
              - dooh
              - ooh
              - print
              - cinema
              - email
              - gaming
              - retail_media
              - influencer
              - affiliate
              - product_placement
              - sponsored_intelligence
              - audio
              - video
            description: Channel.
        regions:
          description: >-
            Primary regions the business operates in (ISO 3166-1 alpha-2 country
            codes or group codes).
          example:
            - UK
            - EMEA
          maxItems: 64
          type: array
          items:
            type: string
            pattern: ^[A-Z0-9_-]{2,32}$
        verticals:
          description: Topic/vertical focus areas, free-text.
          example:
            - sports
            - entertainment
          maxItems: 32
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 80
        publisherDomains:
          description: >-
            Publisher domains/properties the Merchandising Agent should be
            authorized to sell through this Storefront. Omit when unknown;
            omission does not mean all domains are authorized. Domains are
            normalized to lowercase and deduplicated.
          example:
            - pitchside.co.uk
            - football.pitchside.co.uk
          maxItems: 128
          type: array
          items:
            type: string
            maxLength: 253
            pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$
        evidenceUrls:
          description: >-
            URLs the operator pointed Murph at (media kits, about pages, etc.)
            so a future conversation can re-read the source material. New values
            must use HTTP(S).
          maxItems: 16
          type: array
          items:
            type: string
            maxLength: 2048
            format: uri
        notes:
          description: >-
            Free-form Murph-captured notes that did not fit into the structured
            fields.
          type: string
          maxLength: 4000
        updatedBy:
          description: >-
            Identifier of the agent or user that last wrote this profile (e.g.
            "murph" or a userId). Audit-only.
          type: string
          maxLength: 120
      additionalProperties: false
      description: >-
        Operator-supplied business profile captured by Murph during storefront
        setup.
    ApiError:
      type: object
      properties:
        code:
          type: string
          description: Machine-readable error code
        message:
          type: string
          description: Human-readable error message
        field:
          description: Field path associated with the error
          type: string
        details:
          description: Additional error context
          type: object
          additionalProperties: {}
      required:
        - code
        - message
      additionalProperties: false
      description: Structured error object
    StorefrontPricingFactHints:
      type: object
      properties:
        channels:
          description: >-
            AdCP channel codes (e.g. `olv`, `ctv`, `dooh`) this fact applies to.
            Unlike the free-text hint categories, channels are matched as EXACT
            codes against the product's seller-declared `channels` plus the
            broad channel family inferred from its creative format kind — never
            as substrings of names, ids, or tags. So a fact scoped to `["ctv"]`
            applies only to products that declare `ctv`; a `video_hosted` format
            on its own resolves to the broad `video` family, which cannot
            distinguish `olv` from `ctv`. Within the array any code may match
            (OR); across hint categories every populated category must match
            (AND).
          maxItems: 32
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 80
        creativeTerms:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        publisherDomains:
          maxItems: 128
          type: array
          items:
            type: string
            maxLength: 253
            pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$
        countries:
          maxItems: 64
          type: array
          items:
            type: string
            pattern: ^[A-Z0-9_-]{2,32}$
        advertiserVerticals:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        seasonality:
          maxItems: 32
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        signalTags:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        placementTags:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        formatDimensions:
          description: >-
            Creative dimensions this fact applies to. A fact matches when at
            least one pair is admitted by a selected canonical format option: an
            exact width/height pair must equal it, sizes[] must contain it, and
            min/max bounds must include it. Unselected options on the same
            inventory bundle do not count. Within the array any pair may match
            (OR); across hint categories every populated category must match
            (AND).
          maxItems: 64
          type: array
          items:
            type: object
            properties:
              width:
                type: integer
                minimum: 0
                exclusiveMinimum: true
                maximum: 9007199254740991
              height:
                type: integer
                minimum: 0
                exclusiveMinimum: true
                maximum: 9007199254740991
            required:
              - width
              - height
            additionalProperties: false
      description: >-
        Optional best-effort hints for matching a seller pricing fact. These are
        not product assembly rules; the Merchandising Agent still reasons over
        the natural-language appliesWhen field.
    StorefrontPricingFactPrice:
      type: object
      properties:
        pricingModel:
          default: cpm
          description: >-
            AdCP pricing model this pricing fact anchors, sourced from the AdCP
            SDK vocabulary. A price shape the protocol has no model for — share
            of voice, a day-part premium — is a product-coverage gap to report,
            not a value to store.
          type: string
          enum:
            - cpm
            - vcpm
            - cpc
            - cpcv
            - cpv
            - cpp
            - cpa
            - revenue_share
            - flat_rate
            - time
        currency:
          description: >-
            ISO 4217 currency for this pricing fact. Falls back to the Seller
            Account pricing currency when omitted.
          example: USD
          type: string
          minLength: 3
          maxLength: 3
        targetPrice:
          description: >-
            Preferred value-based buyer-facing price for this fact. This is a
            value anchor, not a cost-plus markup.
          type: number
          minimum: 0
          exclusiveMinimum: true
        floorPrice:
          description: >-
            Hard minimum buyer-facing price when this fact applies. Composition
            also floors at wholesale cost/floor.
          type: number
          minimum: 0
        ceilingPrice:
          description: Optional maximum buyer-facing price when this fact applies.
          type: number
          minimum: 0
          exclusiveMinimum: true
      description: >-
        Value-pricing anchor extracted from seller rate cards, media kits, or
        operator instructions.
    StorefrontPricingFactOutput:
      type: object
      properties:
        id:
          type: string
          minLength: 1
          maxLength: 120
          pattern: ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
          description: >-
            Stable operator-facing id for this pricing fact. Murph should
            preserve ids across rewrites when the fact is semantically the same.
        label:
          type: string
          minLength: 1
          maxLength: 160
          description: Short display label for this pricing fact.
          example: Rich media packages
        appliesWhen:
          type: string
          minLength: 1
          maxLength: 2000
          description: >-
            Natural-language applicability condition. This is intentionally not
            a rigid product template; the Merchandising Agent uses it as
            reasoning context.
        hints:
          default: {}
          description: >-
            Optional structured hints for deterministic matching. Missing hints
            are fine.
          allOf:
            - $ref: '#/components/schemas/StorefrontPricingFactHintsOutput'
        pricing:
          $ref: '#/components/schemas/StorefrontPricingFactPriceOutput'
        strength:
          default: default
          type: string
          enum:
            - hard_floor
            - default
            - guidance
          description: >-
            `hard_floor` is a must-not-go-below seller constraint. `default` is
            the preferred value-pricing anchor. `guidance` is advisory context
            only.
        provenance:
          description: >-
            Where this pricing fact came from, such as "Uploaded 2026 rate card,
            page 3" or "Operator statement on setup call".
          type: string
          maxLength: 500
        notes:
          description: Human-readable rationale or caveats for operators and Murph.
          type: string
          maxLength: 2000
      required:
        - id
        - label
        - appliesWhen
        - hints
        - pricing
        - strength
      additionalProperties: false
      description: >-
        Lightly structured seller value-pricing fact. Pricing facts anchor
        prices and floors; they are not product assembly templates.
    StorefrontPricingFactHintsOutput:
      type: object
      properties:
        channels:
          description: >-
            AdCP channel codes (e.g. `olv`, `ctv`, `dooh`) this fact applies to.
            Unlike the free-text hint categories, channels are matched as EXACT
            codes against the product's seller-declared `channels` plus the
            broad channel family inferred from its creative format kind — never
            as substrings of names, ids, or tags. So a fact scoped to `["ctv"]`
            applies only to products that declare `ctv`; a `video_hosted` format
            on its own resolves to the broad `video` family, which cannot
            distinguish `olv` from `ctv`. Within the array any code may match
            (OR); across hint categories every populated category must match
            (AND).
          maxItems: 32
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 80
        creativeTerms:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        publisherDomains:
          maxItems: 128
          type: array
          items:
            type: string
            maxLength: 253
            pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$
        countries:
          maxItems: 64
          type: array
          items:
            type: string
            pattern: ^[A-Z0-9_-]{2,32}$
        advertiserVerticals:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        seasonality:
          maxItems: 32
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        signalTags:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        placementTags:
          maxItems: 64
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 120
        formatDimensions:
          description: >-
            Creative dimensions this fact applies to. A fact matches when at
            least one pair is admitted by a selected canonical format option: an
            exact width/height pair must equal it, sizes[] must contain it, and
            min/max bounds must include it. Unselected options on the same
            inventory bundle do not count. Within the array any pair may match
            (OR); across hint categories every populated category must match
            (AND).
          maxItems: 64
          type: array
          items:
            type: object
            properties:
              width:
                type: integer
                minimum: 0
                exclusiveMinimum: true
                maximum: 9007199254740991
              height:
                type: integer
                minimum: 0
                exclusiveMinimum: true
                maximum: 9007199254740991
            required:
              - width
              - height
            additionalProperties: false
      additionalProperties: false
      description: >-
        Optional best-effort hints for matching a seller pricing fact. These are
        not product assembly rules; the Merchandising Agent still reasons over
        the natural-language appliesWhen field.
    StorefrontPricingFactPriceOutput:
      type: object
      properties:
        pricingModel:
          default: cpm
          description: >-
            AdCP pricing model this pricing fact anchors, sourced from the AdCP
            SDK vocabulary. A price shape the protocol has no model for — share
            of voice, a day-part premium — is a product-coverage gap to report,
            not a value to store.
          type: string
          enum:
            - cpm
            - vcpm
            - cpc
            - cpcv
            - cpv
            - cpp
            - cpa
            - revenue_share
            - flat_rate
            - time
        currency:
          description: >-
            ISO 4217 currency for this pricing fact. Falls back to the Seller
            Account pricing currency when omitted.
          example: USD
          type: string
          minLength: 3
          maxLength: 3
        targetPrice:
          description: >-
            Preferred value-based buyer-facing price for this fact. This is a
            value anchor, not a cost-plus markup.
          type: number
          minimum: 0
          exclusiveMinimum: true
        floorPrice:
          description: >-
            Hard minimum buyer-facing price when this fact applies. Composition
            also floors at wholesale cost/floor.
          type: number
          minimum: 0
        ceilingPrice:
          description: Optional maximum buyer-facing price when this fact applies.
          type: number
          minimum: 0
          exclusiveMinimum: true
      required:
        - pricingModel
      additionalProperties: false
      description: >-
        Value-pricing anchor extracted from seller rate cards, media kits, or
        operator instructions.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key or access token

````