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

# Submit a demand exchange revision for approval

> Submit a draft revision for approval, or clear it immediately when the storefront's campaign-approval setting (or a per-buyer auto-approve override) covers it. expectedSubmissionGeneration must match the draft's current submissionGeneration (as read) — a stale generation (a concurrent amend landed first) is refused rather than submitting content the caller never saw. Resubmitting a previously-rejected draft clears its whole decision record — decider, decided-at, and notes — not just the notes. Scoped to the caller's storefront.



## OpenAPI

````yaml /v2/storefront-api-v2.yaml post /demand-inbox/{runId}/exchange/revisions/{revisionId}/submit
openapi: 3.0.0
info:
  title: Scope3 Storefront API
  version: 2.0.0
  description: |-
    REST API for partners to manage storefronts, 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 storefronts
  - name: AI Usage
    description: Storefront AI token usage visibility by model
  - name: MCP
    description: Model Context Protocol endpoints
paths:
  /demand-inbox/{runId}/exchange/revisions/{revisionId}/submit:
    post:
      tags:
        - Storefront
      summary: Submit a demand exchange revision for approval
      description: >-
        Submit a draft revision for approval, or clear it immediately when the
        storefront's campaign-approval setting (or a per-buyer auto-approve
        override) covers it. expectedSubmissionGeneration must match the draft's
        current submissionGeneration (as read) — a stale generation (a
        concurrent amend landed first) is refused rather than submitting content
        the caller never saw. Resubmitting a previously-rejected draft clears
        its whole decision record — decider, decided-at, and notes — not just
        the notes. Scoped to the caller's storefront.
      operationId: submitDemandExchangeRevision
      parameters:
        - in: path
          name: runId
          schema:
            type: integer
            maximum: 9007199254740991
            minimum: 1
          required: true
        - in: path
          name: revisionId
          schema:
            type: integer
            maximum: 9007199254740991
            minimum: 1
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubmitDemandExchangeRevisionBody'
      responses:
        '200':
          description: Submit a demand exchange revision for approval
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DemandExchangeRevision'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Only the composer of this draft can submit it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: No matching revision in the calling storefront.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The revision is not currently submittable, or was submitted against
            a stale submission generation.
          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:
    SubmitDemandExchangeRevisionBody:
      description: >-
        Submit a draft for approval, or clear it immediately when the
        storefront/buyer auto-approve dial covers it.
        expectedSubmissionGeneration must match the draft's current
        submissionGeneration (as read) — a stale generation (a concurrent amend
        landed first) is refused rather than submitting content the caller never
        saw.
      type: object
      properties:
        expectedSubmissionGeneration:
          type: integer
          minimum: 0
          maximum: 9007199254740991
      required:
        - expectedSubmissionGeneration
    DemandExchangeRevision:
      description: >-
        A seller-composed adjustment to a live demand exchange: silent while
        draft or awaiting approval, and a real pass on the exchange's compose
        run once sent.
      type: object
      properties:
        id:
          type: string
        exchangeId:
          type: string
        state:
          type: string
          enum:
            - draft
            - awaiting_approval
            - sent
            - discarded
        overrides:
          type: object
          properties:
            posture:
              type: object
              properties:
                selectedPosture:
                  type: string
                  enum:
                    - direct_fit
                    - hold_value
                    - value_preserving_compromise
                    - tradeoff_ladder
                    - price_first
                    - wholesale_mirror
              required:
                - selectedPosture
              additionalProperties: false
            pricing:
              type: object
              properties:
                priceAdjustmentBasisPoints:
                  type: integer
                  minimum: -10000
                  maximum: 100000
                floorCpm:
                  type: object
                  properties:
                    amount:
                      type: number
                      minimum: 0
                    currency:
                      type: string
                      minLength: 3
                      maxLength: 3
                  required:
                    - amount
                    - currency
                  additionalProperties: false
              additionalProperties: false
            rules:
              type: object
              properties:
                requiredBundleIds:
                  maxItems: 100
                  type: array
                  items:
                    type: string
                    minLength: 1
                excludedBundleIds:
                  maxItems: 100
                  type: array
                  items:
                    type: string
                    minLength: 1
                maxProducts:
                  type: integer
                  maximum: 100
                  minimum: 1
              additionalProperties: false
          additionalProperties: false
        composeResult:
          type: string
          enum:
            - ok
            - error
        composeError:
          description: >-
            The merchandising engine's own error, kept mounted (with the
            seller's declared overrides) when composition failed, rather than
            the sheet being torn down.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/DemandExchangeRevisionComposeError'
        proposalPreview:
          description: >-
            The draft response envelope, in the same shape the canonical
            proposal card already renders (redacted). Null when compose failed.
          nullable: true
        proposalPreviewSnapshots:
          description: >-
            The draft product snapshots keyed by product id, paired with
            proposalPreview so the canonical proposal card renders a draft with
            no builder-specific projection. Null when compose failed.
          nullable: true
        settlementCurrency:
          nullable: true
          type: string
        buyerStatedCurrencies:
          description: >-
            Read once from the persisted brief request at compose time. A draft
            never converts into these or issues a rate hold — that is the
            buyer-facing response path's job, not a discardable draft's.
          nullable: true
          type: array
          items:
            type: string
        composedByUserId:
          nullable: true
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        composedAt:
          type: string
        approval:
          $ref: '#/components/schemas/DemandExchangeRevisionApproval'
        send:
          $ref: '#/components/schemas/DemandExchangeRevisionSend'
        sentProposalArtifactId:
          nullable: true
          type: string
        delivery:
          description: >-
            Truthful buyer-visibility (build-5 ruling): null until sent. A sent
            revision always reports not_delivered/no_delivery_lane today —
            investigation found no seller-to-buyer lane for a subsequent
            proposal and no honest staging lane either. The UI states the
            buyer's agent was not notified; it never claims a notification that
            did not happen.
          nullable: true
          type: object
          properties:
            status:
              type: string
              enum:
                - not_delivered
            reason:
              type: string
              enum:
                - no_delivery_lane
          required:
            - status
            - reason
          additionalProperties: false
        canApprove:
          description: >-
            False when the caller is this revision's own composer
            (maker-checker) or the revision is not awaiting approval.
          type: boolean
        canAmend:
          description: >-
            True for a draft (fresh or bounced back after rejection) composed by
            the caller; false once submitted, sent, or discarded, or when a
            different storefront user composed it.
          type: boolean
        canSubmit:
          description: >-
            True when the caller composed this draft, it hasn't been submitted,
            sent, or discarded, and its last compose succeeded. A draft whose
            compose failed can only be discarded or re-composed via amend.
          type: boolean
        canDiscard:
          description: >-
            True for a draft (fresh or bounced back after rejection) composed by
            the caller; false once submitted, sent, or discarded, or when a
            different storefront user composed it.
          type: boolean
        submissionGeneration:
          description: >-
            Bumped on every submit, resubmit, and amend. A decision must be made
            against this exact value or it is refused as stale.
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        amendCount:
          description: >-
            How many times this row has been amended in place. Counts toward the
            lifetime adjustment cap alongside the row itself.
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
      required:
        - id
        - exchangeId
        - state
        - overrides
        - composeResult
        - composeError
        - proposalPreview
        - proposalPreviewSnapshots
        - settlementCurrency
        - buyerStatedCurrencies
        - composedByUserId
        - composedAt
        - approval
        - send
        - sentProposalArtifactId
        - delivery
        - canApprove
        - canAmend
        - canSubmit
        - canDiscard
        - submissionGeneration
        - amendCount
      additionalProperties: false
    ErrorResponse:
      description: Standard error response
      type: object
      properties:
        data:
          type: string
          nullable: true
          enum:
            - null
        error:
          $ref: '#/components/schemas/ApiError'
      required:
        - data
        - error
      additionalProperties: false
    DemandExchangeRevisionComposeError:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
      required:
        - code
        - message
      additionalProperties: false
    DemandExchangeRevisionApproval:
      type: object
      properties:
        gate:
          description: >-
            Null before the revision is ever submitted. Cleared back to null
            (with decidedAt/decidedByUserId/notes) on every resubmission after a
            rejection, so a pending revision never reports a decision nobody has
            made against THIS submission.
          nullable: true
          type: string
          enum:
            - pending
            - approved
            - rejected
        decidedByUserId:
          nullable: true
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        decidedAt:
          nullable: true
          type: string
        notes:
          nullable: true
          type: string
      required:
        - gate
        - decidedByUserId
        - decidedAt
        - notes
      additionalProperties: false
    DemandExchangeRevisionSend:
      description: >-
        How a sent revision cleared. Null until sent. An auto send never carries
        a human decision record.
      type: object
      properties:
        mode:
          nullable: true
          type: string
          enum:
            - manual
            - auto
        autoApproveReason:
          nullable: true
          type: string
          enum:
            - storefront_auto_approve
            - buyer_auto_approve
      required:
        - mode
        - autoApproveReason
      additionalProperties: false
    ApiError:
      description: Structured error object
      type: object
      properties:
        code:
          description: Machine-readable error code
          type: string
        message:
          description: Human-readable error message
          type: string
        field:
          description: Field path associated with the error
          type: string
        details:
          description: Additional error context
          type: object
          additionalProperties: {}
      required:
        - code
        - message
      additionalProperties: false
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key or access token

````