Skip to main content

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.

note

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": [...]
}
FieldTypeDescription
idintegerUnique identifier for this report request
statusstringpendingprocessingcomplete or failed
segment_idsarray[integer] | nullSegment IDs scoped in this report
deal_idsarray[string] | nullDeal IDs scoped in this report
start_datestring (ISO 8601)Report start date (inclusive)
end_datestring (ISO 8601)Report end date (inclusive)
filtersobject | nullDevice, format, and geo filters applied
dimensionsarray[string] | nullBreakdown dimensions requested
created_datestring (ISO 8601)When the report was requested
processed_datestring (ISO 8601) | nullWhen results were ready. null until complete.
summaryobject | nullAggregate totals across the full date range. Present only when status is complete.
dataarray[object] | nullRow-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

ParameterTypeRequiredDescription
start_datestring (ISO 8601)RequiredStart of the reporting period (e.g. "2026-01-15").
end_datestring (ISO 8601)RequiredEnd of the reporting period (inclusive).
segment_idsarray[integer]OptionalScope the report to specific segment IDs.
deal_idsarray[string]OptionalScope the report to specific Deal IDs.
filtersobjectOptionalNarrow results further. Supported keys: devices, formats, geo.
dimensionsarray[string]OptionalBreakdown dimensions to include in data. Values: date, device, format, domain. Omit to return summary totals only.

Filter values:

  • devices: desktop, mobile, tablet, ctv
  • formats: banner, video, native, ctv, audio
  • geo: ISO 3166-1 alpha-2 country codes (e.g. "US", "CA", "GB")

Request

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"]
}'

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}
ParameterTypeDescription
idintegerThe report ID returned at creation
curl "https://api.clsfy.me/v1/clsfy/reports/301" \
-H "X-API-Key: <your_api_key>"

Polling for results

Poll GET /v1/clsfy/reports/{id} until status is "complete". Reports are typically ready within a few minutes.

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

MetricFieldTypeDescription
ImpressionsimpressionsintegerTotal ad impressions served
ClicksclicksintegerTotal clicks recorded
SpendspendnumberTotal spend in USD
Click-through ratectrnumberClicks ÷ impressions (e.g. 0.003 = 0.3%)
Effective CPMecpmnumberSpend per 1,000 impressions in USD

Dimensions reference

DimensionValueGranularity
DatedateDaily
Device categorydevicedesktop, mobile, tablet, ctv
Ad formatformatbanner, video, native, ctv, audio
DomaindomainIndividual 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

StatusMeaning
200 OKSuccess
201 CreatedResource created (POST endpoints)
400 Bad RequestInvalid or missing parameters
401 UnauthorizedMissing or invalid API key
404 Not FoundResource not found
422 Unprocessable ContentValidation error (e.g. invalid field values)
429 Too Many RequestsRate limit exceeded