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.
Overview
Data Delivery is a standing subscription that pushes log-level data (LLD) from Scope3 into a destination you own — your cloud storage, your IAM, your data pipeline. Unlike/api/v2/buyer/reporting/metrics (which returns aggregates synchronously), Data Delivery runs on a schedule, writes objects, and never makes you pull.
Two objects make it work, both scoped to an advertiser:
| Object | What it is |
|---|---|
| Data Delivery Credential | A named handle that tells Scope3 where to write and how to authenticate. Probed asynchronously; carries a status of PENDING, VALIDATED, or FAILED. |
| Data Delivery Output | A standing subscription that says “ship <data type> to <credential> every <cadence> as <format> under <pathPrefix>”. Multiple Outputs can share a credential. Campaign-scoped Outputs override the advertiser default for the same data type. |
MB_DELIVERY, IMPRESSIONS, CLICKS, VAST_EVENTS, CAPI_ATTRIBUTION, MMP_POSTBACKS. Cadences: HOURLY (minute 0), DAILY (00:00 UTC), WEEKLY (00:00 UTC on syncWeeklyDay). Formats: JSONL, PARQUET, CSV.
Limits: up to 20 credentials and 20 Outputs per advertiser. One Output per (dataDeliveryType, credentialName) pair per scope — to fan a data type out to two destinations, list one Output per destination.
End-to-end shape
The high-level flow is the same regardless of destination:Grant Scope3 access on your cloud
Add a bucket/container that Scope3 can write into and grant the Scope3 principal the required permissions. Details per destination below.
Register the credential
PUT /advertisers/:advertiserId with a dataDelivery.credentials[] entry. The credential lands as status: PENDING.Wait for the Probe
Scope3 asynchronously writes a sentinel object under
_scope3-probe/ and deletes it. The credential flips to VALIDATED on success or FAILED (with statusError) on failure.Attach Outputs
PUT /advertisers/:advertiserId with dataDelivery.outputs[] referencing the credential by credentialName. Optionally override per campaign via PUT /campaigns/:campaignId dataDelivery.outputs[].dataDelivery.credentials and dataDelivery.outputs are full-replace arrays. The request body is the new desired state — anything not listed is archived (credentials) or cleared (Outputs). Read the current state with GET /advertisers/:advertiserId before writing. A credential cannot be archived while any live Output (advertiser- or campaign-scoped) still references it — remove or repoint the Output first.Destination setup
- Google Cloud Storage
- Amazon S3
- Azure Blob Storage
1. Grant access on your bucket
Scope3 authenticates to GCS with a single service account. Grant itroles/storage.objectCreator on the bucket you want data shipped into. No keys or secrets are exchanged.Scope3 service account:gcloud:2. Register the credential
name must be unique among live credentials on this advertiser. Outputs will reference it by this name.Probe lifecycle
When a credential is created or its config changes, Scope3 kicks off an async Probe workflow keyed on the credential. The Probe writes a sentinel object to the destination, deletes it, and updates the credential row:status | Meaning |
|---|---|
PENDING | Just created or rotated; Probe hasn’t completed yet. Typically clears within seconds. |
VALIDATED | Probe wrote and deleted a sentinel object. validatedAt reflects the run. |
FAILED | Probe could not write. statusError carries a human-readable reason. |
Outputs can reference a credential in any status. The shipping workflow re-checks at run time, so a credential that flips to
FAILED will block its Outputs until you fix it; one that flips back to VALIDATED resumes automatically.Attaching Outputs
Outputs live alongside credentials in the samedataDelivery block. The example below ships hourly impressions and daily clicks to the same GCS credential, with each data type writing under a distinct path prefix.
Rules to know
credentialNamemust point at a live credential on the same advertiser. ThedeliveryConfig.typemust match the credential’sdestinationType(you can’t ship to S3 through a GCS credential).- One Output per
(dataDeliveryType, credentialName). To send the same data type to two destinations, list two Outputs with different credentials. syncWeeklyDayis required whencadence: "WEEKLY"(0 = Sunday, 6 = Saturday). Ignored for HOURLY/DAILY.pathPrefixis used verbatim — leading slashes are not stripped and the prefix is not templated. End it with/if you want a directory-like layout.enabled: falsepauses the schedule without removing the Output. In-flight runs complete; no new runs fire until you flip it back.
Campaign-scoped overrides
For a single campaign that needs a different cadence, format, or destination than its advertiser default, setdataDelivery.outputs on the campaign:
dataDeliveryType on this campaign only. Resolved Outputs in GET responses are tagged with source: "advertiser" or source: "campaign" so it’s clear which level produced each entry.
Rotation
GCS and S3
No rotating secret to manage — Scope3’s identity is fixed, so as long as the IAM grant stays in place the credential keeps working. Rotating means changing the bucket: submit a new credential with the newbucket and the existing credentials inline-array will update in place.
Azure Blob
SAS tokens carry an expiry. The expiry from these= claim is parsed and exposed on the credential response as expiresAt — watch it and rotate ahead of time.
To rotate, submit a fresh credential with the same name:
credentialId, so any Output that references this credential by name keeps shipping without interruption. A fresh Probe runs against the new SAS; an in-flight Probe for the old SAS is cancelled.
Troubleshooting
Credential stuck on PENDING
The Probe workflow typically completes within seconds. If it’s been more than a minute:
- Re-fetch the advertiser — the row may have already flipped.
- Call the revalidate endpoint to force a fresh Probe.
- If it stays
PENDING, contact Scope3 support — the Probe worker may be backed up.
status: FAILED — common statusError patterns
| Destination | statusError includes… | Fix |
|---|---|---|
| GCS | permission, 403, does not have storage.objects.create | Grant roles/storage.objectCreator to report-delivery@swift-catfish-337215.iam.gserviceaccount.com on the bucket. |
| GCS | bucket ... does not exist | Check the bucket name in config.bucket matches an existing bucket in the project that hosts the SA. |
| S3 | AccessDenied, 403 | Confirm the bucket policy grants s3:PutObject to arn:aws:iam::948454267882:user/scope3-data-sync-service on Resource: arn:aws:s3:::<bucket>/*. |
| S3 | PermanentRedirect, region mismatch | config.region must match the bucket’s actual region. |
| S3 | NoSuchBucket | Bucket name typo, or the bucket isn’t in a commercial AWS partition. |
| Azure | Azure SAS token expired at ... | The se= claim is in the past. Mint a new SAS and update the credential. |
| Azure | AuthenticationFailed | SAS signature is wrong (truncated paste, wrong sv= version, signed against a different key). Regenerate. |
| Azure | AuthorizationPermissionMismatch | SAS is valid but missing required permissions. Confirm sp includes c, w, d (sp=cwd). For Account SAS, also confirm ss=b. |
| Azure | AuthorizationResourceTypeMismatch | Account SAS only — srt is missing o (Object). The Probe and delivery worker perform blob-level operations, so srt must include o (e.g., srt=co). srt=s or srt=c alone will not work. Regenerate. |
| Azure | AuthorizationFailure on PUT /<container>/_scope3-probe/<uuid>.txt | Service SAS was scoped to a single blob (sr=b) instead of the container (sr=c). Regenerate with az storage container generate-sas so the SAS covers any blob name under the container. |
| Azure | ContainerNotFound | containerName doesn’t exist on the storage account, or the SAS was issued at a different scope. |
Output created but no objects landing
- Verify the referenced credential is
VALIDATED. - Check
enabledon the Output — iffalse, the schedule is paused. - For HOURLY cadence, allow a full hour boundary to pass before the first run. DAILY fires at 00:00 UTC, WEEKLY at 00:00 UTC on
syncWeeklyDay. - Confirm there is delivery data for the period — a campaign with zero impressions on a given day produces no objects, not an empty file.
Conflicting Outputs
IfPUT returns a validation error about duplicate (dataDeliveryType, credentialName) pairs, it’s because the inline array contains two Outputs with the same data type pointing at the same credential. Use distinct credentials, or merge into a single entry.
Related
- Reporting Overview — pull-style aggregate metrics (the synchronous counterpart to Data Delivery).
- Log Events — push events into Scope3 (the inbound counterpart to outbound Data Delivery).