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. You can find the reference for the endpoints mentioned in the page in the Preview version of this documentation.
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/
- 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).
This endpoint is referenced here.
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.
This endpoint is referenced here.
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.
This endpoint is referenced here.
Data models
Request attributes (RealTimeProductReportJob)
RealTimeProductReportJob)| Field | Type | Description |
|---|---|---|
fileFormat | string | Output format: csv (default) or json. |
advertiserIds* | array[string] | IDs of advertiser accounts. |
campaignIds | array[string] | Optional campaign filter. |
sellerIds | array[string] | Optional seller filter. |
dimensions | array[string] | Aggregation levels (for example, advertiserId, campaignId). |
metrics | array[string] | Metrics to retrieve. Default: ["clicks", "displays", "cost"]. |
lookbackWindow | integer | Duration in minutes counted backwards from now (60–1440). Mutually exclusive with startDate. |
startDate | string | ISO-8601 UTC start time. |
endDate | string | ISO-8601 UTC end time. If omitted, defaults to the current time when startDate is provided. |
timezone | string | IANA time zone identifier (default: UTC). Used to format time values in the output. |
(*) - Required
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. |
Step 1. Create an Async Report Job
POST
https://api.criteo.com/{version}/marketing-solutions/marketplace-performance-outcomes/realtime-reports/export
This endpoint 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.
Sample Request
{
"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"
}
}
}Sample Response
Successful Response
{
"exportId": "45f7ec55-1008-4372-9144-1da37d8dccc2",
"status": "Pending",
"message": null
}Error Example: 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'"
}
]
}Step 2. Poll for Completion
GET
https://api.criteo.com/{version}/marketing-solutions/marketplace-performance-outcomes/report-jobs/{reportId}
This endpoint polls 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.
Step 3. Download Report Output
GET
https://api.criteo.com/{version}/marketing-solutions/marketplace-performance-outcomes/realtime-reports/{reportId}
This endpoint 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 | Description |
|---|---|---|---|
reportId* | path | string (UUID) | Unique ID of the export job. |
(*) - Required
Example Request
GET
GET https://api.criteo.com/{version}/marketing-solutions/marketplace-performance-outcomes/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 20 hours ago