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

# Get one buy's exchange timeline

> The seller-scoped projection of the buy's exchange record: stages (received → screened → decided → forwarded / forward-failed → submitted → source moderation → accepted / rejected → delivering) with evidence, per-source legs, and the references to quote per state — the source's own ids as their reference, and the `sf:` idempotency key paired with the request timestamp as the platform reference. The forwarded payload is returned minus platform-internal fields (webhook/push-notification config and signing material); admin-only material never appears. `{"pruned": true}` payloads mean retention removed the bytes.



## OpenAPI

````yaml /v2/storefront-api-v2.yaml get /media-buys/{mediaBuyId}/timeline
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.apostra.com/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.apostra.com/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:
  /media-buys/{mediaBuyId}/timeline:
    get:
      tags:
        - Storefront
      summary: Get one buy's exchange timeline
      description: >-
        The seller-scoped projection of the buy's exchange record: stages
        (received → screened → decided → forwarded / forward-failed → submitted
        → source moderation → accepted / rejected → delivering) with evidence,
        per-source legs, and the references to quote per state — the source's
        own ids as their reference, and the `sf:` idempotency key paired with
        the request timestamp as the platform reference. The forwarded payload
        is returned minus platform-internal fields (webhook/push-notification
        config and signing material); admin-only material never appears.
        `{"pruned": true}` payloads mean retention removed the bytes.
      operationId: getStorefrontMediaBuyTimeline
      parameters:
        - in: query
          name: buyerCustomerId
          schema:
            description: >-
              Buyer customer id that owns this buyer-scoped media-buy id. Omit
              only for compatibility with callers whose ids are globally
              unambiguous.
            type: integer
            minimum: 0
            exclusiveMinimum: true
            maximum: 9007199254740991
          description: >-
            Buyer customer id that owns this buyer-scoped media-buy id. Omit
            only for compatibility with callers whose ids are globally
            unambiguous.
        - in: path
          name: mediaBuyId
          schema:
            type: string
            minLength: 1
            description: Media buy id at the storefront grain (`sf_mb_…`).
          required: true
          description: Media buy id at the storefront grain (`sf_mb_…`).
      responses:
        '200':
          description: Get one buy's exchange timeline
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StorefrontMediaBuyTimelineResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: >-
            The buy does not exist on this storefront (unknown id, or a buy
            belonging to another storefront).
          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:
    StorefrontMediaBuyTimelineResponse:
      type: object
      properties:
        mediaBuyId:
          type: string
        buyer:
          type: object
          properties:
            customerId:
              nullable: true
              type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            name:
              nullable: true
              type: string
          required:
            - customerId
            - name
          additionalProperties: false
        approval:
          nullable: true
          description: The approval-queue row, when the buy rode the review flow.
          type: object
          properties:
            status:
              type: string
            submittedAt:
              type: string
            reviewedBy:
              nullable: true
              type: string
            reviewedAt:
              nullable: true
              type: string
            reviewerNotes:
              nullable: true
              type: string
            forwardedAt:
              nullable: true
              type: string
            submittedPayload:
              nullable: true
              description: >-
                The buyer's submitted payload as it sits in the approval queue
                (already webhook-credential-free), minus platform-internal
                fields.
              type: object
              additionalProperties: {}
          required:
            - status
            - submittedAt
            - reviewedBy
            - reviewedAt
            - reviewerNotes
            - forwardedAt
            - submittedPayload
          additionalProperties: false
        stages:
          type: array
          items:
            $ref: '#/components/schemas/SellerTimelineStage'
          description: >-
            Buy-level stages (pre-fan-out): received, screened, decided, and any
            pre-dispatch failure.
        legs:
          type: array
          items:
            $ref: '#/components/schemas/SellerTimelineLeg'
        goal:
          nullable: true
          description: >-
            The buyer's goal for this buy and how delivery compares — the same
            block the media-buy list carries, and the same verdict the buyer
            sees. Null when this seller holds no goal for the buy, and also on
            the rare read failure: the block is assembled from a commitment read
            and a delivery read, and either one failing leaves it absent rather
            than showing a half-assembled goal. Those failures are captured to
            Sentry, so an outage has an operational signal even though this
            field cannot distinguish it from genuine absence.
          allOf:
            - $ref: '#/components/schemas/StorefrontMediaBuyGoal'
        eventsTruncated:
          type: boolean
          description: >-
            True when more ledger events exist than were hydrated into this
            timeline.
      required:
        - mediaBuyId
        - buyer
        - approval
        - stages
        - legs
        - goal
        - eventsTruncated
      additionalProperties: false
      description: >-
        The seller-scoped projection of a buy's exchange timeline: only this
        storefront's legs; forwarded/response payloads minus platform-internal
        fields; no admin-only material (resolution cache internals, worker poll
        internals, cross-tenant audit rows).
    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
    SellerTimelineStage:
      type: object
      properties:
        stage:
          $ref: '#/components/schemas/SellerTimelineStageName'
        at:
          nullable: true
          description: >-
            When the buy entered this stage (ISO 8601). Null when the stage is
            inferred without a precise timestamp.
          type: string
        detail:
          nullable: true
          description: >-
            Human-readable note — the reviewer decision, the sanitized source
            moderation message, the failure summary.
          type: string
        evidence:
          type: array
          items:
            $ref: '#/components/schemas/SellerTimelineEvidence'
          description: Supporting observations, newest first.
      required:
        - stage
        - at
        - detail
        - evidence
      additionalProperties: false
      description: One reached stage of the exchange, with evidence.
    SellerTimelineLeg:
      type: object
      properties:
        sourceId:
          type: string
        sourceName:
          nullable: true
          type: string
        sourceKind:
          type: string
        currentStatus:
          nullable: true
          description: Latest persisted upstream status for this leg.
          type: string
        forwardedAt:
          nullable: true
          type: string
        responseReceivedAt:
          nullable: true
          type: string
        theirReference:
          type: object
          properties:
            mediaBuyId:
              nullable: true
              type: string
            taskId:
              nullable: true
              type: string
          required:
            - mediaBuyId
            - taskId
          additionalProperties: false
          description: >-
            The source's own ids for this exchange — quote these to the source;
            they can look them up directly.
        platformReference:
          type: object
          properties:
            idempotencyKey:
              nullable: true
              type: string
            requestedAt:
              nullable: true
              type: string
          required:
            - idempotencyKey
            - requestedAt
          additionalProperties: false
          description: >-
            The Scope3 reference for this exchange: the create idempotency key
            (`sf:<storefront>:<buy>:<source>`) paired with the request
            timestamp. Quote both together — the key is stable across the buy’s
            life, requests are not.
        stages:
          type: array
          items:
            $ref: '#/components/schemas/SellerTimelineStage'
          description: Stages this leg reached, lifecycle order.
        forwardedPayload:
          nullable: true
          description: >-
            The exact AdCP request sent to this source, minus platform-internal
            fields (webhook/push-notification config and signing material are
            projected out server-side). `{"pruned": true}` when retention
            removed the payload.
          type: object
          additionalProperties: {}
        responsePayload:
          nullable: true
          description: >-
            The source's latest response as persisted, minus platform-internal
            fields. `{"pruned": true}` when retention removed the payload.
          type: object
          additionalProperties: {}
        payloadHighlights:
          nullable: true
          description: >-
            Trafficker-grade summary of the forwarded payload; null when nothing
            was forwarded.
          allOf:
            - $ref: '#/components/schemas/SellerPayloadHighlights'
        replayed:
          nullable: true
          description: >-
            True when the captured response was an idempotency-cache replay — a
            historical snapshot, not current state.
          type: boolean
        note:
          nullable: true
          description: >-
            Structural note (e.g. "the forward never succeeded — no route exists
            for this source").
          type: string
      required:
        - sourceId
        - sourceName
        - sourceKind
        - currentStatus
        - forwardedAt
        - responseReceivedAt
        - theirReference
        - platformReference
        - stages
        - forwardedPayload
        - responsePayload
        - payloadHighlights
        - replayed
        - note
      additionalProperties: false
      description: One source leg of the buy, as seen from the storefront.
    StorefrontMediaBuyGoal:
      type: object
      properties:
        goal:
          nullable: true
          description: >-
            The buyer's goal being judged: the commitment's asked goal, else the
            campaign's primary goal. Null when only a fixed outcome price is on
            record.
          type: object
          properties:
            kind:
              type: string
              enum:
                - metric
                - event
            subject:
              type: string
              description: >-
                The metric name for a metric goal; the event type(s) joined with
                | for an event goal.
            eventTypes:
              type: array
              items:
                type: string
            target:
              nullable: true
              allOf:
                - $ref: '#/components/schemas/GoalProgressTarget'
          required:
            - kind
            - subject
            - eventTypes
            - target
          additionalProperties: false
        askedTarget:
          nullable: true
          description: The target the buyer asked for, when the goal carries one.
          allOf:
            - $ref: '#/components/schemas/GoalProgressTarget'
        answeredTarget:
          nullable: true
          description: >-
            The cost or return the seller's terms commit or aim at, from the
            media buy's goal commitment.
          allOf:
            - $ref: '#/components/schemas/GoalProgressTarget'
        commitment:
          nullable: true
          description: >-
            The commitment kind on the media buy, or the weakest across a
            campaign; null when no buy carries one.
          type: string
          enum:
            - guaranteed
            - best_effort
            - report_only
        commitmentSource:
          nullable: true
          description: >-
            Where a media buy commitment came from; null at campaign level,
            where buys may differ.
          type: string
          enum:
            - proposal
            - campaign
        actual:
          nullable: true
          description: >-
            The achieved cost per unit (per thousand for impressions), rate over
            the metric's own denominator, or volume for the goal's metric,
            computed from the same delivery this response reports. Null when the
            metric was not reported or has no observations.
          type: object
          properties:
            kind:
              type: string
              enum:
                - cost_per
                - threshold_rate
                - volume
            value:
              type: number
            unit:
              type: string
              enum:
                - impressions
                - clicks
                - views
                - completedViews
                - conversions
                - leads
                - viewableImpressions
            units:
              type: number
              minimum: 0
            denominatorUnits:
              nullable: true
              description: >-
                What a threshold_rate divided by: measurable impressions for a
                viewable rate, impressions for every other rate. Null for a cost
                or a volume.
              type: number
              minimum: 0
            perUnits:
              anyOf:
                - type: number
                  enum:
                    - 1
                - type: number
                  enum:
                    - 1000
              description: >-
                How many units a cost_per value prices: 1000 for impressions (a
                price per thousand, like CPM), 1 for every other unit.
            currency:
              nullable: true
              type: string
          required:
            - kind
            - value
            - unit
            - units
            - denominatorUnits
            - perUnits
            - currency
          additionalProperties: false
        verdict:
          nullable: true
          description: >-
            How delivery compares with the target. Null whenever the evidence
            does not support a verdict; see verdictWithheld.
          type: string
          enum:
            - on_track
            - behind
            - beat
        judgedAgainst:
          nullable: true
          description: >-
            Which target the verdict compares against: the buyer's asked target,
            or the seller's answered price when the buyer stated none.
          type: string
          enum:
            - asked
            - answered
        verdictWithheld:
          nullable: true
          description: >-
            Why there is no verdict. metric_unsupported covers metrics delivery
            does not carry (reach, attention), event goals other than lead-only
            ones and return-on-ad-spend targets, which need event-scoped counts
            this surface does not have. Too few observations means the metric is
            real but below the minimum count that makes a comparison meaningful.
          type: string
          enum:
            - no_goal
            - no_target
            - metric_unsupported
            - metric_not_reported
            - too_few_observations
        basis:
          nullable: true
          description: Who counted the number. Delivery on this surface is seller reported.
          type: object
          properties:
            kind:
              type: string
              enum:
                - seller_attested
          required:
            - kind
          additionalProperties: false
        freshness:
          type: object
          properties:
            dataThrough:
              nullable: true
              type: string
            reportingPeriodEnd:
              nullable: true
              type: string
            nextExpectedAt:
              nullable: true
              type: string
            notificationType:
              nullable: true
              type: string
            sequenceNumber:
              nullable: true
              type: number
            awaitingLaterReport:
              type: boolean
            missingMetrics:
              type: array
              items:
                type: string
          required:
            - dataThrough
            - reportingPeriodEnd
            - nextExpectedAt
            - notificationType
            - sequenceNumber
            - awaitingLaterReport
            - missingMetrics
          additionalProperties: false
        optimizedBy:
          nullable: true
          description: >-
            Who acts on the goal, for a buy an ad server manages. Read
            `optimizedBy.actor`, never `optimizedBy` itself: this is an object,
            not the enum. Null for a routed buy — it went to a third party whose
            optimization this storefront cannot see — null when the ad server
            did not answer, which is not evidence either way, and null for an
            ad-server buy whose id several buyers on this storefront hold, where
            no buyer can be named for it.
          type: object
          properties:
            actor:
              type: string
              enum:
                - ad_server
                - seller
              description: >-
                `ad_server` = the managing ad server optimizes towards this goal
                itself. `seller` = nothing automatic acts on it, so the seller's
                ad operations own it by hand.
            detail:
              nullable: true
              type: string
          required:
            - actor
            - detail
          additionalProperties: false
      required:
        - goal
        - askedTarget
        - answeredTarget
        - commitment
        - commitmentSource
        - actual
        - verdict
        - judgedAgainst
        - verdictWithheld
        - basis
        - freshness
        - optimizedBy
      additionalProperties: false
      description: >-
        How this buy is doing against the buyer's goal, at the seller list
        grain.
    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
    SellerTimelineStageName:
      type: string
      enum:
        - received
        - screened
        - decided
        - forwarded
        - forward_failed
        - submitted
        - source_moderation
        - accepted
        - rejected
        - delivering
      description: >-
        Lifecycle stage of a buy exchange as seen from the storefront: received
        → screened → decided → forwarded / forward-failed → submitted → source
        moderation → accepted / rejected → delivering. Update exchanges reuse
        the same stages. `screened` is RESERVED for the acceptance-policy
        pre-screen record and is not emitted today — do not wait for it.
    SellerTimelineEvidence:
      type: object
      properties:
        at:
          type: string
          description: When it happened (ISO 8601).
        kind:
          type: string
          enum:
            - exchange_event
            - webhook
            - collapsed_run
          description: >-
            exchange_event = one attempt/response/poll observation; webhook = an
            inbound source webhook receipt; collapsed_run = N near-identical
            repeated events elided (retry loops).
        eventType:
          nullable: true
          description: >-
            Ledger event type (attempt_started, request_sent, response_received,
            precondition_failed, poll_result, webhook_received, terminalized).
          type: string
        outcome:
          nullable: true
          type: string
        errorCode:
          nullable: true
          description: Structured error code when the exchange failed.
          type: string
        recovery:
          nullable: true
          description: >-
            Recovery class of a failure: transient (retry can succeed),
            correctable (fix the input and resubmit), structural (no retry can
            succeed — escalate).
          type: string
          enum:
            - transient
            - correctable
            - structural
        attemptNumber:
          nullable: true
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        hiddenCount:
          nullable: true
          description: 'For collapsed_run: how many near-identical events were elided.'
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        detail:
          nullable: true
          description: Short human-readable note (webhook type, poll status, …).
          type: string
      required:
        - at
        - kind
        - eventType
        - outcome
        - errorCode
        - recovery
        - attemptNumber
        - hiddenCount
        - detail
      additionalProperties: false
      description: One observed fact supporting a timeline stage.
    SellerPayloadHighlights:
      type: object
      properties:
        flightStart:
          nullable: true
          type: string
        flightEnd:
          nullable: true
          type: string
        budget:
          nullable: true
          type: number
        currency:
          nullable: true
          type: string
        packageCount:
          nullable: true
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        productIds:
          type: array
          items:
            type: string
          description: Product ids referenced by the packages (first 20).
        targetingKeys:
          type: array
          items:
            type: string
          description: Top-level targeting dimensions present in the request (keys only).
        signalTargetingSelections:
          type: array
          items:
            type: object
            properties:
              scope:
                type: string
              signalId:
                type: string
              groupOperator:
                nullable: true
                type: string
                enum:
                  - any
                  - none
              minValue:
                nullable: true
                type: number
              maxValue:
                nullable: true
                type: number
            required:
              - scope
              - signalId
              - groupOperator
              - minValue
              - maxValue
            additionalProperties: false
          description: >-
            Product signal selections forwarded to sources (first 20), including
            a stable opaque reference, validated scope, include/exclude group
            operator, and numeric range. The original buyer-controlled signal
            identifier is not exposed to Seller agents.
      required:
        - flightStart
        - flightEnd
        - budget
        - currency
        - packageCount
        - productIds
        - targetingKeys
        - signalTargetingSelections
      additionalProperties: false
      description: >-
        Trafficker-grade highlights extracted from the forwarded payload:
        flight, budget, packages, targeting dimensions, and signal selections.
    GoalProgressTarget:
      oneOf:
        - type: object
          properties:
            kind:
              type: string
              enum:
                - cost_per
            value:
              type: number
          required:
            - kind
            - value
          additionalProperties: false
        - type: object
          properties:
            kind:
              type: string
              enum:
                - threshold_rate
            value:
              type: number
          required:
            - kind
            - value
          additionalProperties: false
        - type: object
          properties:
            kind:
              type: string
              enum:
                - per_ad_spend
            value:
              type: number
          required:
            - kind
            - value
          additionalProperties: false
        - type: object
          properties:
            kind:
              type: string
              enum:
                - maximize_value
          required:
            - kind
          additionalProperties: false
      description: >-
        A goal target: a cost per unit, a minimum rate per impression, a minimum
        return on ad spend, or maximise with no number.
      type: object
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key or access token

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.