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,
GETonly - 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.
Authorization: Bearer <api_key>
X-API-Key: <api_key> and ?api_key=<api_key> are also accepted.
3Endpoint
GET https://api.adsfive.com/reporting
| Parameter | Required | Format | Description |
|---|---|---|---|
| start_date | Yes | YYYY-MM-DD | First day of the report, inclusive (UTC) |
| end_date | Yes | YYYY-MM-DD | Last day of the report, inclusive (UTC) |
| format | No | json | csv | Defaults 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.
GET /reporting?start_date=2026-07-31&end_date=2026-08-02
Authorization: Bearer <api_key>
4Response fields
| Singular dimension | JSON key | Type | Notes |
|---|---|---|---|
| Date | date | YYYY-MM-DD | UTC |
| App | app | string | Matches the app name in the advertiser's Singular account |
| Store ID | store_id | string | iOS Store ID or Android package name |
| Campaign Name | campaign_name | string | — |
| OS | os | string | ios or android |
| Currency | currency | string | ISO code of the cost value. Present on every row. |
| Cost | cost | number | Total 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). |
| Installs | installs | integer | Installs reported by us |
{
"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
}
]
}
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_dateis later than yesterday it is clamped to yesterday, and the adjustment is reported in anoticesarray 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
0values, not omitted. A row is only absent when the campaign did not exist on that date. Add&include_empty=falseto 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
noticesarray is the only signal that a window was shortened; its absence means everything asked for was served.
6Errors
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Missing or malformed parameters (bad date format, inverted range) |
| 401 | Missing or invalid API key |
| 500 | Internal 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.