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

# Connecting Ad Platform Accounts

> Grant Scope3 access to advertiser accounts on Meta, TikTok, Google Ads, and other ad platforms

## Overview

Some storefronts run through direct ad platform adapters instead of a publisher
sales agent. Before Scope3 can discover products, create media buys, sync
creatives, or read delivery from those adapters, the customer must connect the
relevant advertiser account to Scope3 through the platform's own account-sharing
or OAuth flow.

This guide is written for legal, procurement, and platform admins who need to
approve the access request. For what a connection actually is — organization
vs advertiser accounts, manager-account (MCC / Business Manager) expansion,
account types, and how discovered accounts map to your advertisers — see
[Ad Platform Accounts](/v2/concepts/ad-platform-accounts).

When Claude, ChatGPT, or another generic MCP client operates a connected
account, it can call `get_adcp_tool_schema` before a write. Start with the tool
name, then inspect the returned nested paths—for example,
`packages[].targeting_overlay` before `create_media_buy`, and `revision` plus
`packages[]` before `update_media_buy`. This returns the exact versioned schema
fragment on demand without loading every platform contract into the initial
tool list. Clients should inspect those fields rather than guess targeting,
creative, budget, or lifecycle request shapes.

<Note>
  This page covers ad platform account access such as Meta, TikTok, Google Ads,
  Snap, LinkedIn, Pinterest, Reddit, and Amazon Ads. Google Ads is separate from
  Google Ad Manager. For Google Ad Manager inventory-source setup, see the
  [Storefront onboarding guide](/v2/setup/storefront-onboarding#google-ad-manager-service-account-grant).
</Note>

## What Write Access Means

When Scope3 asks for platform write access, it is asking for permission to
operate campaigns and related advertising objects for the advertiser accounts
that the customer explicitly grants. It does not mean Scope3 needs broad
business administration rights.

Write access may be used to:

* Create, update, pause, or resume campaign objects, ad groups or ad sets, ads,
  budgets, targeting, and flight dates.
* Upload or sync creative assets and create platform-native creative records.
* Create or update first-party audience segments when the customer enables
  audience sync.
* Create or update product catalogs or feeds when the media-buy workflow uses
  catalog products.
* Read delivery, spend, approval status, pacing, and performance reporting.
* Send conversion or event data when measurement is configured for the
  advertiser.
* List connected advertiser accounts so the customer can choose the right one.

Scope3 does not need permission to:

* Add, edit, or delete users.
* Take ownership of the customer's business account or advertiser account.
* Manage unrelated advertiser accounts that were not shared with Scope3.
* Change security settings, login settings, business verification, or platform
  account ownership.
* Manage billing users or finance roles unless a customer has a separate,
  explicitly approved billing workflow.

## Recommended Access Pattern

Use the platform's partner or manager-account sharing flow where available. The
customer remains the owner of the business and advertiser accounts, and can
remove or reduce Scope3's access from the platform console at any time.

For activation workflows, choose the least broad role that can both manage ads
and read reporting. Use read-only access only for reporting-only pilots.

| Use case            | Recommended access                                                           |
| ------------------- | ---------------------------------------------------------------------------- |
| Reporting only      | Read/reporting role for the advertiser account                               |
| Campaign activation | Campaign/ad management role plus reporting                                   |
| Creative sync       | Campaign/ad management role plus access to required creative identity assets |
| Audience sync       | Campaign/ad management role plus audience/customer-list permissions          |
| Catalog products    | Campaign/ad management role plus catalog/feed permissions                    |

## Agencies: Link the Manager Account

When an agency runs media for several clients, the pattern is the same on every
platform:

1. Each client grants access on the **platform side** — to the agency's
   container (Business Manager, manager account / MCC, Business Center) or, on
   platforms without an organization container, to the agency's user.
2. The agency connects **its own login** in Interchange, once.
3. Every client account the grant reaches is discovered under that one
   connection, grouped under the manager account where the platform has one.
4. The agency maps each client account to the matching advertiser on the
   **Advertiser mapping** tab (**Settings → Connections**).

Organization-level linking is the agency-correct move because one grant
surfaces the whole client portfolio. Linking a single client-shared ad account
also works, but each additional client then needs its own connect. The
per-platform sections below include an **Agency setup** subsection with the
client-side steps.

## Platform Summary

| Platform   | Default customer grant                                                                                 | Read-only fallback                   | Usually not required                                            |
| ---------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------ | --------------------------------------------------------------- |
| Meta       | Partner access to the ad account with campaign management and performance reporting                    | View performance only                | Full business portfolio control, billing admin, user management |
| TikTok     | Business Center partner access to the advertiser account as Operator                                   | Analyst                              | Business Center Admin, finance roles, user management           |
| Google Ads | Manager-account or account access that can manage campaigns and read reporting                         | Read-only reporting role             | Billing admin, user management                                  |
| Snap       | OAuth or partner/account access with ads management and reporting                                      | Reporting-only role when supported   | Organization admin, user management                             |
| LinkedIn   | OAuth or ad account access with ads read/write and reporting                                           | Reporting-only role when supported   | Company Page admin unless organic/social posting is required    |
| Pinterest  | OAuth or ad account access with ads read/write and reporting                                           | Reporting-only role when supported   | Account ownership or user administration                        |
| Reddit     | OAuth or ads account access with ads read/write and conversion permissions when measurement is enabled | Reporting-only role when supported   | Profile ownership, user administration                          |
| Spotify    | OAuth access from a user who can manage campaigns and read reporting for the advertiser account        | Reporting-only access when supported | Business ownership, billing admin, user management              |
| Amazon Ads | Advertising account access with campaign-management permission                                         | Reporting-only role when supported   | Retail account administration, billing admin                    |

## Meta

Scope3's validated Meta onboarding path uses an Ad Account owned by a Meta
Business Portfolio. Personal ad accounts can appear during account discovery,
but campaign activation with them has not been validated. For production
onboarding, use a Business Portfolio-owned account.

In Meta Business Suite or Meta Business Manager, add the Scope3 Business
Portfolio (Business ID: 1091793362240769) as a partner, then grant it access
only to the advertiser assets required for the workflow.

Default grant for activation:

* The relevant ad account.
* Campaign management access.
* Performance reporting access.

Additional assets may be needed depending on the campaign:

* Facebook Page or Instagram account access when ads use those identities.
* Pixel or dataset access when conversion events or conversion optimization are
  configured.
* Catalog access when catalog products are used.

Meta's OAuth consent can include `ads_management`, `ads_read`, and
`business_management`. The customer-side asset grant should still stay scoped
to the specific business assets needed for the advertiser workflow.

Scope3 does not need full control of the customer's business portfolio, broad
account-settings control, billing administration, or permission to add, edit, or
delete users.

### Real-time Meta signals

After you select a Meta ad account, Scope3 automatically installs and repairs
its Meta app subscription for processing completion, objects with issues, ad
recommendations, creative fatigue, and product-set issues. No separate Ads
Manager setup is required for each connected account. The connection must keep
campaign-management permission so Meta allows the subscription and subsequent
authoritative readback.

These notifications reduce detection latency; they do not replace provider
readback. Scope3 verifies each signed notification and, when it identifies an
ad, ad set, or campaign, reads that object with the current connection before
changing canonical campaign or creative state. Polling remains the fallback if
delivery is delayed or missed, and duplicate deliveries are deduplicated.

`get_media_buys` and `list_creatives` can include recent observations in
the response-level `ext.scope3_provider_signals` object as
`{ version: "1", provider: "meta", signals: [...] }`. Creative-fatigue entries
include the stable `creative_id` when available, the fatigue level when Meta
provides it, and the observation time. Meta emits creative-fatigue notifications
for active ads only. These observations are Scope3 extensions, not canonical
AdCP status fields.

### Brief planning in MCP hosts

When Claude, ChatGPT, or another MCP host calls Meta `get_products` with a
non-empty brief, Scope3 uses assisted planning by default. The response includes
the interpreted objective, optimization, geography, demographics, creative
format, assumptions, and rationale. If the brief is ambiguous or asks for a
targeting or creative decision that Scope3 cannot represent exactly, the call
returns clarification requirements and no actionable product instead of silently
guessing.

Use `buying_mode: "wholesale"` only when the buyer explicitly wants raw Meta
catalogue discovery without brief-strategy provenance. Wholesale discovery does
not claim that Scope3 interpreted the advertiser's brief. Connected-account campaign
planning uses its separate propose-and-accept flow before an assisted write.

### Pixel and dataset ownership

Meta measurement setup is scoped to the selected ad account. Scope3 lists the
complete Pixel/Dataset inventory Meta authorizes on that account; if Meta
returns no sources, Scope3 reports an empty list instead of substituting the ad
account ID. Installation snippets and Event Match Quality appear only for a
source verified in that inventory. A requested missing or foreign source is
reported as failed. When you request specific source IDs, Scope3 returns only
those IDs and does not inspect Event Match Quality for other owned sources.

Before sending a conversion event, an account-bound connector rechecks that the
Pixel/Dataset is still authorized. If Meta discovery, pagination, or ownership
verification fails, Scope3 sends no conversion event. The connector rejects a
request account that differs from its authenticated selected account, and a
pagination continuation cannot change API version, account, or resource. MCP
hosts do not need to add an account field to `log_event`: a complete
`sync_event_sources` call learns private tenant-scoped ownership for the
selected account. A later host-neutral event resolves exactly one fresh learned
binding, then rechecks the complete Pixel/Dataset inventory with the current
connection before sending. Missing, ambiguous, stale, revoked, or temporarily
unavailable ownership sends nothing and returns a re-sync or retry error instead
of guessing an account.

### Meta creative format discovery

Meta creative-format discovery honors exact legacy named-format references,
required asset types, minimum width and height, and case-insensitive name
search. These filters compose: every supplied filter must match. A request that
matches nothing returns an empty list instead of the complete Meta catalog.

Paginated discovery returns a bounded page and a signed continuation cursor.
The cursor is short-lived, retry-safe, and bound to the authenticated tenant,
account context, filters, page size, and current catalog revision. Safe retries
return the same page; changed, expired, or tampered cursors are rejected. Filters that the static Meta
catalog cannot verify—such as publisher/property, accessibility, disclosure,
input/output transformation, responsive, and maximum-dimension filters—return
an error instead of being ignored.

Meta creative sync is scoped to the selected ad account. Image and video
creatives keep the caller's creative ID and declared Meta format across sync,
list, and media-buy operations, while the provider's creative ID remains the
trafficking identity. Submitted image/video assets are returned on list. Review
status comes from explicit provider review evidence on ads; paused, active, or
archived lifecycle status alone is never reported as approval. A creative that
has not been attached to an ad remains `processing`.

TikTok creative sync keeps your original creative ID and TikTok format across
adapter restarts. Scope3 stores uploaded media and Spark published-post
references under the selected advertiser, then uses the provider media or post
ID as the typed TikTok trafficking reference. Mapped list rows return the normalized submitted image
or video URL. Retrying the same upload reuses provider media after readback; an
upload whose outcome is unknown is not repeated automatically. Image success
always requires an exact, displayable readback from the selected advertiser's
media library.
For video, Scope3 records the TikTok video ID before checking processing status,
so a temporary missing-status response resumes against the same video instead
of uploading another copy. The same exact-ID recovery applies if the adapter
restarts between its final durable journal steps. Structured TikTok format
references must use the format authority returned by `list_creative_formats`.
Image and video URLs must include a recognized file
extension that matches both the supplied asset type and selected TikTok format;
extensionless, audio, and mismatched media are rejected before upload. Changed
images use a bounded source-digest filename to satisfy TikTok's per-account
filename uniqueness requirement.
TikTok carousel is available for Reach, Traffic, Website Conversions, and App
Promotion products. Supply one `tiktok_carousel` creative with 2-35 distinct
square image assets in the advertised order. Interchange uploads every image to
the selected advertiser and waits for TikTok to mark each exact image both
displayable and carousel-usable. It then creates one paused `CAROUSEL` ad and
requires TikTok to return the same complete ordered image list. Missing,
duplicate, reordered, substituted, or ineligible images stop the campaign before
activation. `list_creatives` returns the original carousel as one source
creative instead of exposing its uploaded children as separate duplicates.

TikTok's Marketing API does not expose a provider-native creative
translation/localization operation. Interchange therefore does not advertise
native creative localization and does not infer it from language targeting.
`list_creatives` returns the original ID for Scope3-synced creatives and keeps
unmapped provider-native images/videos visible under their provider IDs. It
exhausts uploaded media, assigned ads, performance pages, and advertiser-authorized
`AUTH_CODE` TikTok VIDEO rows before claiming a complete result. A missing
connection identity, a cross-account or inactive mapping, stale provider media,
or malformed, expired, or unauthorized Spark reference stops the operation
before campaign creation. Only explicit, provider-authorized AUTH\_CODE rows are
accepted; missing identity types, legacy identity types, carousel rows, revoked
authorization, and missing provider authorization start times fail closed. The stored Spark
post and advertiser-bound identity must match the active provider generation.
Uploaded media must read back as displayable before campaign creation. Channel
accounts use a deterministic key over the advertiser and exact AUTH\_CODE identity,
so distinct grants remain isolated. A completed older creative generation cannot
report unchanged or become active after a newer generation exists. Its historical
assignment, review, and performance evidence remains joined to the active source
creative. Each newly created TikTok ad remains paused while Scope3 requests its
explicit creative fields. The exact uploaded media ID and format, or the exact
Spark post ID and AUTH\_CODE identity, must read back before activation; a missing
or substituted creative triggers campaign cleanup. Media-library
displayability and Spark authorization do not prove ad review: an unassigned
creative remains `processing`. Explicit assigned-ad readback supplies approval
or rejection status plus package and redacted provider-status evidence. Approval
requires every assignment to be explicitly delivering or completed. Audit
denials, partial approval, Promote audit failure, and terminal transcode failure
are rejected; paused, pending, partial-review, budget, schedule, account, and
asset-lifecycle states remain processing. Unknown provider statuses fail closed.
Assignment inventory is mandatory; any incomplete page or transport failure fails the read.
Scope3 verifies that each assignment and review-evidence row belongs to the
selected TikTok advertiser; foreign or malformed evidence fails the read rather
than changing a creative's assignment or review state.
TikTok's AUTH\_CODE endpoints do not return post publication time. A Spark row
synced through Scope3 uses its durable registration timestamps. A provider-native
authorized row uses TikTok's UTC authorization start as its creative-availability
timestamp and labels that basis in extension evidence; authorization timestamps
are not presented as post creation or modification time. TikTok timestamps must
use the documented UTC form or explicitly zoned RFC3339; numeric epochs,
date-only values, offsetless ISO strings, and invalid calendar dates are rejected.
Existing TikTok connections
must remain connected through Settings > Connections and grant TikTok Posts
Management query access so Scope3 can verify AUTH\_CODE authorization before writes.

Provider-native creatives that were not synced through Scope3 remain visible,
but are returned under their provider ID with the explicit
`meta_unmapped_provider_creative` format. Scope3 does not infer an upload format
or reconstruct a source-media URL that Meta does not return. After a synced
creative is updated, assignment, review, and delivery reads include every
retained provider generation while returning only the current source creative.
List cursors are account-, filter-, and snapshot-bound; restart pagination when
the provider inventory or requested delivery snapshot changes.

Scope3 discovers the Facebook Pages authorized for the selected ad account. If
there is exactly one, `page_id` may be omitted and Scope3 selects it. If there
are several, validation returns bounded `page_id` and Page-name choices without
writing. If more choices remain, repeat the request with the returned
`ext.meta_page_selection_offset` to page through them, then include the chosen
`page_id`. Include `instagram_actor_id` only when the ad should use
that authorized Instagram identity; explicit Page and Instagram IDs are
validated against the selected account before any upload or creative write.
Use the legacy Meta `format_id` returned by `list_creative_formats`. Image and
video inputs must satisfy that format's file type, dimensions, aspect ratio,
duration, size, text, and link requirements. Public HTTPS URLs remain accepted.
The portable Meta upload tool in supported MCP hosts instead returns a private,
account-bound `scope3-asset://` reference; `sync_creatives` exchanges that stable
reference for a short-lived provider delivery URL without exposing the private
object publicly. Scope3 validates required roles and request metadata before
writing. For public image URLs it also pins public DNS, rejects redirects, caps
downloaded bytes, and verifies JPEG/PNG content; Meta performs the final
provider-side media processing. Portable upload availability depends on the
Storefront environment having its private asset store configured.

`sync_creatives.assignments` supports one `meta_image_feed` creative assigned to
one existing paused package. Scope3 verifies that the package and its campaign
belong to the selected account and are paused before creative writes, creates a
paused Meta ad, records that provider ad before checking the package collection,
and requires exact provider ad, creative, account, campaign, package, and
paused-status readback. Retries reconcile the recorded ad instead of creating
another one. Only that fully proven result returns the package in `assigned_to`
with `ext.manual_action_count: 0`; ambiguity or drift is returned in
`assignment_errors` without a zero-manual claim. Assignment during
`create_media_buy` remains supported too. Sync-time assignment is a separate
post-create operation; the current assisted decision plan does not choose or
bind creative and actor fields.

Carousel child attachments, native Meta translation/localization, assignment
weights, placement-specific assignments, multiple sync-time assignments, and
creative deletion are not currently supported. Generated formats without a
provider build-and-readback path are not advertised. Callers should not treat a
successful upload as evidence that native localization ran, that provider
review completed, or that no Ads Manager follow-up is required. Empty
unsupported option collections are accepted as no-ops, but non-empty unsupported
mutations fail before any provider write. Localization hints, including a raw Meta
`asset_feed_spec`, also fail before Page discovery, media upload, or durable
creative reservation instead of being silently removed from an otherwise valid
creative.

Meta's current manual multi-language representation uses an
[`asset_feed_spec`](https://developers.facebook.com/docs/marketing-api/dyn-language-optimization/)
with `optimization_type: "LANGUAGE"`: bodies, titles, descriptions, links, and
media carry labels, `asset_customization_rules` bind those labels to Meta locale
keys, and exactly one rule is the default. Supported keys come from Meta's
`/search?type=adlocale` response. Scope3 does not pass this provider object
through until the request has a typed AdCP representation and every requested
locale, copy/media asset, Page/Instagram actor, provider creative, and provider
variant label can be read back exactly. Dry runs read durable idempotency state
and provider readback where needed, and perform no provider or ledger mutation.

### Agency setup

The client adds the agency's Business Manager as a **Partner** on the ad
account — in Business settings, under Partners, using the agency's Business
Manager ID — and assigns the same scoped access described above (campaign
management plus performance reporting, plus Page, pixel, or catalog assets as
needed). The agency then connects its own Business Manager login in
Interchange; every client ad account the partner grants reach arrives under
the agency's Business Manager on the **Advertiser mapping** tab, ready to map
to the right advertiser.

### Supported buying types

Interchange creates all Meta campaigns using the **Auction** buying type.
Reservation (Reach & Frequency) buying type is not supported.

### Meta app-install readiness

For Meta app-install campaigns, plan the campaign around mobile-first creative
and privacy-safe app-event measurement before scaling spend:

* Use Advantage+ App Campaigns as the default starting structure unless the
  advertiser has a specific manual-buying reason.
* Start with lowest-cost bidding while the campaign is learning; move to cost
  controls only after the account has stable cost and conversion history.
* Keep placements open across Feed, Stories, and Reels so Meta can allocate
  delivery, and design Reels-ready vertical creative rather than treating Reels
  as an afterthought.
* Launch with at least 5-10 distinct creative variants. Prefer short vertical
  video that shows the app experience quickly, then keep refreshing variants as
  the campaign learns.
* For iOS, confirm SKAdNetwork or MMP postbacks and Conversions API event
  forwarding before scaling. Evaluate D7/D30 cohort ROAS instead of day-1
  last-click results.
* Once trial, purchase, subscription, or other downstream app events are flowing
  reliably, optimize toward those events rather than raw installs.

## TikTok

Ask the customer to share the advertiser account from TikTok Business Center to
Scope3's Business Center as a partner.

Default grant for activation:

* Advertiser account role: `Operator`.

Use `Analyst` only for reporting-only access. `Analyst` can view ads,
performance, and reports, but it cannot create or edit ads or manage audiences.

Use `Admin` only when there is an explicitly approved reason to manage ad
account settings. Admin is not the default activation role.

TikTok [fixes an ad account's currency when the account is created](https://ads.tiktok.com/help/article/account-setup-faq?lang=en\&redirected=2).
Interchange reads that currency directly from the selected advertiser for product pricing,
campaign creation and budget or bid updates, account financials, media-buy inventory, and delivery. If
TikTok returns another advertiser, omits a requested account, reports an
unknown account status, or returns malformed balance, timezone, identity, or
currency data that conflicts with the selected account or accepted product,
Interchange stops before a campaign budget or bid mutation. It never substitutes USD
or combines money from different advertiser currencies. TikTok's approved status is
shown as active, its closed status is shown as closed, and its recognized review,
verification, punishment, audit, authorization, and contract states are shown as
suspended. Unknown or missing status and role values fail closed.

Account discovery returns the complete accessible TikTok account inventory
when pagination is omitted. Clients that request pages receive accounts in a
stable order and must follow the opaque continuation cursor until `has_more`
is false. Continuations are valid only for the same connection, filters, and
provider snapshot; expired, changed, or modified cursors fail and must be
restarted. Status filters are supported. TikTok does not identify these OAuth
advertiser grants as sandbox accounts, so `sandbox: true` returns no production
accounts.

Additional assets may be needed depending on the campaign:

* TikTok account delivery access for Spark Ads.
* Use "Only show as ads" when Scope3 should be able to run Spark Ads without
  publishing posts to the TikTok profile.
* Use "Show on TikTok profile and as ads" only when organic profile publishing
  is explicitly intended.

Scope3 does not need Business Center Admin, finance roles, or permission to add,
edit, or delete users.

### TikTok catalog sync

Interchange syncs a catalog only after TikTok confirms that the selected
advertiser owns it and returns the complete catalog and feed inventory. The sync
stops without changing the TikTok catalog if TikTok returns inventory from
another advertiser, omits a page, or returns duplicate or malformed catalog or
feed records. Interchange does not fall back to another advertiser or treat a
partial inventory as complete.

If a catalog that previously synced now fails, confirm that the connected
TikTok advertiser owns the catalog and that TikTok can return its complete feed
inventory, then retry. This buyer-side check does not change seller storefront
setup, ranking, inventory labels, or any other buyer-visible seller information.

Every TikTok campaign package must include a supported ISO country, either in
the package targeting or its offering geography. Interchange stops before
creating a campaign when a country cannot be mapped or when the request includes
regions, unresolved interest themes, or another targeting dimension that TikTok
cannot yet apply and read back exactly. It does not silently broaden delivery.
For supported targeting, Interchange explicitly disables TikTok's smart
audience and interest expansion, then reads the new paused ad group back before
adding creatives or activating delivery. If TikTok returns different country,
age, gender, audience, frequency, or expansion settings—or the readback belongs
to another advertiser—the campaign is not reported as successfully created and
cleanup is requested.

After that paused readback, Interchange records the exact requested targeting,
TikTok confirmation, concrete product, advertiser, and provider ad-group
identity in tenant-isolated durable state. Subsequent campaign reads return the
provider-neutral requested and current targeting plus an exact-match result. An
Interchange-created campaign fails closed if a provider-returned ad group loses
that provenance or its targeting changes unexpectedly. TikTok-native campaigns
remain readable without an Interchange request claim, and stale provenance is
ignored only for ad groups TikTok has authoritatively removed. Terminal campaign
deletion also removes the durable targeting record.

### Agency setup

The client shares each advertiser account from their TikTok Business Center to
the agency's Business Center as a partner, using the agency's Business Center
ID, and assigns the `Operator` role (the same role guidance as above). The
agency connects its own Business Center login in Interchange; the shared
advertiser accounts appear grouped under the agency's Business Center on the
**Advertiser mapping** tab — map each to the right advertiser.

## Google Ads

Ask the customer to grant Scope3 manager-account or account-level access to the
Google Ads account that will run the campaign.

Default grant for activation:

* Campaign management access.
* Reporting access.

Additional access may be needed depending on the workflow:

* Customer data or data-manager permissions when first-party audiences,
  enhanced conversions, or similar measurement workflows are enabled.
* Conversion action access when Scope3 is expected to configure or send
  conversion events.

Scope3 does not need Google Ads account ownership, billing administration, or
permission to add, edit, or delete users.

For a mapped advertiser account, campaign inventory includes active, paused,
and removed campaigns plus their ad groups (or Performance Max asset groups).
Scope3 rejects the inventory read if Google returns an incomplete or
cross-account hierarchy; it does not silently present a partial account mirror.

For Search, Display, Performance Max, and Demand Gen campaigns, every returned
revision is derived from the complete provider campaign and child state.
Updates reject stale revisions before writing, then read back pause/resume,
seller-package budget, supported ad-group bid, and advertiser-local schedule
changes from Google. If one part of a multi-entity update fails, Scope3 restores
the prior state or verifies that the campaign is paused before returning the
error. Cancellation pauses an active campaign first and is not reported as
complete until Google returns the removed campaign in terminal history.
Reporting-only Google campaign types return no write actions.

### Agency setup

Google's flow runs in the other direction: the agency sends a link request
from its **manager account (MCC)** using the client's ten-digit customer ID,
and the client accepts it from their account's access settings. The agency
then connects the manager account login in Interchange; client accounts under
the MCC are discovered through the manager grant and appear under it on the
**Advertiser mapping** tab — the MCC itself is context only and can never run
buys.

## Snap

Ask the customer to connect the relevant Snap advertiser account through OAuth
or the approved Snap account-sharing flow.

Default grant for activation:

* Ads management access.
* Reporting access.

Additional access may be needed for profile-backed creative workflows or
measurement. New and reconnected hosted Snap connections request both
`snapchat-marketing-api` and `snapchat-offline-conversions-api`. Existing
connections must reconnect in **Settings > Connections** before conversion
measurement is available. `snapchat-profile-api` remains excluded unless Snap
has allowlisted the Scope3 app for Public Profile API access; profile-dependent
creative workflows remain unavailable until then.

For Snap server-side website and offline conversions, select the ad account that
owns the Pixel. Interchange reads every page of the account's Pixel inventory,
rejects malformed, duplicate, or cross-account rows, and lists every Pixel Snap
authorizes. If the account has multiple Pixels, Pixel-optimized packages must
select one `event_source_id`; conflicting selections, a missing Pixel, or a
foreign ID stop before campaign creation. Setup code appears only when Snap
returns a provider-issued snippet. The base Pixel inventory proves configuration
and ownership, not signal quality.

Before conversion delivery, Interchange rechecks Pixel ownership, preserves
event IDs for deduplication, and forwards a supplied test-event code. Snap's
documented exact `VALID` receipt confirms successful event processing, so the
confirmed batch count is reported as both received and processed. Matching,
attribution, and reporting finalization remain separate and asynchronous. An
HTTP success without the exact `VALID` receipt is treated as a failed batch.
Provider response bodies and access tokens are not exposed in diagnostics.
Mobile-app conversion delivery remains unavailable until Interchange can verify
the Snap App ID and required app metadata.

Scope3 does not need organization administration, billing administration, or
permission to add, edit, or delete users.

For brief-led discovery, include one clear objective, exactly one supported
country, and at most one gender. Interchange returns no actionable product when a Snap brief is
missing those decisions, contains competing or negated objectives, requests
targeting exclusions or unresolved interests, includes prompt-injection
language, or asks for an unverified localization, age, or creative capability.
For selected accounts, clear briefs receive a reviewable strategy with
Snap's exact objective, optimization goal, targeting intent, and supported
image or video format. After the deterministic safety check, Interchange reads
the exact selected account and uses its currency for returned and stored
pricing, then verifies the requested country against Snap's complete cached
read-only targeting inventory before model interpretation, account-history
ranking, or product persistence. Briefs that need clarification make no
provider request. Both clear briefs and an empty “return the complete available
Snap catalog” request require a selected account. USD-authored advisory floors
and static budget guidance are not relabeled: non-USD products use a zero floor
and omit unsupported static guidance. Before campaign creation, Interchange
rechecks the provider currency against any trusted account snapshot, declared
media-buy currency, accepted product, and assisted-execution snapshot, and
stops before a write when they disagree. Every campaign, package, offering, and
bid amount must also convert exactly to Snap's integer microcurrency within the
safe range before creation. When an offering omits its own budget, Interchange
splits the package's integer micros in request order and gives any remainder
micros to earlier offerings, preserving the exact total across retries. Live non-spend evidence is still
required for each non-USD account used in production readiness review.

An assisted Snap create accepts exactly the concrete product, pricing option,
objective, optimization goal, country, age, gender, and pricing snapshot that
was proposed and accepted. A changed or incomplete snapshot stops before a Snap
write. The accepted package intentionally contains no inline creative,
offering, or catalog input: Interchange creates it paused, then performs
creative assignment through a separate fail-closed sync while it remains
paused. After creating each ad squad, Interchange reads its targeting back from
Snap and requires an exact normalized match before continuing. It records the
requested targeting, Snap-confirmed targeting, concrete product, connection,
advertiser account, campaign, and ad-squad identity together; if that durable
record cannot be written, Interchange deletes the paused campaign instead of
returning success; deletion is reported complete only after Snap's terminal
readback confirms it.

Campaign reads use that durable record to populate each package's `productIds`,
`requestedTargeting`, `providerTargeting`, and `targetingMatchesRequest` fields.
Only country, region, metro, postal, age, and gender values cross this API
boundary. Interest and audience identifiers remain private, but changes to
them still make `targetingMatchesRequest` false because equality is checked on
the complete normalized Snap targeting. A durable record is visible only to its
exact connection and advertiser account. An incomplete matching record fails
the read instead of inventing product or targeting provenance.

Snap creative discovery currently returns only full-screen 9:16 image and
video formats. Both require a brand name and a headline of at most 34
characters. Images must be JPEG or PNG, exactly 1080x1920, and at most 5 MB.
Direct-upload video must be MP4 or MOV, exactly 1080x1920, 3-180 seconds, and
at most 32 MB. During `sync_creatives`, Interchange validates every downloaded
file before creating Snap media or creatives. Media URLs must use HTTPS on
port 443; redirects, private or transition network addresses, mixed
public/private DNS results, oversized bodies, and mismatched file types fail
before those Snap writes.

Interchange keeps a tenant- and advertiser-scoped creative identity. Retrying
the same buyer creative with the same assets returns its existing provider
creative instead of creating another one. A changed creative becomes the new
active generation while the prior provider identity remains retained as
history, and creative listing continues to use the stable buyer creative ID
with the original name, format, and assets you submitted.

When `sync_creatives` assigns that source creative to a package, Interchange
first confirms that the campaign and Ad Squad still belong to the selected
Snap account and reads the buyer's durable paused intent. It journals the
assignment before creating the Snap Ad, so
retrying after a lost response reuses the same exact provider Ad instead of
creating another one. Ordinary `get_media_buys` reports Snap review state,
provider creative identity, requested paused intent, provider campaign/package
pause state, whether lifecycle intent is available, and whether those states
match. If the intent store is unavailable, provider state remains readable but
buyer intent and the match result are explicitly unknown; Interchange does not
infer them from Snap. Exact source/media/creative/Ad materialization is available
only to Scope3's protected staging readiness check. That check also
requires a future-dated paused campaign, a paused Ad, and zero delivery before
it records readiness.
Story, Collection, Lead Generation, Sponsored Snap, Commercial, generated, and
promoted-offering formats are not currently advertised; stale selections fail
before provider or media-source access.

This discovery change does not edit, pause, or delete existing campaigns or
provider creatives. They can continue delivering in Snap. If a connected
account contains a creative in one of the unadvertised formats, Interchange
leaves it in Snap and returns `UNSUPPORTED_CREATIVE_FORMAT` instead of showing
an incomplete creative inventory.

If Snap is still processing any creative media, creative inventory stays
fail-closed and returns `CREATIVE_MEDIA_NOT_READY`. Retry after Snap finishes
processing the media.

Buyer-paused Snap campaigns stay paused after delayed creative assignment in
both ordinary and protected paths. Only an explicit resume can change that
intent, and resume is rejected until every live Ad Squad has a creative.
Resume completes creative replacement and readback while paused, then activates
each Ad, each Ad Squad, and the Campaign in that order. The explicit resume is
recorded durably after preflight so a process restart can finish it safely. A
failed or ambiguous resume is contained back to paused state and restores paused
intent before the error returns.
Campaigns created before durable lifecycle intent was introduced require one
explicit pause or resume before another budget, schedule, or creative update;
Interchange does not infer buyer intent from provider state.
Before creating any ad squad, Interchange requires the new campaign to return
and read back under the selected advertiser account as paused and not deleted.
Each new ad squad must likewise return and read back under that campaign as
paused and not deleted, including for paused requests. A campaign identity that
belongs to another advertiser account is never paused or deleted; the request
fails with an ownership-isolation error for operator review.

Snap sometimes communicates a rejected operation inside an HTTP success
response. Interchange accepts a media-buy or control-plane single-entity read or
write only when both Snap's request and its one entity result report success and
the returned identity and parent scope match the requested object. Snap's
campaign and ad deletions use the provider's documented empty acknowledgement,
followed by a required terminal readback. Otherwise Interchange stops before the
next lifecycle step and returns a fixed error category with a Scope3-generated
correlation ID. Snap request IDs, messages, debug text, and identifiers are not
returned or logged.
Public Profile selection follows every canonical Snap Business API page and
stops if the complete inventory does not identify exactly one usable profile.

Before mutating a global campaign, ad-squad, or ad ID, Interchange reads its
parent chain back to the selected advertiser account. Creative assignments
preflight every target package through the same chain before media or creative
writes. Media upload must acknowledge the allocated media ID before polling, and
bid estimates must match the requested optimization goal with a valid numeric
range before use. Native catalog creation derives its organization from the
selected Snap account rather than request context, requires that account's
currency, and maps the catalog to a supported Snap vertical. Interchange stores
complete native catalog inventory as a durable pre-write baseline before
creating anything. Selected-account and currency checks complete before the
create is reserved, so a failure before the POST can be corrected and retried.
A first sync never adopts a matching catalog created manually
in Snap. If the create response is lost or ambiguous, retries remain read-only
and may recover only one matching catalog that was absent from that baseline;
they never send another create request. Missing or multiple new matches stop
safely for a later retry. The durable boundary requires a stable connection
credential or principal, uses the host credential key or client identity rather
than optional metadata, and never uses the rotating OAuth access token or a
non-durable direct-call fallback. Catalog
data and delete-missing changes remain staged until provider checks and conflict
arbitration succeed. The final account mapping update is atomic and revision
checked, so a stale concurrent delete-missing request changes nothing. Retrying
reuses a completed Snap create rather than posting another catalog. The complete
source catalog participates in conflict detection, so concurrent configurations cannot overwrite the winning mapping.
Stored offering and job catalog references must be non-empty, well formed, and
belong to the same connection and selected account before Snap receives a
request. Catalog data, Snap identities, discovery, and delete-missing behavior remain isolated
when connections share an account or catalog ID. A Snap identity is reused only
from that connection's completed journal and must still match the selected
organization, name, and catalog type. Feed creation revalidates the catalog's organization
against that account and sends Snap's required catalog, currency, URL, and
schedule fields. Interchange retains the Snap catalog identity before feed setup,
so retrying after a rejected or lost feed response reuses the same catalog. An
already-created feed is reused only when its complete paginated readback exactly
matches the effective requested name, currency, URL, and interval. Snap may omit
documented primary, active, UTC, interval-count-one, or minute-zero defaults from
a response; Interchange normalizes those defaults before comparison. Explicit
drift or ambiguous inventory stops without another provider write. Feed creation
has its own connection/account/catalog-scoped durable journal. If an accepted
feed is not yet visible after a lost response, every retry stays read-only until
the exact feed appears. When `catalog_ids` selects only part of a request,
unselected catalogs create no Snap object, feed, journal, or local mapping.
If a later Ads or Business API inventory page fails at the HTTP, provider, or
sub-request layer, Interchange returns an incomplete-inventory flag and
correlation ID instead of returning the successful prefix. The legacy endpoint
uses `INCOMPLETE_PAGINATION`; the standard SDK endpoint uses
`SERVICE_UNAVAILABLE`. A short enum-shaped provider code may be included;
provider text and identifiers are withheld. These guarantees apply to the
campaign, ad-squad, ad, creative, media-upload, bid-estimate, Public Profile,
Pixel, and catalog client methods covered here. Audience batch/poll and
Conversions API HTTP-success provider-envelope handling remain separately
tracked work; this is not a universal claim for every Snap endpoint.

For an unpaused request, Interchange activates and verifies each ad squad while
the campaign remains paused, then activates and verifies the campaign last. A
fresh provider read must still match the expected parent campaign or advertiser
account immediately before each activation PATCH; ownership drift or a deleted
row sends no PATCH. Provider identity and status must match at every readback, and deleted
tombstones never satisfy a live status. For any post-campaign-create failure
after advertiser ownership is validated—including a thrown creative or profile
operation—Interchange first requests paused containment and reads the campaign
back, then requests deletion. It reports rollback only after Snap confirms the
terminal deleted state. If any intervening readback belongs to another
advertiser account, Interchange stops before another provider mutation and
raises an ownership-isolation error. Drift discovered after campaign activation
triggers only a selected-account-scoped paused-containment attempt; if ownership
cannot be recovered, the fatal response says the campaign may still be active
and requires operator review. This also applies when campaign activation returns
an error or its active-state readback fails, because Snap may have applied the
activation. Rejected provider-client promises follow the same cleanup path.
Once another advertiser account is observed, a later provider error cannot
proceed to DELETE until exact selected-account ownership is seen again.
An exact already-deleted selected-account readback
confirms rollback without another DELETE. When Snap cannot confirm deletion, the
response says whether paused containment was confirmed or whether the campaign
may still be active; it never describes an unconfirmed deletion as complete.

Every Snap package or offering must currently resolve to one supported ISO
country; `UK` is normalized to `GB`. Before creating a campaign, Interchange
checks that country against Snap's complete current targeting inventory, cached
for 24 hours. A missing, empty, malformed, or unavailable inventory stops the
request. Five-digit US ZIP targeting is supported. Interchange rejects regions,
device form factors, standard audience include/exclude fields, non-US postal
systems, unknown products, incompatible campaign-objective mixes, and other
targeting it cannot represent exactly before creating the campaign. Product
targeting may use Snap's exact age buckets, one gender, discovered SLC interest
IDs, and discovered Snap audience IDs. Per-individual frequency caps support a
maximum 30-day window on compatible Snap optimization goals. Interchange also
sets Snap's interest and custom-audience expansion controls to disabled so the
provider does not silently broaden those accepted targets.

First-party Customer Lists are isolated to the Interchange connection and
selected Snap advertiser that created them. Interchange records a durable
buyer-to-Snap audience identity before writing, validates Snap's exact add and
remove receipts, and confirms deletion only after Snap no longer returns the
segment. Each request carries one identifier type and at most 100,000 hashed
identifiers; an audience reports only counts confirmed by Snap's exact receipts,
including earlier confirmed batches if a later batch fails. The same normalized
identifier cannot be added and removed in one request. Name and description
changes are read back from Snap before
Interchange reports them complete. Hashed identifiers and provider text that
could echo them are excluded from logs together with request paths, bodies, and
provider response data. Member-write errors similarly replace provider and
transport text with fixed host-owned semantics. Polling accepts buyer audience
IDs only and fails as a whole if any requested status cannot be verified.
Post-add/post-remove readback preserves Snap's pending, paused, upload, and
targetability states but does not present Snap's approximate size as an exact
match count. A lost or ambiguous provider response is reported as
reconciling and does not trigger a duplicate create. If a connection has no
durable private identity, audience access fails closed and asks you to reconnect
it. Audience types and tags that Snap cannot preserve are rejected before a
provider request.

Snap recognizes only the documented audience source types. Known sources that
are not first-party Customer Lists remain outside Customer List discovery; an
unknown or malformed source fails the complete read instead of disappearing
silently.

### Agency setup

Snap access is member-based: each client invites the agency's user into their
Snap Organization as a member with an ad-account role that can manage
campaigns and read reporting. The Snap grant is tied to the authorizing user,
so the agency connects that user's own Snap login in Interchange — the
connection discovers every ad account the login can reach across all client
Organizations, grouped by Organization on the **Advertiser mapping** tab.

## LinkedIn

Ask the customer to connect the LinkedIn ad account that will run the campaign.

Default grant for activation:

* Ads read access.
* Ads write access.
* Ads reporting access.

Additional access may be needed when creatives or sponsored content require an
organization identity. Scope3 does not need Company Page administration unless
the agreed workflow includes organic or organization-social publishing.

Scope3 does not need LinkedIn account ownership, billing administration, or
permission to add, edit, or delete users.

### Agency setup

Each client adds the agency's user to their LinkedIn ad account with a role
that can manage campaigns and read reporting (Account Manager, or Campaign
Manager when scoped to campaign work); a Sponsored Content Poster grant on the
client's Page is only needed when ads run under the Page's identity. The
agency connects its own LinkedIn login in Interchange; every client ad account
the login can reach is discovered on the **Advertiser mapping** tab — map each
to the right advertiser.

Connected-account campaign reads enumerate LinkedIn's complete cursor-paginated
campaign and creative inventory and fail closed if LinkedIn cannot prove a
complete account-scoped snapshot. Enrolled directed writes use LinkedIn's
provider version for conflict detection, preserve exact campaign/package
identity, verify every pause, budget, bid, date, and deletion transition, and
pause for containment when an interrupted write cannot be restored. Write
support is still in live verification; an account appearing here does not by
itself mean directed writes are enabled.

## Pinterest

Ask the customer to connect the Pinterest ad account that will run the campaign.

Default grant for activation:

* Ads read access.
* Ads write access.

Additional pin read/write access may be requested when the campaign workflow
uses Pinterest-native creative or pin objects.

Scope3 does not need account ownership, billing administration, or permission to
add, edit, or delete users.

### Agency setup

The client shares the ad account with the agency's business through Pinterest
business access — adding the agency as a partner by its business ID and
assigning an ad-account role that can manage campaigns and read reporting. The
agency connects its own Pinterest business login in Interchange; shared client
ad accounts are discovered on the **Advertiser mapping** tab — map each to the
right advertiser.

## Reddit

Ask the customer to connect the Reddit Ads account or profile that will run the
campaign.

Default grant for activation:

* Ads read access.
* Ads edit access.

Additional conversion permissions may be requested when the customer enables
conversion tracking or event logging.

Interchange reads the selected account's Reddit Pixel inventory before showing
setup instructions or sending server events. The Pixel ID comes from Reddit;
the ad account ID is not used as a substitute. Server events use Reddit's
Conversions API v3 and are reported as processed only when Reddit confirms the
entire submitted batch. If a Pixel is missing, belongs to another account, or
cannot be resolved to one account, the operation stops before sending events.
Website and app sources keep their native Reddit categories. In-store events
use Reddit's physical-store category; broader offline or CRM events use Reddit's
`OTHER` category because v3 does not accept an `OFFLINE` value.

Customer-list audiences accept SHA-256 email addresses and mobile advertising
IDs. Interchange binds each created list to the connected customer and ad
account, so retries and buyer/provider ID aliases reuse the same Reddit audience
and operation lock. A provider audience created by another connected customer
cannot be changed or deleted through its raw Reddit ID, even when both
connections can access the same ad account. Lists not created by the current
Interchange connection remain visible but read-only. Adds and removes are set operations.
`uploaded_count` reports add rows accepted by Reddit, not matched users;
audience size and match readiness come from later provider status. A failed
delete or remove is returned as failed rather than successful.

Reddit does not return partner ad accounts when an integration enumerates a
Business. Account-selected Pixel discovery still works for those accounts, but
server-event logging without an account reference fails closed until the Pixel
can be bound to one accessible account.

Scope3 does not need Reddit account ownership, profile administration beyond
the advertising workflow, or permission to add, edit, or delete users.

### Agency setup

Each client invites the agency's user into their Reddit Ads Business as a
member with access to the relevant ad account and a role that can manage ads
and read reporting. The agency connects its own Reddit login in Interchange;
the client ad accounts the login can reach are discovered grouped under their
Business on the **Advertiser mapping** tab — map each to the right advertiser.

## Spotify

Ask the customer to authorize Spotify with a user who can reach the Business
and advertiser ad account that will run the campaign.

Default grant for activation:

* Campaign and ad-set management access.
* Reporting access for the selected advertiser account.

The Spotify adapter can pause or resume a campaign and update package budgets,
bids, end dates, and delivery state. The directed-campaign API keeps ordinary
Spotify mutations disabled while the integration is staged. Its protected
canary path creates a future-dated paused campaign and permits only an exact,
revision-bound USD $251-to-$250 package-budget decrease. A newly created
campaign is explicitly paused and read back from the selected Spotify account
before any ad set is created. These changes use the selected account's currency
and are confirmed by a complete provider readback.
Spotify does not expose an irreversible campaign
cancellation operation: use pause to stop delivery, and expect a cancellation
request to return unsupported rather than permanently deleting the campaign.

Configure Spotify Pixel and Conversions API sources in Spotify Ads Manager.
Interchange discovers only sources delegated to the selected advertiser account
and does not create a new source against an unverified dataset. Spotify Pixel is
a browser installation managed in Spotify Ads Manager; Conversions API is the
server-side source. Customer-list discovery and reconciled deletion are available.
Customer-list upload and replacement are currently unavailable because Spotify's
published Ads API does not provide the CSV and retry-recovery contract needed to
make those writes safe. Conversion-event ingestion is not currently advertised:
the shared request cannot select an advertiser account for Spotify's multi-account
OAuth connection, and Spotify does not document authoritative success semantics
that make retries safe. Calls fail before provider I/O.

Scope3 does not need Spotify Business ownership, billing administration, or
permission to add, edit, or delete users.

## Amazon Ads

Ask the customer to connect the Amazon Ads account that will run the campaign.

Default grant for activation:

* Advertising campaign-management access.
* Reporting access.

Amazon retail, seller, or vendor account administration is separate from
advertising campaign management. Scope3 does not need retail account ownership,
billing administration, or permission to add, edit, or delete users.

### Agency setup

Each client invites the agency's user to their Amazon advertising account from
the Amazon Ads console's user management, with a role that can manage
campaigns and read reporting (DSP entities manage their users separately).
Amazon access follows the Login with Amazon user, so the agency connects its
own Amazon login in Interchange; every Sponsored Ads profile and DSP
advertiser the login can reach is discovered on the **Advertiser mapping**
tab. Amazon has no manager container — accounts arrive as a flat list, typed
`sponsored_ads` or `dsp`.

## Revoking Access

Customers can revoke Scope3's access from the platform's business, partner,
manager-account, or OAuth settings. Revoking access stops future discovery,
campaign changes, creative sync, audience sync, catalog sync, reporting reads,
and measurement writes for that connected platform account.

After revocation, refresh the connection in Interchange before running new
discovery or media-buy workflows so the account status reflects the provider's
current authorization state.
