Partner integration specification

Cost Reporting API

The reporting API Singular pulls from to ingest aggregated campaign cost data on behalf of a mutual customer. Daily pull, one credential per advertiser.

Integration type
API (pull)
Endpoint
https://api.adsfive.com/reporting
Protocol
HTTPS, GET only
Response formats
JSON (default) or CSV
Timezone
UTC
Currency
USD
Granularity
Date × App × Campaign
History
90 days
Recommended pull
Once daily, trailing 7 days

1Overview

A single authenticated GET returns day-level cost and install data for one advertiser, aggregated to date × app × campaign. Every request is independent and recomputed from source, so re-pulling a window always reflects the latest state.

Rows carry only the six fields listed in §4. Columns we do not populate are omitted from the payload entirely rather than returned blank.

2Authentication

A distinct API key is issued per customer, so each advertiser's data is pulled and differentiated separately.

Request header
Authorization: Bearer <api_key>

X-API-Key: <api_key> and ?api_key=<api_key> are also accepted.

3Endpoint

GET https://api.adsfive.com/reporting

ParameterRequiredFormatDescription
start_dateYesYYYY-MM-DDFirst day of the report, inclusive (UTC)
end_dateYesYYYY-MM-DDLast day of the report, inclusive (UTC)
formatNojson | csvDefaults to json

start and end are accepted as aliases.

A single request may span any date range, so the recommended pattern is one request per pull — the trailing 7 days in one call — rather than one request per day. Day-by-day iteration is equally supported if that suits your connector.

Example request
GET /reporting?start_date=2026-07-31&end_date=2026-08-02
Authorization: Bearer <api_key>

4Response fields

Singular dimensionJSON keyTypeNotes
DatedateYYYY-MM-DDUTC
AppappstringMatches the app name in the advertiser's Singular account
Store IDstore_idstringiOS Store ID or Android package name
Campaign Namecampaign_namestring—
OSosstringios or android
CurrencycurrencystringISO code of the cost value. Present on every row.
CostcostnumberTotal spend for the row in USD, rounded to 2 decimal places — not a per-install rate. A JSON number, so trailing zeros are not preserved (184.8, never 184.80).
InstallsinstallsintegerInstalls reported by us
Response
{
  "status": "ok",
  "start_date": "2026-07-31",
  "end_date": "2026-08-02",
  "timezone": "UTC",
  "row_count": 3,
  "rows": [
    {
      "date": "2026-07-31",
      "app": "SkeeBoost",
      "store_id": "6449432839",
      "campaign_name": "Skeeboost_US_iOS_1",
      "os": "ios",
      "currency": "USD",
      "cost": 0,
      "installs": 0
    },
    {
      "date": "2026-08-01",
      "app": "SkeeBoost",
      "store_id": "6449432839",
      "campaign_name": "Skeeboost_US_iOS_1",
      "os": "ios",
      "currency": "USD",
      "cost": 0,
      "installs": 0
    },
    {
      "date": "2026-08-02",
      "app": "SkeeBoost",
      "store_id": "6449432839",
      "campaign_name": "Skeeboost_US_iOS_1",
      "os": "ios",
      "currency": "USD",
      "cost": 8,
      "installs": 5
    }
  ]
}
CSV — add &format=csv
Date,App,Store ID,Campaign Name,OS,Currency,Cost,Installs
2026-07-31,SkeeBoost,6449432839,Skeeboost_US_iOS_1,ios,USD,0,0
2026-08-01,SkeeBoost,6449432839,Skeeboost_US_iOS_1,ios,USD,0,0
2026-08-02,SkeeBoost,6449432839,Skeeboost_US_iOS_1,ios,USD,8,5

CSV carries no envelope, so any date-range clamp is reported in an X-Report-Notices response header instead of the notices field.

5Data freshness and history

  • Figures are finalised by a daily process that runs at 00:00 UTC for the day that just closed. The most recent complete day is therefore yesterday.
  • If end_date is later than yesterday it is clamped to yesterday, and the adjustment is reported in a notices array on the response. The request still succeeds.
  • 90 days of history are available, so an initial ~3-month backfill is served in full. A request reaching further back is clamped to the earliest available day, again reported in notices, rather than returning an error.
  • Figures for a given day may be restated for a short period as conversions settle. Re-pulling the trailing 7 days daily, as is standard, picks these up automatically.
  • A campaign that was live but had no spend and no installs on a given day is reported as a row with 0 values, not omitted. A row is only absent when the campaign did not exist on that date. Add &include_empty=false to suppress zero rows.
  • Row count reflects how long the campaign has existed, not the length of the window. A 90-day request covering a campaign created last week returns about 7 rows, not 90 — and that is a complete, successful response, not a truncated one. The notices array is the only signal that a window was shortened; its absence means everything asked for was served.

6Errors

StatusMeaning
200Success
400Missing or malformed parameters (bad date format, inverted range)
401Missing or invalid API key
500Internal error; safe to retry

Errors return {"status": "error", "error": "<description>"}.

An empty rows array with 200 means no campaign existed in the window — a valid, successful response, not an error. A campaign that existed but did not spend is reported as a row of zeros (see §5), not as an absent row.

Cost Reporting API v1 Specification for Singular Analytics