Work with this as data
Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/scope3-campaigns-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
OpenAPI Specification
openapi: 3.2.0
info:
title: Scope3 Buyer Campaigns API
version: 2.0.0
description: 'REST API for advertisers to manage advertisers, campaigns, and reporting.
## Authentication
All endpoints require a Bearer token in the Authorization header:
```
Authorization: Bearer your-api-key
```
## Base URL
`https://api.interchange.io/api/v2/buyer`
## For AI Agents
AI agents can use the MCP endpoint at `/mcp/v2/buyer` 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/buyer
description: Production server
tags:
- name: Campaigns
description: Manage advertising campaigns
paths:
/campaigns:
get:
operationId: listCampaigns
summary: List campaigns
description: List campaigns with optional filtering by advertiser and status.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: query
name: advertiserId
schema:
description: Filter by advertiser ID
example: '12345'
type: string
pattern: ^\d+$
description: Filter by advertiser ID
- in: query
name: name
schema:
description: Filter by campaign name (case-insensitive, partial match)
example: Summer
type: string
description: Filter by campaign name (case-insensitive, partial match)
- in: query
name: status
schema:
description: Filter by campaign status. Accepts a single value or repeated values; pass "ALL" to include every status. Defaults to the non-terminal statuses (ACTIVE, DRAFT, PAUSED) — every campaign that could still spend. Completed, canceled, and archived campaigns require an explicit status filter (or "ALL").
example: ACTIVE
anyOf:
- type: array
items:
$ref: '#/components/schemas/CampaignStatusListFilter'
- allOf:
- $ref: '#/components/schemas/CampaignStatusListFilter'
description: Filter by campaign status. Accepts a single value or repeated values; pass "ALL" to include every status. Defaults to the non-terminal statuses (ACTIVE, DRAFT, PAUSED) — every campaign that could still spend. Completed, canceled, and archived campaigns require an explicit status filter (or "ALL").
- in: query
name: mode
schema:
description: Filter by campaign mode. Accepts a single mode (`?mode=directed`) or repeated values (`?mode=discovery&mode=performance`).
example: directed
anyOf:
- type: array
items:
$ref: '#/components/schemas/CampaignMode'
- allOf:
- $ref: '#/components/schemas/CampaignMode'
description: Filter by campaign mode. Accepts a single mode (`?mode=directed`) or repeated values (`?mode=discovery&mode=performance`).
- in: query
name: management
schema:
description: 'Filter by management state: "tracked" (campaigns the platform did not set up, mirrored from connected seller accounts), "managed" (campaigns authored or adopted through the platform), or "all" (both — the default). The default status lens (non-terminal: ACTIVE, DRAFT, PAUSED) is what keeps mirrored history out of the ambient list; browse tracked scale through the connected-account relationship rollup.'
example: managed
default: all
allOf:
- $ref: '#/components/schemas/CampaignManagementFilter'
description: 'Filter by management state: "tracked" (campaigns the platform did not set up, mirrored from connected seller accounts), "managed" (campaigns authored or adopted through the platform), or "all" (both — the default). The default status lens (non-terminal: ACTIVE, DRAFT, PAUSED) is what keeps mirrored history out of the ambient list; browse tracked scale through the connected-account relationship rollup.'
- in: query
name: mediaBuyStatus
schema:
description: Filter to only campaigns that have at least one media buy matching any of the given statuses
anyOf:
- type: array
items:
type: string
enum:
- DRAFT
- PENDING_APPROVAL
- INPUT_REQUIRED
- ACTIVE
- PAUSED
- COMPLETED
- CANCELED
- FAILED
- REJECTED
- ARCHIVED
- type: string
enum:
- DRAFT
- PENDING_APPROVAL
- INPUT_REQUIRED
- ACTIVE
- PAUSED
- COMPLETED
- CANCELED
- FAILED
- REJECTED
- ARCHIVED
description: Filter to only campaigns that have at least one media buy matching any of the given statuses
- in: query
name: includeArchived
schema:
description: 'Include archived (soft-deleted) campaigns in the response (default: false). Implicitly treated as true when the status filter contains ''ARCHIVED''.'
type: string
enum:
- 'true'
- 'false'
description: 'Include archived (soft-deleted) campaigns in the response (default: false). Implicitly treated as true when the status filter contains ''ARCHIVED''.'
- in: query
name: fields
schema:
description: Optional response enrichment fields. Pass geo_metro_names to include display labels for geo_metros from the local label table.
example: geo_metro_names
anyOf:
- type: string
- type: array
items:
type: string
description: Optional response enrichment fields. Pass geo_metro_names to include display labels for geo_metros from the local label table.
- in: query
name: cursor
schema:
description: Opaque pagination cursor returned by the previous response. When provided, skip is derived from the cursor and any explicit skip param is ignored.
example: eyJza2lwIjoxMH0=
type: string
description: Opaque pagination cursor returned by the previous response. When provided, skip is derived from the cursor and any explicit skip param is ignored.
- in: query
name: take
schema:
description: Number of results to return (max 250)
example: 50
default: 50
type: integer
maximum: 250
minimum: 1
description: Number of results to return (max 250)
- in: query
name: skip
schema:
description: Number of results to skip for pagination
example: 0
default: 0
type: integer
minimum: 0
maximum: 9007199254740991
description: Number of results to skip for pagination
responses:
'200':
description: List campaigns
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignListResponse'
'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'
post:
operationId: createCampaign
summary: Create campaign
description: Create a new campaign. Optional fields like discoveryId and performanceConfig can be provided at creation or set later via update. The `brief` and `name` fields are screened by the content-moderation engine and rejected with 422 `CONTENT_MODERATION_BLOCKED` on policy violation.
tags:
- Campaigns
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateCampaignOpenApiBody'
responses:
'201':
description: Create campaign
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Content rejected by moderation policy. The `brief` or `name` matched a prompt-injection / jailbreak / hate-speech / CSAM / violence / misinformation pattern, or failed the business-context gate.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/campaigns/{campaignId}:
put:
operationId: updateCampaign
summary: Update campaign
description: Update an existing campaign. All fields are optional. The `brief` and `name` fields are screened by the content-moderation engine and rejected with 422 `CONTENT_MODERATION_BLOCKED` on policy violation.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateCampaignOpenApiBody'
responses:
'200':
description: Update campaign
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Content rejected by moderation policy. See `POST /campaigns` for full criteria.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
get:
operationId: getCampaign
summary: Get campaign
description: Get detailed information about a specific campaign.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: query
name: fresh
schema:
description: When true, bypasses the server-side media-buy query cache for this request. Use after a successful lifecycle write when immediate authoritative local readback is required.
example: 'true'
anyOf:
- type: boolean
- type: string
enum:
- 'true'
- 'false'
description: When true, bypasses the server-side media-buy query cache for this request. Use after a successful lifecycle write when immediate authoritative local readback is required.
- in: query
name: mediaBuyId
schema:
description: Filter the embedded `mediaBuys[]` array to only the media buys with these IDs. Accepts a single ID (`?mediaBuyId=mb_X`) or repeated values (`?mediaBuyId=mb_X&mediaBuyId=mb_Y`). The campaign object itself is unchanged; only the nested media buys are narrowed. Use to drill into specific buys without loading every buy on the campaign (helps when the full tree exceeds an LLM context window). `mediaBuyRefs` still lists every buy on the campaign so callers can discover IDs.
example: mb_ETBn4gJ9Wu
anyOf:
- type: array
items:
type: string
- type: string
description: Filter the embedded `mediaBuys[]` array to only the media buys with these IDs. Accepts a single ID (`?mediaBuyId=mb_X`) or repeated values (`?mediaBuyId=mb_X&mediaBuyId=mb_Y`). The campaign object itself is unchanged; only the nested media buys are narrowed. Use to drill into specific buys without loading every buy on the campaign (helps when the full tree exceeds an LLM context window). `mediaBuyRefs` still lists every buy on the campaign so callers can discover IDs.
- in: query
name: includePropertyLists
schema:
description: When true, embed a `propertyLists` aggregate showing the include/exclude lists actually applied to this campaign via its media-buy packages. Defaults to false to keep the response small. To fetch the aggregate without the rest of the campaign, use `GET /campaigns/:campaignId/property-lists`.
example: 'true'
anyOf:
- type: boolean
- type: string
enum:
- 'true'
- 'false'
description: When true, embed a `propertyLists` aggregate showing the include/exclude lists actually applied to this campaign via its media-buy packages. Defaults to false to keep the response small. To fetch the aggregate without the rest of the campaign, use `GET /campaigns/:campaignId/property-lists`.
- in: query
name: includeProductDetails
schema:
description: When false, strips `formatOptions` from each product in `mediaBuys[].products[]`. Defaults to true (full product details included). Set to false when the goal is to read `packageId` values or other non-product fields and the full product payload would cause response truncation.
example: 'false'
anyOf:
- type: boolean
- type: string
enum:
- 'true'
- 'false'
description: When false, strips `formatOptions` from each product in `mediaBuys[].products[]`. Defaults to true (full product details included). Set to false when the goal is to read `packageId` values or other non-product fields and the full product payload would cause response truncation.
- in: query
name: fields
schema:
description: Optional response enrichment fields. Pass geo_metro_names to include display labels for geo_metros from the local label table.
example: geo_metro_names
anyOf:
- type: string
- type: array
items:
type: string
description: Optional response enrichment fields. Pass geo_metro_names to include display labels for geo_metros from the local label table.
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
responses:
'200':
description: Get campaign
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignResponse'
'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'
delete:
operationId: deleteCampaign
summary: Delete campaign
description: Delete a campaign.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
responses:
'204':
description: No content
'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'
/campaigns/{campaignId}/delivery:
get:
operationId: getDirectedCampaignDelivery
summary: Get campaign delivery (alpha)
description: Read live delivery through a tracked campaign's connected seller account or an unambiguous single-storefront platform campaign's persisted provider media-buy identity. The latest totals are persisted; PostHog-gated alpha with no upstream write.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: query
name: startDate
schema:
description: Inclusive reporting start. Defaults to the subscription backfill boundary, capped at one year ago.
example: '2026-07-10'
type: string
format: date
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])))$
description: Inclusive reporting start. Defaults to the subscription backfill boundary, capped at one year ago.
- in: query
name: endDate
schema:
description: Inclusive reporting end. Defaults to yesterday because same-day platform data may be incomplete.
example: '2026-07-10'
type: string
format: date
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])))$
description: Inclusive reporting end. Defaults to yesterday because same-day platform data may be incomplete.
- in: query
name: placementBreakdown
schema:
description: Request canonical AdCP by_placement delivery rows when the product declares placement reporting support.
type: string
enum:
- 'true'
- 'false'
description: Request canonical AdCP by_placement delivery rows when the product declares placement reporting support.
- in: query
name: placementLimit
schema:
description: Maximum placement rows per package. Requires placementBreakdown=true.
type: integer
maximum: 9007199254740991
minimum: 1
description: Maximum placement rows per package. Requires placementBreakdown=true.
- in: query
name: placementSortBy
schema:
description: Metric used to order placement rows before applying placementLimit.
type: string
enum:
- impressions
- spend
- clicks
- conversions
- in: path
name: campaignId
schema:
type: string
minLength: 1
required: true
responses:
'200':
description: Get campaign delivery (alpha)
content:
application/json:
schema:
$ref: '#/components/schemas/DirectedCampaignDeliveryResponse'
'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: The directed-campaigns alpha is not enabled.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: No directed campaign mirror with this id.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/campaigns/{campaignId}/execute:
post:
operationId: executeCampaign
summary: Execute campaign
description: 'Launch/execute a campaign to start delivering ads. Pass `debug: true` in the request body to include detailed debug information in error responses.'
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExecuteCampaignBody'
responses:
'200':
description: Execute campaign
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignStatusChangeResponse'
'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'
/campaigns/{campaignId}/pause:
post:
operationId: pauseCampaign
summary: Pause campaign
description: Pause a running campaign. Cascades to all active media buys and reports the per-media-buy outcome.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
responses:
'200':
description: Pause campaign
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignCascadeResponse'
'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'
/campaigns/{campaignId}/reactivate:
post:
operationId: reactivateCampaign
summary: Reactivate campaign
description: Reactivate a paused campaign. The campaign must be PAUSED. Cascades to all paused media buys and reports the per-media-buy outcome.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
responses:
'200':
description: Reactivate campaign
content:
application/json:
schema:
$ref: '#/components/schemas/CampaignCascadeResponse'
'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'
/campaigns/{campaignId}/auto-select-products:
post:
operationId: autoSelectProducts
summary: Auto-select products
description: Automatically select products for a performance campaign using a 3-tier strategy (scoring → measurability → CPM heuristic). Campaign must be in DRAFT status. Supports iterative refinement via ADCP-style refine directives — review results then re-call with include/omit/more_like_this to adjust selections. Replaces all previously selected products.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AutoSelectProductsRequest'
responses:
'200':
description: Auto-select products
content:
application/json:
schema:
$ref: '#/components/schemas/AutoSelectProductsResponse'
'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'
/campaigns/{campaignId}/media-buy-status:
get:
operationId: getMediaBuyAdcpStatus
summary: Get media buy ADCP status
description: Poll ADCP sales agents for the live status of all media buys in a campaign. Returns current ADCP status for each media buy and updates local status when changes are detected.
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: id
schema:
description: Unique identifier for the campaign
example: cmp_987654321
type: string
minLength: 1
required: true
description: Unique identifier for the campaign
responses:
'200':
description: Get media buy ADCP status
content:
application/json:
schema:
$ref: '#/components/schemas/GetAdcpStatusOutput'
'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'
/media-buys/{mediaBuyId}:
get:
operationId: getMediaBuy
summary: Get media buy
description: 'Get a single media buy with its why-visibility fields: pendingReason (why it is not delivering yet and since when), buyer-safe errorCode with ownership, the sanitized source message, forwardedAt, and the buyerReference support handle. One call answers "why is my buy stuck". Use GET /campaigns/{campaignId} for packages, products, and delivery.'
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: mediaBuyId
schema:
description: Buyer media buy ID
example: mb_ETBn4gJ9Wu
type: string
minLength: 1
required: true
description: Buyer media buy ID
responses:
'200':
description: Get media buy
content:
application/json:
schema:
$ref: '#/components/schemas/BuyerMediaBuyResponse'
'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: Caller is not a buyer — the route is mounted behind the buyer role guard.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: No media buy with this id owned by the caller.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
operationId: updateMediaBuy
summary: Update media buy
description: 'Partially update a single media buy, resolved top-level by mediaBuyId — the owning campaign is resolved server-side, consistent with GET /media-buys/{mediaBuyId}. Rejected outright (not a warning) when it would violate a campaign invariant: currency (a product''s replacement pricing option settles in a different currency than this buy), budget headroom (the update would exceed the campaign''s remaining all-in budget), or mode compatibility (the campaign is directed and has no platform-managed update path). A flight date outside the campaign''s current window is not a failure — the campaign flight is widened to cover it and a warning is returned.'
tags:
- Campaigns
security:
- bearerAuth: []
parameters:
- in: path
name: mediaBuyId
schema:
description: Buyer media buy ID
example: mb_ETBn4gJ9Wu
type: string
minLength: 1
required: true
description: Buyer media buy ID
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateMediaBuyRequest'
responses:
'200':
description: Update media buy
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateMediaBuyResponse'
# --- truncated at 32 KB (633 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/scope3/refs/heads/main/openapi/scope3-campaigns-api-openapi.yml