Every request requires
X-Application-Id and X-Api-Key. Keep a separate local
collection and cursor for each agency, endpoint, campaign, and supported filter
set. Existing list endpoints keep their behavior. Each new feed has an explicit
record format documented on its page; it is not a drop-in replacement for list
responses containing previews, aggregates, or display conversions.
Apply a page and save its cursor together
- Start without
cursor, using an empty local collection for this sync scope. - Replace or insert each
datarecord using its identity from the table above. - Delete each
removedIdsentry. Unknown IDs are harmless. - Commit
nextCursorin the same local transaction as those changes. - When
hasMoreistrue, immediately request another page with that cursor. - When
hasMoreisfalse, keep the cursor for your next poll.
Cursors do not expire by age. Pausing an integration, restarting it, changing the
page size, or rotating its API key does not require a full reload. A cursor stays
bound to its feed and agency/campaign scope, and every request still checks access.
Shared request and response
The six new feeds accept onlycursor and limit. Campaign media additionally
supports its documented initial filters. Unknown parameters are rejected so a
misspelled filter cannot silently broaden a sync.
Pages target 1 MiB of record data. A single larger record is returned intact;
page length can be smaller than
limit.
data contains complete replacements, not partial patches. removedIds
means the record no longer belongs in this local view: for example, it was
deleted, moved to another scope, or became unavailable. Restored records return
as upserts. Campaign media also removes records that leave its saved filters.
Concurrent changes and retries
Each page reads a consistent current state. A multi-page run is not a frozen export: edits during paging appear in a later page or the next poll. Transactions that started before the checkpoint and committed later are included too. Delivery is at least once. Repeated records and removals are safe when applied idempotently. Multiple edits can become one replacement containing the latest state; these feeds are not audit logs of intermediate edits. On an API error or failed local transaction, retry the last committed cursor. Keep your local data. Do not automatically restart the sync on an error.400: fix malformed parameters or a damaged/wrong-scope cursor. There is no routine cursor-expiry error.401/403: restore valid credentials or the required scope, then resume.404: the requested campaign is unavailable to your agency. Do not reuse its cursor for a different campaign.429/5xx: back off and retry the same saved cursor; honorRetry-Afterwhen supplied.
Client example
The repository demo exportssync from sdk-demo/backend/src/sdkClient.js.
Supply your own database adapter and transaction implementation:
sync.contracts, sync.eligibility, sync.payouts, sync.transactions, or
sync.trackedMedia for the other new feeds. Agency feeds omit campaignId.
The deployed campaign media feed retains its existing mediaSync client and
campaignCreatorMediaId identity; see its client example.