Segment Reporting
Pull performance data for your activated segments. Classify reports on delivery and engagement at the campaign level, with optional breakdowns by date, device, ad format, and domain.
Classify does not perform user-level tracking. Reach and frequency metrics are not available.
Reporting is asynchronous. You submit a report request and receive a report ID immediately. Results are typically ready within a few minutes.
The report object
{
"id": 301,
"status": "complete",
"segment_ids": [61],
"deal_ids": ["classify-ttd-61-a8f3c"],
"start_date": "2026-01-15",
"end_date": "2026-02-14",
"filters": {
"devices": ["desktop", "mobile"],
"formats": ["banner", "video"],
"geo": ["US", "CA"]
},
"dimensions": ["date", "device", "domain"],
"created_date": "2026-02-16T10:00:00Z",
"processed_date": "2026-02-16T10:04:12Z",
"summary": {
"impressions": 4823100,
"clicks": 14469,
"spend": 9646.20,
"ctr": 0.003,
"ecpm": 2.00
},
"data": [...]
}
| Field | Type | Description |
|---|---|---|
id | integer | Unique identifier for this report request |
status | string | pending → processing → complete or failed |
segment_ids | array[integer] | null | Segment IDs scoped in this report |
deal_ids | array[string] | null | Deal IDs scoped in this report |
start_date | string (ISO 8601) | Report start date (inclusive) |
end_date | string (ISO 8601) | Report end date (inclusive) |
filters | object | null | Device, format, and geo filters applied |
dimensions | array[string] | null | Breakdown dimensions requested |
created_date | string (ISO 8601) | When the report was requested |
processed_date | string (ISO 8601) | null | When results were ready. null until complete. |
summary | object | null | Aggregate totals across the full date range. Present only when status is complete. |
data | array[object] | null | Row-level data broken down by requested dimensions. Present only when status is complete. |
Create a report
POST https://api.clsfy.me/v1/clsfy/reports
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date | string (ISO 8601) | Required | Start of the reporting period (e.g. "2026-01-15"). |
end_date | string (ISO 8601) | Required | End of the reporting period (inclusive). |
segment_ids | array[integer] | Optional | Scope the report to specific segment IDs. |
deal_ids | array[string] | Optional | Scope the report to specific Deal IDs. |
filters | object | Optional | Narrow results further. Supported keys: devices, formats, geo. |
dimensions | array[string] | Optional | Breakdown dimensions to include in data. Values: date, device, format, domain. Omit to return summary totals only. |
Filter values:
devices:desktop,mobile,tablet,ctvformats:banner,video,native,ctv,audiogeo: ISO 3166-1 alpha-2 country codes (e.g."US","CA","GB")
Request
- curl
- Python
curl -X POST "https://api.clsfy.me/v1/clsfy/reports" \
-H "X-API-Key: <your_api_key>" \
-H "Content-Type: application/json" \
-d '{
"segment_ids": [61],
"start_date": "2026-01-15",
"end_date": "2026-02-14",
"filters": {
"devices": ["desktop", "mobile"],
"formats": ["banner", "video"],
"geo": ["US", "CA"]
},
"dimensions": ["date", "device", "domain"]
}'
import requests
response = requests.post(
"https://api.clsfy.me/v1/clsfy/reports",
headers={
"X-API-Key": "<your_api_key>",
"Content-Type": "application/json",
},
json={
"segment_ids": [61],
"start_date": "2026-01-15",
"end_date": "2026-02-14",
"filters": {
"devices": ["desktop", "mobile"],
"formats": ["banner", "video"],
"geo": ["US", "CA"],
},
"dimensions": ["date", "device", "domain"],
},
)
report = response.json()
print(report["id"]) # e.g. 301
Response
Returns the newly created report object with status: "pending".
{
"id": 301,
"status": "pending",
"segment_ids": [61],
"deal_ids": null,
"start_date": "2026-01-15",
"end_date": "2026-02-14",
"filters": {
"devices": ["desktop", "mobile"],
"formats": ["banner", "video"],
"geo": ["US", "CA"]
},
"dimensions": ["date", "device", "domain"],
"created_date": "2026-02-16T10:00:00Z",
"processed_date": null,
"summary": null,
"data": null
}
Get a report
Retrieves a report by ID. Use this to poll for results.
GET https://api.clsfy.me/v1/clsfy/reports/{id}
| Parameter | Type | Description |
|---|---|---|
id | integer | The report ID returned at creation |
- curl
- Python
curl "https://api.clsfy.me/v1/clsfy/reports/301" \
-H "X-API-Key: <your_api_key>"
import requests
response = requests.get(
"https://api.clsfy.me/v1/clsfy/reports/301",
headers={"X-API-Key": "<your_api_key>"},
)
report = response.json()
if report["status"] == "complete":
print("Summary:", report["summary"])
print("Rows:", len(report["data"]))
Polling for results
Poll GET /v1/clsfy/reports/{id} until status is "complete". Reports are typically ready within a few minutes.
- Python
import requests
import time
def wait_for_report(report_id: int, api_key: str, poll_interval: int = 30):
"""Poll until a report is ready. Returns the completed report object."""
url = f"https://api.clsfy.me/v1/clsfy/reports/{report_id}"
headers = {"X-API-Key": api_key}
while True:
report = requests.get(url, headers=headers).json()
if report["status"] == "complete":
return report
elif report["status"] == "failed":
raise RuntimeError(f"Report {report_id} failed.")
print(f"Status: {report['status']} — retrying in {poll_interval}s")
time.sleep(poll_interval)
Reading the results
When complete, the response includes a summary object with aggregate totals and a data array with one row per unique combination of the requested dimensions.
Summary
"summary": {
"impressions": 4823100,
"clicks": 14469,
"spend": 9646.20,
"ctr": 0.003,
"ecpm": 2.00
}
Data rows
Each row contains the requested dimension values alongside all five metrics:
"data": [
{
"date": "2026-01-15",
"device": "desktop",
"domain": "nytimes.com",
"impressions": 12400,
"clicks": 37,
"spend": 24.80,
"ctr": 0.003,
"ecpm": 2.00
},
{
"date": "2026-01-15",
"device": "mobile",
"domain": "theguardian.com",
"impressions": 8750,
"clicks": 18,
"spend": 17.50,
"ctr": 0.0021,
"ecpm": 2.00
}
]
Metrics reference
| Metric | Field | Type | Description |
|---|---|---|---|
| Impressions | impressions | integer | Total ad impressions served |
| Clicks | clicks | integer | Total clicks recorded |
| Spend | spend | number | Total spend in USD |
| Click-through rate | ctr | number | Clicks ÷ impressions (e.g. 0.003 = 0.3%) |
| Effective CPM | ecpm | number | Spend per 1,000 impressions in USD |
Dimensions reference
| Dimension | Value | Granularity |
|---|---|---|
| Date | date | Daily |
| Device category | device | desktop, mobile, tablet, ctv |
| Ad format | format | banner, video, native, ctv, audio |
| Domain | domain | Individual publisher domain |
Error responses
When a request fails, the API returns a JSON object with an error code and a human-readable message:
{
"error": "not_found",
"message": "Report with ID 999 not found"
}
HTTP status codes
| Status | Meaning |
|---|---|
200 OK | Success |
201 Created | Resource created (POST endpoints) |
400 Bad Request | Invalid or missing parameters |
401 Unauthorized | Missing or invalid API key |
404 Not Found | Resource not found |
422 Unprocessable Content | Validation error (e.g. invalid field values) |
429 Too Many Requests | Rate limit exceeded |