Cost import & sync
Daily spend per campaign via CSV, the costs API or automatic sync from Google Ads, Meta, TikTok and Apple Search Ads — the basis of CPI and ROAS.
Updated 2026-09-02
Costs API#
curl -X POST https://app.whichclick.is/api/v1/costs \
-H "Authorization: Bearer wc_live_…" -H "Content-Type: application/json" \
-d '{"rows":[{"campaign_external_id":"2098765432","day":"2026-09-01","spend":1240.5,"currency":"USD","impressions":91000}]}'
# {"ok":true,"upserted":1}Rows are upserted on (campaign, day); up to 5000 per call. Reference campaigns by WhichClick campaign_id or by the ad platform's id in campaign_external_id. Rows for unknown campaigns are skipped (not an error) — create the campaign first or set its externalId.
CSV import#
Integrations → Cost import accepts campaign_external_id,day,spend,currency,impressions with the same semantics.
Automatic sync#
Connect a platform under Integrations; credentials are encrypted at rest (CREDENTIALS_KEY) and the scheduler (pnpm scheduler or your cron) pulls the previous day every morning, backfilling 7 days.
| Platform | Source | Granularity |
|---|---|---|
| Google Ads | GAQL campaign report (metrics.cost_micros, impressions) | Campaign / day |
| Meta | Marketing API Insights (spend, impressions) | Campaign / day |
| TikTok | Reporting API (spend, impressions) | Campaign / day |
| Apple Search Ads | Campaign reports (localSpend, impressions) | Campaign / day |
| AppLovin | Advertiser reporting (r.applovin.com/report) | Campaign / day |
| Unity Ads | Stats API v2 acquisitions report | Campaign / day |
| ironSource (LevelPlay) | Advertiser reporting API v2 | Campaign / day |
| Mintegral | Advertiser reporting API | Campaign / day |
Sync runs are listed with status and row counts; failures raise an alert.
Metrics derived from cost#
| Metric | Formula |
|---|---|
| CPC | spend / valid clicks |
| CPI | spend / attributed installs |
| CPA | spend / conversions |
| ROAS | (conversion value + purchase, subscription and ad-revenue events) / spend |
| Saved spend (Protect) | invalid clicks × average CPC |
Costs are shown in the currency you send; no FX conversion is applied. Synced rows always carry the currency reported by the partner API — a row without one aborts the run instead of assuming USD.