> ## 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.

# Get storefront margin (P&L) reporting

> The curator's resale P&L from the spread ledger: booked vs realized buy/sell/spread and margin %, rolled up buyer → media buy → package → source leg. Sourced from the storefront spread ledger (not BigQuery delivery); amounts are signed and never summed across settlement currencies. Cumulative as-of snapshot — there is no per-day timeseries.



## OpenAPI

````yaml /v2/storefront-api-v2.yaml get /reporting/margin
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: 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:
  /reporting/margin:
    get:
      tags:
        - Reporting
      summary: Get storefront margin (P&L) reporting
      description: >-
        The curator's resale P&L from the spread ledger: booked vs realized
        buy/sell/spread and margin %, rolled up buyer → media buy → package →
        source leg. Sourced from the storefront spread ledger (not BigQuery
        delivery); amounts are signed and never summed across settlement
        currencies. Cumulative as-of snapshot — there is no per-day timeseries.
      operationId: getStorefrontMarginReporting
      parameters:
        - in: query
          name: inventorySourceId
          schema:
            description: >-
              Narrow to the buy legs sourced from a single inventory source
              (storefront_spread_ledger.source_id). When omitted, includes every
              source on the storefront.
            type: string
          description: >-
            Narrow to the buy legs sourced from a single inventory source
            (storefront_spread_ledger.source_id). When omitted, includes every
            source on the storefront.
        - in: query
          name: buyerCustomerId
          schema:
            description: >-
              Narrow to a single buyer customer. Can only narrow within the
              calling storefront — it never widens scope.
            type: integer
            maximum: 9007199254740991
            minimum: 1
          description: >-
            Narrow to a single buyer customer. Can only narrow within the
            calling storefront — it never widens scope.
      responses:
        '200':
          description: Get storefront margin (P&L) reporting
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StorefrontMarginReportingResponse'
        '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:
    StorefrontMarginReportingResponse:
      description: >-
        Hierarchical storefront margin (P&L) response: buyer → media buy →
        package → source leg
      type: object
      properties:
        buyers:
          description: Buyer-level P&L data
          type: array
          items:
            $ref: '#/components/schemas/MarginBuyer'
        totals:
          description: >-
            Aggregated totals, one entry per settlement currency (amounts are
            never summed across currencies)
          type: array
          items:
            $ref: '#/components/schemas/MarginAmounts'
        periodStart:
          description: >-
            As-of start: earliest booked_at of the included edges (YYYY-MM-DD),
            null when empty
          nullable: true
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        periodEnd:
          description: >-
            As-of end: latest realized_through (or booked_at) of the included
            edges (YYYY-MM-DD), null when empty
          nullable: true
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
      required:
        - buyers
        - totals
        - periodStart
        - periodEnd
      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
    MarginBuyer:
      description: Buyer-level P&L with media-buy breakdown
      type: object
      properties:
        buyerCustomerId:
          description: The buyer customer this storefront sold to
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        buyerName:
          description: Buyer customer name, null when it cannot be resolved
          nullable: true
          type: string
        amounts:
          $ref: '#/components/schemas/MarginAmounts'
        mediaBuys:
          description: Media-buy-level P&L breakdown
          type: array
          items:
            $ref: '#/components/schemas/MarginMediaBuy'
      required:
        - buyerCustomerId
        - buyerName
        - amounts
        - mediaBuys
      additionalProperties: false
    MarginAmounts:
      description: >-
        Booked vs realized buy/sell/spread and margin %, one currency. The
        buy/sell/spread figures are independent coverage sums (each over the
        legs that carry that figure); when *Complete is false they do not
        reconcile by sell − buy = spread.
      type: object
      properties:
        settlementCurrency:
          description: ISO currency these amounts are denominated in
          type: string
        sellBooked:
          description: Committed buyer-facing gross (SUM of sell_booked_amount)
          nullable: true
          type: number
        sellRealized:
          description: >-
            Delivered buyer-facing gross (SUM of sell_realized_amount); null
            until delivery accrues
          nullable: true
          type: number
        buyBooked:
          description: Projected source cost (SUM of buy_booked_amount)
          nullable: true
          type: number
        buyRealized:
          description: >-
            Actual source spend — the realized cost basis (SUM of
            buy_realized_amount); null until delivery accrues
          nullable: true
          type: number
        spreadBooked:
          description: >-
            Committed spread, summed over the legs whose spread is determinable.
            Signed: negative when the curator commits to resell at a loss. May
            span fewer legs than sellBooked/buyBooked — see bookedComplete.
          nullable: true
          type: number
        spreadRealized:
          description: >-
            Delivered spread, summed over the legs whose realized spread is
            determinable. Signed; null until delivery accrues. May span fewer
            legs than buyRealized — see realizedComplete.
          nullable: true
          type: number
        marginBookedPct:
          description: >-
            Booked spread as a fraction of booked sell (0.25 = 25%), computed
            over the same legs that contributed spreadBooked (so numerator and
            denominator cover the same legs). Null when no leg has a
            determinable booked spread or that sell is zero — null means
            not-yet-determinable, never zero margin.
          nullable: true
          type: number
        marginRealizedPct:
          description: >-
            Realized spread as a fraction of realized sell, computed over the
            same legs that contributed spreadRealized. Null when no leg has a
            determinable realized spread or that sell is zero — null means
            not-yet-determinable, never zero margin.
          nullable: true
          type: number
        bookedComplete:
          description: >-
            True when every contributing leg has a determinable booked spread,
            so spreadBooked reconciles with sellBooked − buyBooked. False when a
            leg has booked activity but an undetermined spread (unresolved or
            mismatched pricing models) — then sellBooked/buyBooked span more
            legs than spreadBooked.
          type: boolean
        realizedComplete:
          description: >-
            True when every leg with realized activity has a determinable
            realized spread. False when a leg has realized cost but a
            deferred/undetermined realized spread (vcpm, cpp, cross-currency) —
            then buyRealized includes cost that spreadRealized does not yet
            account for.
          type: boolean
      required:
        - settlementCurrency
        - sellBooked
        - sellRealized
        - buyBooked
        - buyRealized
        - spreadBooked
        - spreadRealized
        - marginBookedPct
        - marginRealizedPct
        - bookedComplete
        - realizedComplete
      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
    MarginMediaBuy:
      description: Media-buy-level P&L with package breakdown
      type: object
      properties:
        mediaBuyId:
          description: Buyer-facing media buy identifier (the SELL leg)
          type: string
        amounts:
          $ref: '#/components/schemas/MarginAmounts'
        packages:
          description: Package-level P&L breakdown
          type: array
          items:
            $ref: '#/components/schemas/MarginPackage'
      required:
        - mediaBuyId
        - amounts
        - packages
      additionalProperties: false
    MarginPackage:
      description: >-
        Package-level P&L with per-source-leg breakdown. Package amounts are the
        sum of the source legs; this reconciles only while each buyer package
        routes to a single source package (the single-source guard enforced at
        forward time). Under curation-mode fan-out (one buyer package → many
        partitioned source packages) the per-leg sources[] remain exact, but
        package-level sell would need budget partitioning before the sum holds.
      type: object
      properties:
        packageId:
          description: Buyer-facing package identifier
          type: string
        productId:
          description: Product identifier this package was composed from
          nullable: true
          type: string
        amounts:
          $ref: '#/components/schemas/MarginAmounts'
        sources:
          description: >-
            Per-source buy-leg breakdown: which source package contributed which
            spread
          type: array
          items:
            $ref: '#/components/schemas/MarginSourceLeg'
      required:
        - packageId
        - productId
        - amounts
        - sources
      additionalProperties: false
    MarginSourceLeg:
      description: 'One buy-leg edge: a single source package under a buyer package'
      type: object
      properties:
        sourceId:
          description: Inventory source the buy leg was sourced from
          type: string
        upstreamMediaBuyId:
          description: The source's media buy id for this leg
          type: string
        upstreamPackageId:
          description: The source's package id for this leg
          type: string
        settlementStatus:
          $ref: '#/components/schemas/SettlementStatus'
        amounts:
          $ref: '#/components/schemas/MarginAmounts'
      required:
        - sourceId
        - upstreamMediaBuyId
        - upstreamPackageId
        - settlementStatus
        - amounts
      additionalProperties: false
    SettlementStatus:
      description: >-
        Per-edge settlement state: booked (committed, no delivery yet), accruing
        (delivering), settled (final), void (cancelled — excluded from this
        report).
      type: string
      enum:
        - booked
        - accruing
        - settled
        - void
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key or access token

````