RTB SSP Report API
Aggregated auction figures for the RTB exchange, pulled over HTTP or HTTPS. Reporting runs on its own host so a slow report never competes with bidding.
GET /reports/ssp?sspId={sspId}&auth={authKey} HTTP/1.1
Host: reports.rtb.adon3.com
Accept: application/json
Figures for the XML feed live on a separate host, reports.xml.adon3.com. The parameters are the same, so one client can serve both with the host swapped.
Authentication
Both credentials go in the query string. There is no header to set and no token exchange to perform.
| Field | Type | Req. | Notes |
|---|---|---|---|
sspId | string | yes | Your SSP id. Tells us whose figures to return. |
auth | string | yes | Your reporting auth key, issued with the SSP id. |
Both are issued by the adon3 integration office. The auth key is read only, so a leaked key cannot spend money or change anything, but it does expose your figures. Ask for a rotation if it escapes.
A missing or unknown auth returns 401. An auth that is valid but does not
belong to the sspId you asked for returns 403.
Query parameters
| Field | Type | Req. | Notes |
|---|---|---|---|
sspId | string | yes | Your SSP id. |
auth | string | yes | Your reporting auth key. |
date_from | date | yes | First day in the range, inclusive. YYYY-MM-DD, UTC. |
date_to | date | yes | Last day in the range, inclusive. YYYY-MM-DD, UTC. |
dims | string | no | Grouping dimension. date is the only accepted value, and the default. |
date_from and date_to are the only way to set a range. There is no relative
shortcut such as last_7_days, deliberately, because relative ranges drift
across the UTC boundary and produce figures nobody can reconcile later.
Ranges are capped at 92 days. Beyond that the call returns RANGE_TOO_LONG, so
page through longer periods a month at a time.
Dimensions
dims accepts date and nothing else, which is also what you get when you omit
it. Anything else returns UNKNOWN_DIM.
Passing dims= empty is not the same as omitting it. Empty means no grouping,
and returns totals with an empty rows array.
Requesting
curl -sS -G 'https://reports.rtb.adon3.com/reports/ssp' \
--data-urlencode 'sspId=ssp-90ab12cd' \
--data-urlencode 'auth=ak_c08e5b91f27d' \
--data-urlencode 'date_from=2026-07-01' \
--data-urlencode 'date_to=2026-07-07' \
--data-urlencode 'dims=date'
Response
{
"sspId": "ssp-90ab12cd",
"range": { "date_from": "2026-07-01", "date_to": "2026-07-07" },
"dims": ["date"],
"cur": "USD",
"totals": {
"requests": 18420600,
"responses": 4210880,
"impressions": 884190,
"clicks": 6108,
"revenue": "7412.44100"
},
"rows": [
{
"date": "2026-07-01",
"requests": 2422400,
"responses": 594300,
"impressions": 124270,
"clicks": 820,
"revenue": "901.42200"
},
{
"date": "2026-07-02",
"requests": 2610900,
"responses": 631040,
"impressions": 131880,
"clicks": 874,
"revenue": "968.31500"
}
]
}
totals covers the whole range regardless of grouping, so it does not change
when you change dims. That makes it the right figure to reconcile against, and
a quick check that your own aggregation is summing what you think it is.
Field reference
| Field | Type | Notes |
|---|---|---|
sspId | string | Echoes the SSP id the figures belong to. |
range | object | Echoes date_from and date_to. |
dims | array | Echoes the dimension applied. |
cur | string | Currency of revenue. USD at launch. |
totals | object | Range totals. Present whatever dims you asked for. |
rows | array | One entry per day. Empty when dims is empty. |
date | string | Calendar day, UTC. |
requests | int | Bid requests we received from you. |
responses | int | Requests answered 200 with a bid. |
impressions | int | Billing notices received and counted. |
clicks | int | Clicks recorded on the creative. |
revenue | string | Net revenue in cur, to five decimal places. |
Counts are integers and revenue is a decimal string. Parse it as a decimal
rather than a float, because five places of revenue summed over a month will not
survive binary floating point intact.
Responses and impressions
responses is always higher than impressions, and the gap is not a
discrepancy. A response is counted when we return a bid. An impression is counted
when your burl fires, which happens after the creative renders. Auctions you
did not render, pages abandoned before render and blocked creatives all live in
that gap.
Billing follows impressions. If your own counts follow responses, you will
report more inventory than you are paid for every day, by a stable margin, and it
will look like a discrepancy when it is a definition.
The most common cause of a large gap is burl never being fired at all. Check
that first.
Freshness and settlement
Figures appear within a few minutes and stay provisional for 48 hours while impression reconciliation completes. After that they are final and match your invoice.
Raise discrepancy claims within 30 days, as set out in the charter.
Errors
| Code | Status | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | auth is missing, unknown or revoked. |
FORBIDDEN | 403 | auth does not belong to that sspId. |
MISSING_PARAM | 400 | sspId, auth, date_from or date_to is absent. |
INVALID_DATE | 400 | A date is not YYYY-MM-DD, or date_from is after date_to. |
RANGE_TOO_LONG | 400 | The range exceeds 92 days. |
UNKNOWN_DIM | 400 | dims contains something other than date. |
RATE_LIMITED | 429 | Above 60 report calls per hour. |
Reporting is rate limited at 60 calls an hour per SSP id. Pull once and cache, since polling the same range every minute achieves nothing that a five-minute schedule does not.
Next: Testing.