Reporting API
Build flat, paginated reports with selectable metrics, UTC time grains, filters, and up to three breakdown columns. There are two Reporting APIs with the same request shape and response contract:
| Channel Reporting V2 | Publisher Reporting V2 | |
|---|---|---|
| Who it's for | DiscoBeat channel operators reporting across all their publishers | A single publisher reporting on its own performance |
| Base URL | https://api.disconetwork.com | https://merchant.disconetwork.com/api |
| Endpoint | GET /discobeat/reporting/v2/report/ | GET /analysis/publisher-reporting/v2/report/ |
| Authentication | X-API-Key header with a Channel management secret key | X-API-Key header with a Publisher Reporting secret key |
| Scope | The channel assigned to the key (no channel ID parameter is accepted) | The publisher assigned to the key |
Secret keys use the disco_sk_live_… prefix. Send requests from server-side code only, and ask your Disco contact for a key and the metrics enabled for you. Both APIs accept GET only.
Quickstart
curl -G -H "X-API-Key: disco_sk_live_..." \
--data-urlencode "from=2026-07-18" \
--data-urlencode "to=2026-07-20" \
--data-urlencode "time_grain=day" \
--data-urlencode "group_by=publisher,page_type" \
--data-urlencode "metrics=impressions,clicks,conversions,channel_payout,ctr,cvr" \
--data-urlencode "sort_order=asc" \
"https://api.disconetwork.com/discobeat/reporting/v2/report/"
Import a Postman collection or OpenAPI spec and set the api_key variable to your key:
Channel: Postman collection · OpenAPI spec ·
Publisher: Postman collection · OpenAPI spec
Shared contract
Everything in this section applies to both APIs.
Dates and periods
| Rule | Contract |
|---|---|
| Date pair | from and to are optional together; supplying only one returns 400 |
| No dates | Non-hourly requests use the latest 7 UTC dates in the reporting window |
| No hourly dates | Hourly requests use up to 3 UTC dates in the hourly reporting window |
| Query boundaries | from and to are inclusive UTC calendar dates; to cannot be in the future |
| Response boundaries | period_start is inclusive; period_end is exclusive |
| Weeks | UTC weeks begin Monday; edge periods are clipped to the query |
| Months | UTC calendar months; edge periods are clipped to the query |
Time grains (time_grain, default total): total (one period for all matching activity), day, week (Monday-based), month, hour (maximum 3 inclusive dates).
Response shape
| Field | Value |
|---|---|
data | Paginated flat rows with period, grouping, and selected metric fields |
summary | Selected metrics totalled across all matching rows, not just the page |
pagination | offset, limit, total, has_more |
meta | timezone, data_through (latest available data period, shown by its UTC start time), request_id |
data_through is the start of the latest available data period, not a refresh time. It's null when unavailable.
Rows are sorted by period_start in descending order by default, and sorting always precedes pagination (sort_order: desc latest-first, asc oldest-first; grouping values stay ascending). To page through results, add data.length to offset while pagination.has_more is true. A request with no matching activity returns 200 with empty data and zero-valued summary metrics.
Value rules and limits
| Rule | Contract |
|---|---|
| Zero denominator | Calculated metric is 0 |
| Ratio precision | 4 decimal places (decimals, not percentages) |
| Monetary precision | 2 decimal places |
| Non-hourly range | Must fit available reporting history |
| Groupings | Up to 3 unique values, on every time grain; multiple groupings return one row per observed combination |
| Filters | Up to 250 values per filter; a filtered dimension appears in data only when it's also in group_by |
| Result rows | 10,000 before pagination (REPORT_ROW_LIMIT_EXCEEDED) |
Errors
| Status or code | Condition |
|---|---|
400 validation | Malformed or unknown parameters, unpaired dates, empty lists, duplicate or unsupported metrics or groupings |
METRIC_NOT_AVAILABLE | A requested metric isn't enabled for you; the response lists unsupported_metrics and allowed_metrics. Contact Disco to enable it |
REPORTING_DATA_UNAVAILABLE | No reporting data is available for your channel or publisher |
DATE_RANGE_OUTSIDE_AVAILABLE_WINDOW | Dates are outside available history; the response may include available_window |
REPORT_ROW_LIMIT_EXCEEDED | Result exceeds 10,000 rows before pagination |
REPORTING_SOURCE_ROW_LIMIT_EXCEEDED | Historical request is too large to process; shorten the date range or use fewer breakdowns |
401 | Missing, invalid, public, revoked, or expired secret key |
405 | Any method other than GET |
{
"code": "METRIC_NOT_AVAILABLE",
"unsupported_metrics": ["channel_payout"],
"allowed_metrics": ["impressions", "clicks", "ctr"]
}
Channel Reporting V2
GET https://api.disconetwork.com/discobeat/reporting/v2/report/
| Parameter | Type | Details |
|---|---|---|
from / to | date | Inclusive UTC dates, YYYY-MM-DD, optional together (see Dates and periods) |
metrics | list | Comma-separated metric columns, in response order. Defaults to your channel's enabled metric set |
time_grain | string | total (default), day, week, month, hour |
group_by | list | Up to three of publisher, page_type, widget_type, widget_id. publisher adds publisher_id and publisher_name columns |
sort_order | string | desc (default) or asc |
sort_by | string | period_start (default), a selected metric, or a selected grouping field. Use publisher_name for the publisher grouping |
sort_direction | string | asc or desc. Defaults to sort_order |
publisher_ids | list | Filter by publisher UUIDs, max 250; filters don't add columns |
page_types | list | Filter by page types, max 250. MODAL activity is excluded |
widget_types | list | Filter by widget types, max 250 |
offset / limit | integer | Pagination; limit 1 to 250, default 50 |
Measured metrics: impressions, clicks, conversions, channel_payout, revenue_with_email, revenue_without_email, feed_loads, widget_displays, viewable_widget_displays, order_revenue_amount, attributed_ad_spend_amount, billable_ad_spend_amount.
Calculated metrics:
| Metric | Formula | Definition |
|---|---|---|
ctr | clicks / impressions | Click-through rate |
cvr | conversions / clicks | Channel conversion rate |
rpl | channel_payout / feed_loads | Payout per feed load |
attributed_cpa | attributed_ad_spend_amount / conversions | Attributed cost per acquisition |
A documented metric may not be enabled for every channel; conversions are Disco-attributed, so totals may differ from your own systems.
{
"data": [
{
"period_start": "2026-07-18T00:00:00Z",
"period_end": "2026-07-19T00:00:00Z",
"publisher_id": "9aa17f8c-7746-4218-9025-83d38c406179",
"publisher_name": "Example Publisher",
"page_type": "ORDER_TRACKING",
"impressions": 4584,
"clicks": 180,
"conversions": 46,
"channel_payout": 189.90,
"ctr": 0.0393,
"cvr": 0.2556
}
],
"summary": {
"impressions": 225072,
"clicks": 8928,
"conversions": 2234,
"channel_payout": 6546.24,
"ctr": 0.0397,
"cvr": 0.2502
},
"pagination": { "offset": 0, "limit": 50, "total": 36, "has_more": false },
"meta": {
"timezone": "UTC",
"data_through": "2026-07-20T00:00:00Z",
"request_id": "7e9fe348-7558-4e28-b8c6-b26ea44899eb"
}
}
Publisher Reporting V2
GET https://merchant.disconetwork.com/api/analysis/publisher-reporting/v2/report/
For a single publisher reporting on its own performance, authenticated with a Publisher Reporting secret key.
| Parameter | Type | Details |
|---|---|---|
from / to | date | Inclusive UTC dates, YYYY-MM-DD, optional together (see Dates and periods) |
metrics | list | Comma-separated metric columns, in response order. Defaults to all Publisher Reporting V2 metrics |
time_grain | string | total (default), day, week, month, hour |
group_by | list | Up to three of page_type, widget_type, widget_id |
sort_order | string | desc (default) or asc |
page_types | list | Filter by page types, max 250. ORDER_TRACKING and MODAL are excluded |
widget_types | list | Filter by widget types, max 250 |
offset / limit | integer | Pagination; limit 1 to 10,000, default 50 |
Measured metrics: publisher_payout, widget_loads, widget_displays, viewable_widget_displays, impressions, clicks, conversions.
Calculated metrics:
| Metric | Formula | Definition |
|---|---|---|
ctr | clicks / impressions | Click-through rate |
cvr | conversions / widget_displays | Publisher conversion rate |
curl -G -H "X-API-Key: disco_sk_live_..." \
--data-urlencode "from=2026-07-18" \
--data-urlencode "to=2026-07-20" \
--data-urlencode "time_grain=day" \
--data-urlencode "group_by=page_type,widget_type" \
--data-urlencode "metrics=publisher_payout,widget_loads,widget_displays,impressions,clicks,conversions,ctr,cvr" \
--data-urlencode "page_types=THANK_YOU,ORDER_STATUS" \
"https://merchant.disconetwork.com/api/analysis/publisher-reporting/v2/report/"
{
"data": [
{
"period_start": "2026-07-18T00:00:00Z",
"period_end": "2026-07-19T00:00:00Z",
"page_type": "THANK_YOU",
"widget_type": "SHOPIFY_NATIVE_ESSENTIAL",
"publisher_payout": 20.00,
"widget_loads": 120,
"widget_displays": 100,
"impressions": 50,
"clicks": 5,
"conversions": 2,
"ctr": 0.1000,
"cvr": 0.0200
}
],
"summary": {
"publisher_payout": 61.75,
"widget_loads": 360,
"widget_displays": 300,
"impressions": 150,
"clicks": 15,
"conversions": 6,
"ctr": 0.1000,
"cvr": 0.0200
},
"pagination": { "offset": 0, "limit": 50, "total": 6, "has_more": false },
"meta": {
"timezone": "UTC",
"data_through": "2026-07-20T00:00:00Z",
"request_id": "cd292465-9007-44c3-b12c-773e941003fb"
}
}
Using V1?
The V1 channel endpoints (/discobeat/reporting/v1/summary/ and /discobeat/reporting/v1/publishers/) keep working for existing integrations, but they're no longer documented here and new integrations should use V2. Contact your Disco representative if you're on V1 and need help migrating.