Before you start
Choose all of the following before the first request:- A scope filter such as
sponsor_id,sponsor_name,categories, orpublication_url, depending on the endpoint. - One or more explicit platforms:
youtube,instagram,podcast,substack, ortiktok. - A fixed
sincedate for the publication history you want to monitor. - A durable place to save the final
activity_window.throughtime.
since and until filter when content was published. activity_after filters
when Upriver first detected a placement. They answer different questions and
can be used together.since date. If you omit
it, the default publication window moves forward over time, and content can
age out before a newly detected placement is delivered. Usually omit until
so each new completed poll can include newly published content. Set until
only when you intentionally want a permanent upper bound.
Fetch a complete activity window
1
Start with activity_after
Send an ISO 8601 time with a timezone offset. This example finds new YouTube
placements for a known sponsor name:Every activity response includes its effective interval:If your requested time predates activity tracking, the response’s
after
shows the effective start time used by the API.2
Follow every page cursor
When Continue until
has_more is true, send next_cursor with the same filters. Omit
activity_after; the cursor already identifies the window.has_more is false. Do not change filters, platforms,
publication dates, or sort order between pages.3
Save the final through time
The final page has no After you successfully process the whole final page, save
next_cursor:activity_window.through.4
Use the through time for the next poll
Send the saved time as The next window starts after the previous window’s
activity_after:through time.Switch from a sponsor name to sponsor_id
Usesponsor_name as a convenience when you initially know only a brand’s
external name. When a result includes sponsor_id, store it as the canonical
identifier for later sponsor-specific searches, saved filters, and
deduplication.
Finish all pages of the name-based window first. Then start a new ID-based
window from the prior response’s activity_window.through:
Use sponsor summary activity
GET /v1/sponsors follows the same cursor and timestamp workflow. During an
activity search:
new_placements_in_windowcounts newly detected placements for that sponsor name.last_detected_atreports the latest detection in the window.sort_by=total_adsranks bynew_placements_in_window.sort_by=recentranks bylast_detected_at.
sponsor_id. Use sponsor_id to recognize that they represent the same brand.
Delivery and billing behavior
Activity means first detection only. A later correction, deletion, or change that makes an older placement match your filters does not create new activity. The API does not provide a correction feed or maintain a permanent list of which sponsors your account has seen. Existing result-based prices apply to rows returned by each request. Retries and overlapping workers can return and charge for the same rows again. Process one page at a time for a given cursor. Persistactivity_window.through only
after the final page has been processed.
Troubleshooting
The API says the cursor does not match
The API says the cursor does not match
Use the same endpoint, filters, platforms, publication dates, and sort order
that produced it. Also omit
activity_after while following a page cursor.The API returns 409
The API returns 409
Your requested start is later than the activity currently available, or a
pinned page is temporarily unavailable. Keep your saved time or cursor and
retry later.
The API returns 503 for a platform
The API returns 503 for a platform
Activity is not currently available through every required ingestion path
for that platform. Keep your prior activity time and retry later. Contact
support if the response persists.
An activity window returns no results
An activity window returns no results
An empty window is valid. Save
activity_window.through and use it as the
next activity_after so you do not search the same interval again.