403.
Base URL
Authentication
Pass your project’s server key in thelinkrunner-key header. This is the same key the Reporting API and other /api/v1 endpoints use. Find it under Settings → Data APIs:
Postman collection
Download the Postman collection. Import it into Postman, set thelinkrunner_key collection variable to your key, and run any request.
Rate limit and freshness
- 1 request per minute per API key (
429withRetry-After: 60when exceeded). This limit is separate from/reporting/campaigns, so you can pull app and web numbers in the same minute. - 30 req/sec per source IP (shared across all
/api/v1endpoints). - Cache responses for at least 60 seconds. Polling faster returns the same data.
Endpoint
Example request
- cURL
- Google Apps Script
Response
from and to in the response are the dates the numbers cover, including the defaults when you sent none.
pagination.total is the number of rows matching your filters, and pages is total / limit rounded up. totals covers every matching row, not only the current page. Unique counts such as visitors are deduplicated across the whole range, so totals.visitors is not the sum of the rows.
Query parameters
Send each parameter once. A repeated parameter, such as
limit=5&limit=50, returns 400.
Grouping
network_campaign, ad_set and ad answer for one network at a time, so network is required with them. A channel or source from a different network, such as network=meta&source=google, returns 400.
Some rows collect traffic that has no key, such as visits without a utm_id. Their id is null and their name describes the bucket, for example (no campaign ID).
Row fields
Revenue is summed as the amounts your website sent, without currency conversion. Spend keeps the currency of each ad account. Compare
revenue, spend and roas only when your site and your ad accounts use one currency.Days are counted in India Standard Time (
Asia/Kolkata), whatever your project timezone. If your project uses another timezone, numbers for a single day can differ from your own day boundaries near midnight.Custom events
Custom event columns are opt-in. Name the events you want inevents, and each row carries their counts in custom_events:
count is the number of times the event happened. An event with no occurrences returns 0. You can name up to 50 events, each up to 120 characters. Longer lists return 422.
Ad network hierarchy
To list the ad sets of one Meta campaign, group byad_set and pass the campaign ID from a group_by=network_campaign row:
ad_set_id the same way with group_by=ad.
Errors
Troubleshooting
403 Web Campaigns not enabled for this project
403 Web Campaigns not enabled for this project
A project admin turns on Web Campaigns in Settings → Project Details. See Track your website in an app project. Website projects have it on already.
429 Too Many Requests on the second call
429 Too Many Requests on the second call
The limit is 1 request per minute per API key. Honor the
Retry-After: 60 header and cache responses for at least 60 seconds.pagination.truncated is true
pagination.truncated is true
With
group_by=campaign&channel=google, Linkrunner can list up to 1,000 Google Ads campaigns. When a project has more, truncated is true and the remaining campaigns are not in the response. Request a shorter date range.Numbers don't match the dashboard
Numbers don't match the dashboard
Compare the same date range, the same attribution model and the same grouping. Both the dashboard Web Campaigns page and this API default to one row per campaign.