MPO Real-Time Asynchronous API
Important Data Usage Warning
This data is generated in real time and is intended only for real-time reporting purposes. It is not subject to standard data cleaning practices (deduplication, quality checks) and must not be used for pricing, bidding, invoicing, or any financial decision-making.
BETA Access
The API is currently in beta and is only available to a limited list of clients onboarded by the Criteo technical team.
Overview
This API provides real-time reporting for Marketplace Performance Outcomes (MPO) via an asynchronous export workflow designed for large volumes of data.
- Data latency: Approximately 10 minutes.
- Base URL: https://api.criteo.com/{version}/marketing-solutions/marketplace-performance-outcomes/stats
- Compatibility: This endpoint supports both multi-seller and single-seller campaign configurations.
The workflow is:
- Create an asynchronous report job with your filters.
- Poll the job status until it is complete.
- Download the generated export file (CSV or JSON).
1. Create a report job
Endpoint: POST /realtime-reports/export
Submit a request with your desired filters. The API creates an export job and returns an identifier (UUID) and a status (typically Pending).
2. Poll for Completion
Endpoint: GET /report-jobs/{'{<reportId>}'}
Poll the job status until it reaches Done. Do not poll more than once every 5–10 seconds to remain within rate limits.
- Status options:
Pending,Done,Failure,Expired. - Note: Identical requests may reuse cached results, returning a previously generated ID.
3. Download the report
Endpoint: GET /realtime-reports/{'{<reportId>}'}
Once the status is Done, this call returns the raw file bytes.
- CSV output:
Content-Type: text/csv. - JSON output:
Content-Type: application/json.
Data models
Request attributes (RealTimeProductReportJob)
RealTimeProductReportJob)| Field | Type | Required | Description |
|---|---|---|---|
fileFormat | string | No | Output format: csv (default) or json. |
advertiserIds | array[string] | Yes | IDs of advertiser accounts. |
campaignIds | array[string] | No | Optional campaign filter. |
sellerIds | array[string] | No | Optional seller filter. |
dimensions | array[string] | No | Aggregation levels (for example, advertiserId, campaignId). |
metrics | array[string] | No | Metrics to retrieve. Default: ["clicks", "displays", "cost"]. |
lookbackWindow | integer | No | Duration in minutes counted backwards from now (60–1440). Mutually exclusive with startDate. |
startDate | string | No | ISO-8601 UTC start time. |
endDate | string | No | ISO-8601 UTC end time. If omitted, defaults to the current time when startDate is provided. |
timezone | string | No | IANA time zone identifier (default: UTC). Used to format time values in the output. |
Dimensions
| Dimension | Description | Constraints |
|---|---|---|
advertiserId | ID of the advertiser. | — |
partnerId | ID of the partner. | — |
campaignId | ID of the campaign (ad set-level entity in MPO). | — |
sellerId | ID of the seller used in the MPO public API. | — |
productId | Client-provided product ID. | Cannot be combined with hour or minute. |
hour | Start of hourly aggregation bucket (ISO-8601; minutes/seconds = 00) in the requested time zone. | Cannot be combined with minute or productId. |
minute | Start of minute aggregation bucket (ISO-8601; seconds = 00) in the requested time zone. | Cannot be combined with hour or productId. |
Metrics
| Metric | Description |
|---|---|
clicks | Number of clicks generated. |
displays | Number of display opportunities used. |
cost | Total cost in the advertiser account currency. |
1. Create Async report job

/realtime-reports/export
Creates a new asynchronous report job for a real-time product report. The backend triggers production of an export file and may reuse cached results when the same request has already been processed.
Request body
{
"data": {
"type": "RealTimeProductReportJob",
"attributes": {
"fileFormat": "csv",
"advertiserIds": ["321"],
"campaignIds": ["12345", "56789"],
"sellerIds": ["254614150"],
"dimensions": ["advertiserId", "campaignId", "sellerId"],
"metrics": ["clicks", "displays", "cost"],
"startDate": "2026-01-09T08:00:00Z",
"endDate": "2026-01-09T09:00:00Z",
"timezone": "UTC"
}
}
}Successful response
{
"exportId": "45f7ec55-1008-4372-9144-1da37d8dccc2",
"status": "Pending",
"message": null
}Example error – unsupported fileFormat
fileFormatIf fileFormat is not one of csv or json, the API returns a 400 Bad Request validation error.
{
"warnings": [],
"errors": [
{
"traceId": "31500d5059bb85b2168e9256f8722fa8",
"type": "validation",
"code": "json-serialization-error",
"title": "JSON error",
"detail": "data.attributes.fileFormat 'xls' not valid. Must be one of 'Csv','Json'"
}
]
}2. Poll for completion
Endpoint: GET /report-jobs/{'{reportId}'}
Poll the job status until it reaches Done. Do not poll more than once every 5–10 seconds to remain within rate limits.
- Status options:
Pending,Done,Failure,Expired. - Note: Identical requests may reuse cached results, returning a previously generated ID.
3. Download Report Output
GET /realtime-reports/{'{<reportId>}'}
GET /realtime-reports/{'{<reportId>}'}Downloads the file corresponding to a completed export job.
- If
fileFormat = csv→Content-Type: text/csv - If
fileFormat = json→Content-Type: application/json
Path parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
reportId | path | string (UUID) | Yes | Unique ID of the export job. |
Example request
GET /realtime-reports/45f7ec55-1008-4372-9144-1da37d8dccc2Successful response
- 200 OK only if job status is
Done. - Body contains raw file bytes (CSV or JSON).
Output formats
CSV output
The response contains a header row followed by data rows.
"advertiserId","campaignId","clicks","displays","cost"
321,12345,1873,800247,992.21671380425
321,56789,17927,5275096,3460.71409576333
...JSON output
The response contains a columnar JSON payload with a data array and top-level columns and rows fields.
{
"columns": [
"advertiserId",
"campaignId",
"clicks",
"displays",
"cost"
],
"data": [
[
321,
12345,
17927,
5275096,
3460.71409576333
],
[
321,
56789,
1873,
800247,
992.21671380425
]
],
"rows": 2
}Validation rules
The following validation rules are explicitly described via field notes and domain errors.
1) Required fields
advertiserIdsis required.- Missing required fields yields
invalid-query.
2) File format
fileFormatmust be one ofcsvorjson.- Otherwise the API returns
json-serialization-error(as shown in the example).
3) Time interval definition
You must use exactly one of:
- Relative interval:
lookbackWindow(minutes from now). - Absolute interval:
startDate(and optionallyendDate).
Rules:
lookbackWindowmust be within 60–1440.lookbackWindowcannot be combined withstartDateand/orendDate.startDateis mutually exclusive withlookbackWindow.- If
startDateis provided andendDateis omitted,endDatedefaults to the current time.
Violations return invalid-lookbackwindow and/or invalid-time-interval.
4) Time zone
timezonemust exist in the IANA Time Zone database.- Invalid time zones yield
invalid-query(as part of "invalid query definition").
5) Dimension combination constraints
- Only one of the following dimensions can be used in a single request:
productIdhourminute
Violations yield invalid-dimensioncombination.
6) Report lifecycle constraints
- Downloading output is only valid when
status == Done. - If the job does not exist (or is not visible), the API returns
export-not-foundand maps it to HTTP403. - If the job exists, but the output has been permanently deleted, the API returns
export-alreadyexpired.
7) Caching behavior (identical requests)
- Identical requests may reuse cached results, meaning a previous export/report ID may be returned instead of generating a new export.
Errors & status codes
HTTP status codes
| HTTP | Meaning |
|---|---|
| 400 | Bad request (invalid syntax or validation error). |
| 401 | Authentication failed (missing or expired token). |
| 403 | Insufficient permissions, no campaign found in scope, or export job not found. |
| 409 | Conflicting parameters (for example, invalid combination of filters). |
| 429 | Throttling limit reached (example value noted: 200 requests/minute — to be confirmed). |
| 500 | Internal server error. |
Domain errors / validation errors
| Code | Title / Description | Notes |
|---|---|---|
insufficient-accountpermissions | Insufficient account permissions | Caller lacks rights for specified advertisers. |
invalid-query | Invalid query definition | Missing required fields, unsupported dimensions/metrics, invalid time zone, invalid IDs. |
invalid-lookbackwindow | Invalid lookback window | Outside 60–1440 or combined with dates. |
invalid-time-interval | Invalid time interval definition | Dates combined with lookbackWindow; may be returned alongside invalid-lookbackwindow. |
invalid-dimensioncombination | Invalid combination of dimensions | Only one of productId, hour, minute per request. |
unsupported-fileformat | Unsupported file format | Only CSV and JSON are supported. |
export-not-found | Export job not found | Requested reportId does not exist or is not visible. |
export-alreadyexpired | Export already expired | Output has been permanently deleted. |
Updated about 12 hours ago