Skip to main content
A modular inventory source is an operator-managed source composed from smaller modules: an inventory feed, an optional booking ledger, optional execution modules, and optional human work queues. The storefront still presents one buyer-facing sales-agent surface. The modules describe how that source gets inventory, prevents overbooking, books upstream supply, traffics campaigns, syncs creatives, and imports reporting. Use a modular source when inventory and execution do not come from one fully compliant upstream sales agent. For example, a publisher may send a periodic avails spreadsheet, confirm bookings manually, traffic a campaign in an addressable TV system, and upload the final delivery report after the campaign ends.
Modular source operations are storefront-operator endpoints. Buyer agents do not call them directly. Buyers still transact through the storefront’s AdCP media-buy workflow.
All examples use the storefront base URL:
export BASE=https://api.interchange.io/api/v2/storefront
export SCOPE3_API_KEY=scope3_<your_api_key>

1. Check readiness

Start with the runtime projection:
curl "$BASE/inventory-sources/retail-modular/modular" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
The response includes lifecycleSummary, one row per stage:
StatusMeaning
UNSUPPORTEDNo active module implements this stage.
MISSING_SETUPA module supports the stage, but required module config is missing.
RUNTIME_INPUTS_REQUIREDSetup is complete, but the stage needs runtime input such as an avails feed, creative, or report upload.
HITL_PENDINGA human work item is open for this stage.
READYThe stage has enough setup and runtime inputs for the current source state.
BLOCKEDA module has an error or source-health issue that needs operator attention.
activeAvailCount tells you whether the source currently has usable avails. openWorkItemCountsByKind tells you what human queue is blocking a module or stage, for example MAP_CREATIVE_REF or UPLOAD_FINAL_REPORT.

2. Preview, then commit avails

An inventory-feed module accepts normalized avails. The feed can come from a publisher upload, a pasted CSV/JSON payload, or a file that Murph has parsed into rows. Murph previews parsed rows first; commit the feed only after an operator confirms the normalized rows and confirms impressionsCapacity is net sellable capacity.
curl -X POST "$BASE/inventory-sources/retail-modular/modular/avails-feed" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "confirmed": true,
    "avails": [
      {
        "availId": "sports-week-2026-07",
        "collectionId": "connected-tv",
        "collectionName": "Connected TV",
        "name": "Sports week CTV impressions",
        "startTime": "2026-07-01T00:00:00.000Z",
        "endTime": "2026-07-31T23:59:59.000Z",
        "impressionsCapacity": 1500000,
        "cpm": 22,
        "currency": "USD",
        "targeting": {
          "market": "South Africa",
          "screen": "CTV"
        },
        "sourceMetadata": {
          "publisher": "Example Network",
          "upstreamBookedImpressions": 300000
        }
      }
    ]
  }'
Ingestion upserts by availId. If an avail already has held or booked impressions, the feed update will not reduce capacity below those commitments.

3. Inspect product projections

List the product-like projections generated from active avails:
curl "$BASE/inventory-sources/retail-modular/modular/products" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
Each product maps back to one normalized avail. Generic feed-only sources return cadent: null. Cadent fields appear only when the source has an active Cadent execution module, so uploaded publisher avails are not implicitly treated as Cadent-backed inventory.

4. Reserve capacity

If the source has an active booking-ledger module, hold capacity before finalizing:
curl -X POST "$BASE/inventory-sources/retail-modular/modular/reservations" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "avail:sports-week-2026-07",
    "mediaBuyId": "mb_123",
    "buyerCustomerId": 42,
    "requestedImpressions": 250000,
    "holdMinutes": 60
  }'
You can pass either productId or availId. The reservation prevents this modular source from overbooking against capacity it controls. Upstream booked supply must be removed from impressionsCapacity before commit; upstreamBookedImpressions is explanatory metadata and does not increase sellable capacity.

5. Prepare supported execution handoffs

Execution is module-specific. In the current Cadent demo path, the handoff requires an active booking ledger and an active Cadent execution module. It keeps the reservation HELD, renders the Cadent campaign XML, and creates source-side work items for trafficking, creative mapping, and reporting. Do not treat the line as upstream-booked until the trafficking step succeeds; completing the TRAFFIC_TO_CADENT work item moves the held reservation to BOOKED.
curl -X POST "$BASE/inventory-sources/talpa-cadent-demo/modular/bookings/finalize" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mediaBuyId": "mb_123",
    "availId": "sports-week-2026-07",
    "campaignName": "July CTV sports",
    "advertiserName": "Example Advertiser",
    "creative": {
      "format": "video",
      "durationSeconds": 30,
      "assetUrl": "https://assets.example.com/creative.mp4"
    }
  }'
For a source that books through a person rather than an execution API, the same lifecycle should surface a human work item instead of pretending the stage is automated.

6. Release capacity

Release a held reservation when a buyer cancels, a hold expires, or the execution handoff fails:
curl -X POST "$BASE/inventory-sources/retail-modular/modular/bookings/release" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mediaBuyId": "mb_123",
    "availId": "sports-week-2026-07"
  }'

7. Work the human queue

Some stages are intentionally human-in-the-loop. Common examples:
Work item kindWhen it appears
CONFIRM_AVAILSAn operator must confirm or correct incoming avails before products are shown.
MAP_CREATIVE_REFA buyer creative needs a broadcast-system creative ID or trafficking reference.
TRAFFIC_TO_CADENTA Cadent campaign payload is ready for a human operator to traffic; completing it books the held reservation.
UPLOAD_FINAL_REPORTThe campaign has ended and delivery reporting needs a file upload.
RESOLVE_SOURCE_HEALTHA module is blocked or misconfigured.
These work items belong to the inventory source, not the buyer-facing storefront task. The storefront can still expose buyer task status or webhooks while source operators complete the underlying queue.

Demo source

POST /inventory-sources/modular/cadent-demo creates or resets a demo-only source with static avails, a booking ledger, and Cadent execution. Use it to test the end-to-end lifecycle, not as a publisher avails ingestion path. Demo source IDs must be talpa-cadent-demo or start with demo-.

Get modular readiness

Inspect lifecycle status, module contracts, setup gaps, and work-item counts

Update module config

Write non-secret module setup fields