Reporting API
Your statistics with us, by API: requests, bids, wins, impressions and money, by day or hour, in your time zone. The same API works for publishers (SSP) and advertisers (DSP); a key sees only its own feed.
Quick start
curl
curl -X POST 'https://api.gfybid.com/api/v1/report' \
-H 'X-API-Token: your_api_token_here' \
-H 'Content-Type: application/json' \
--data '{
"date_from": "2026-11-01 00:00:00",
"date_to": "2026-11-04 23:59:59",
"group_by": ["EventDate"],
"metrics": ["Requests", "Bids", "Impression", "Amount", "Ecpm"],
"timezone": "UTC",
"order": {"field": "EventDate", "sort": "DESC"},
"page": {"number": 1, "size": 100}
}'Authentication
Every request carries your API key in a header:
Headers
X-API-Token: {your key}
Content-Type: application/json- How to get a key: ask your account manager. A key is shown once — store it safely.
- A key belongs to one feed and sees only that feed's statistics.
Authorization: Bearer {your key}is accepted as well.- Lost or leaked key: ask for a new one; the old one is revoked at once. You can have several keys (for example, one per system).
Endpoint
Endpoint
POST https://api.gfybid.com/api/v1/reportRequest body
| Field | Type | Required | Description |
|---|---|---|---|
date_from | string | yes | Start, Y-m-d H:i:s, in timezone |
date_to | string | yes | End, inclusive, Y-m-d H:i:s; at most 31 days after date_from |
metrics | array | yes | 1 to 10 of the metrics |
group_by | array | no | EventDate, EventHour; none = one total row |
timezone | string | no | IANA name, e.g. UTC (default), Europe/Berlin |
order | object | no | {"field": "<group field or requested metric>", "sort": "ASC" | "DESC"}; default: by time, ascending |
page | object | no | {"number": 1, "size": 10}; size 1–100, default 10 |
where | array | no | Filters are not supported yet: omit it or send [] |
Unknown fields are refused with 422, so a typo never silently changes your report.
Metrics
| Metric | Publisher (SSP) | Advertiser (DSP) |
|---|---|---|
Requests | Bid requests you sent us | Bid requests we sent you |
Bids | Bids we returned to you | Bids you returned that we passed on |
Wins | Win notices you sent us | Win notices for your bids |
Impression | Billing notices recorded | Billing notices recorded for your bids |
Amount | What we owe you, USD | What you owe us, USD |
Ecpm | Amount per 1000 impressions, USD | Same |
Time and freshness
- Statistics are updated every minute.
- Impressions and money are dated by the time of the bid, not of the billing notice.
- Traffic counters are hourly. In time zones with a 30- or 45-minute offset, hour boundaries follow UTC hours.
- Only periods with data are returned: a day or hour without traffic has no row.
Response
200 OK
{
"meta": {
"pagination": {"per_page": 100, "current_page": 1, "has_more": false},
"role": "ssp",
"status": true,
"code": 200,
"currency": "USD",
"timezone": "UTC"
},
"data": [
{
"metric": {
"Requests": "1250000",
"Bids": "310000",
"Impression": "41020",
"Amount": "1590.776",
"Ecpm": "0.038781"
},
"group": {
"EventDate": {"id": "2026-11-04", "name": "2026-11-04", "field_name": "EventDate"}
}
}
]
}- Values are strings. Counts are integers; money is a decimal in USD with up to 6 decimals.
meta.roleissspordsp— the side of your key.- With
EventHour, the group id looks like2026-11-04 13:00. Withoutgroup_by,groupis an empty object. - Page through the result with
page.numberwhilemeta.pagination.has_moreistrue.
The numbers above are an example, not real data.
Example: hours of one day, in Berlin time
Request body
{
"date_from": "2026-11-04 00:00:00",
"date_to": "2026-11-04 23:59:59",
"group_by": ["EventHour"],
"metrics": ["Requests", "Impression", "Amount"],
"timezone": "Europe/Berlin",
"page": {"number": 1, "size": 24}
}Limits
- At most 2 requests per second per key, with bursts up to 10.
- A period of at most 31 days per request.
- Up to 100 rows per page.
- The same report (any page) is served from a cache for 2 minutes, so paging is fast and cheap.
Errors
| Code | When |
|---|---|
| 401 | Missing, invalid or revoked key |
| 422 | Invalid request: the error field says what is wrong |
| 429 | More than 2 requests per second per key (bursts up to 10): retry after Retry-After seconds |
| 500 | Our error, or the report took too long: retry later, or ask for a shorter period |
Error body
{
"meta": {"status": false, "code": 422},
"error": "the period must not exceed 31 days"
}Common 422 messages
| Message | Fix |
|---|---|
date_from and date_to: format Y-m-d H:i:s … | Send both dates as 2026-11-04 00:00:00 |
the period must not exceed 31 days | Split the period |
metrics: 1 to 10 of … | Send at least one supported metric |
group_by: supported fields are EventDate, EventHour | Remove other group fields |
timezone: an IANA name … | Use names like UTC or Europe/Berlin |
order.field: a group_by field or a requested metric | Order by a field you group by or a metric you asked for |
page.number must be ≥ 1, page.size 1–100 | Fix the page object |
where: filters are not supported yet; send [] | Omit where |
Questions about the integration? Write to manager@gfybid.com or use the contact form.