Endpoints
Four separate endpoints support requests to create campaign and line item reports and retrieve the report data and status.| Verb | Endpoint | Description |
|---|---|---|
| Create a Campaign report request | ||
| Create a Line Item report request | ||
| Get status of a specific report | ||
| Download output of a specific report |
Report Request Attributes
| Attribute | Data Type | Description |
|---|---|---|
| Campaign or Line Item ID(s) of the desired report Accepted values: single or list of string/int64 (max 50 ids per call) Writeable? N / Nullable? N | ||
| enum | Writeable? N / Nullable? N | |
| Dimension attributes desired for metrics breakdown for the custom report of the campaign(s) / line item(s). Writeable? N / Nullable? N | ||
| Quantitative metrics desired in the custom report of the campaign(s) / line item(s). Writeable? N / Nullable? N | ||
| date | Start date to report (inclusive) Writeable? N / Nullable? N | |
| date | End date to report (inclusive) Writeable? N / Nullable? N | |
| enum | Writeable? N / Nullable? N | |
| string | Time zone to consider in the report. Defaults to UTC if omitted. Writeable? N / Nullable? Y | |
| enum | Writeable? N / Nullable? Y | |
| enum | Writeable? N / Nullable? Y | |
| enum | Filter on specific sales channel: online or offline Writeable? N / Nullable? Y | |
| enum | Format of the report data returned Writeable? N / Nullable? N | |
| string | The match type used to associate a search term and keywords entered for the campaign. Accepted values: | |
| string | Indicates how the keyword was targeted — either manually by the user or automatically by the platform. Accepted values: | |
| string | Specifies the conquesting strategy used with the keyword. Accepted values: | |
| string | The type of creative asset used in the ad, such as Display or Video. |
Reporting Asynchronous Workflow: Step 1 of 3
- First, create a request for the campaign or line item report with the desired attributes
- This generates a
reportIdrepresenting the report
Create a Report Request
Reporting endpoints provide two separate endpoints that allow downloading reports at the campaign or line item level. Each of the following requests can be repeated for each individual report type.Campaigns Level Report
Sample Requestcurl -X POST "https://api.criteo.com/{version}/retail-media/reports/campaigns" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "8343086999167541140",
"metrics": ["impressions"],
"dimensions": ["date"],
"reportType": "summary",
"startDate": "2025-01-01",
"endDate": "2025-01-31",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
}'
import requests
import json
url = "https://api.criteo.com/{version}/retail-media/reports/campaigns"
payload = json.dumps({
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "1285",
"metrics": [
"impressions"
],
"dimensions": [
"date"
],
"reportType": "summary",
"startDate": "2025-01-01",
"endDate": "2025-01-31",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"data\":{\"type\":\"RetailMediaReportRequest\",\"attributes\":{\"id\":\"8343086999167541140\",\"metrics\":[\"impressions\"],\"dimensions\":[\"date\"],\"reportType\":\"summary\",\"startDate\":\"2025-01-01\",\"endDate\":\"2025-01-31\",\"timeZone\":\"America/New_York\",\"campaignType\":\"sponsoredProducts\",\"salesChannel\":\"offline\"}}}");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/campaigns")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/campaigns');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
$request->setBody('{\"data\":{\"type\":\"RetailMediaReportRequest\",\"attributes\":{\"id\":\"8343086999167541140\",\"metrics\":[\"impressions\"],\"dimensions\":[\"date\"],\"reportType\":\"summary\",\"startDate\": \"2025-01-01\",\"endDate\":\"2025-01-31\",\"timeZone\":\"America/New_York\",\"campaignType\":\"sponsoredProducts\",\"salesChannel\":\"offline\"}}}');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Line Items Level Report
Sample Requestcurl -X POST "https://api.criteo.com/{version}/retail-media/reports/line-items" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "8343086999167541140",
"metrics": [
"impressions"
],
"dimensions": [
"date"
],
"reportType": "summary",
"startDate": "2020-04-06",
"endDate": "2020-06-04",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
}'
import requests
import json
url = "https://api.criteo.com/{version}/retail-media/reports/line-items"
payload = json.dumps({
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "1285",
"metrics": [
"impressions"
],
"dimensions": [
"date"
],
"reportType": "summary",
"startDate": "2022-06-06",
"endDate": "2022-07-04",
"timeZone": "America/New_York",
"campaignType": "sponsoredProducts",
"salesChannel": "offline"
}
}
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"data\": {\n \"type\": \"RetailMediaReportRequest\",\n \"attributes\": {\n \"id\": \"8343086999167541140\",\n \"metrics\": [\n \t\t\t\t\t\t\t\t \"impressions\"\n \t\t\t\t\t\t\t\t ],\n \t\t\t\t\t\t \"dimensions\": [\n \t\t\t\t\t\t \"date\"\n \t\t\t\t\t\t\t\t ],\n \"reportType\": \"summary\",\n \"startDate\": \"2020-04-06\",\n \"endDate\": \"2020-06-04\",\n \"timeZone\": \"America/New_York\",\n \"campaignType\": \"sponsoredProducts\",\n \t\t\t\t\t\t \"salesChannel\": \"offline\"\n }\n }\n }");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/line-items")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/line-items');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
$request->setBody('{\n \"data\": {\n \"type\": \"RetailMediaReportRequest\",\n \"attributes\": {\n \"id\": \"8343086999167541140\",\n \"metrics\": [\n \t\t\t\t\t\t\t\t \"impressions\"\n \t\t\t\t\t\t\t\t ],\n \t\t\t\t\t\t \"dimensions\": [\n \t\t\t\t\t\t \"date\"\n \t\t\t\t\t\t\t\t ],\n \"reportType\": \"summary\",\n \"startDate\": \"2020-04-06\",\n \"endDate\": \"2020-06-04\",\n \"timeZone\": \"America/New_York\",\n \"campaignType\": \"sponsoredProducts\",\n \t\t\t\t\t\t \"salesChannel\": \"offline\"\n }\n }\n }');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
{
"data": {
"type": "RetailMediaReportStatus",
"id": "2e733b8c-9983-4237-aab9-17a42f4267cb",
"attributes": {
"status": "pending",
"rowCount": null,
"fileSizeBytes": null,
"md5Checksum": null,
"createdAt": null,
"expiresAt": null,
"message": null
}
}
}
Reporting Asynchronous Workflow: Step 2 of 3
- Next, use the
reportIdto poll the report status endpoint until one is successfully computed
Get Status of a Specific Report
This endpoint retrieves the status of a specific report. Status can bepending, success, failure, or expired
Sample Request
curl -X GET "https://api.criteo.com/{version}/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/status" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/status"
payload={}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/status")
.method("GET", body)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/status');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Accept' => 'application/json',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
{
"data": {
"attributes": {
"status": "success",
"rowCount": 50,
"fileSizeBytes": 9711,
"md5CheckSum": "b92bf24cd899f172907f8b001b8a5edb",
"createdAt": "2025-02-19T19:40:27.000Z",
"expiresAt": "2025-02-26T19:40:30.000Z",
"message": "rows_count=50",
"id": "16d70ce4-6917-48b8-8a55-184809dd59b5"
},
"id": "16d70ce4-6917-48b8-8a55-184809dd59b5",
"type": "StatusResponse"
},
"warnings": [],
"errors": []
}
Reporting Asynchronous Workflow: Step 3 of 3
- Finally, download the report using the report output endpoint
- Report outputs are cached for at least 1 hour before expiration
- Exact expiration is indicated by the
expiresAtfield in the /status response
Download Output of a Specific Report
This endpoint returns the specific report in the requested format. Sample Requestcurl -X GET "https://api.criteo.com/{version}/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/output" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/output"
payload={}
headers = {
'Accept': 'application/octet-stream',
'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/output")
.method("GET", body)
.addHeader("Accept", "application/octet-stream")
.addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
Response response = client.newCall(request).execute();
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/{version}/retail-media/reports/73fb7859-301f-4371-be91-3e4ad00964aa/output');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Accept' => 'application/octet-stream',
'Authorization' => 'Bearer <MY_ACCESS_TOKEN>'
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
{
"columns": [
"campaignId", "campaignName", "campaignTypeName", "date", "impressions", "clicks",
"attributedOrders", "attributedUnits", "attributedSales", "ctr", "spend", "cpc", "cpo",
"roas", "uniqueVisitors", "frequency"
],
"data": [
[
"1285", "End of Summer Sale", "Open Auction", "2025-01-31", 0, 0,
1, 1, 76.9400, null, 0.0000, null, 0.0000,
null, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2025-01-29", 1883, 6,
8, 8, 1749.2600, 0.0032, 3.7000, 0.6167, 0.4625,
472.7730, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2025-01-28", 0, 0,
1, 1, 99.4600, null, 0.0000, null, 0.0000,
null, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2025-01-27", 35087, 107,
25, 25, 4381.2700, 0.0030, 96.3000, 0.9000, 3.8520,
45.4961, null, null
]
],
"rows":4
}
{
"columns": [
"purchasedDate", "purchasedHour", "advDate", "advHour", "daysDifference",
"campaignId", "campaignName", "lineItemId", "lineItemName",
"advProductId", "advProductGtin", "advProductMpn", "advProductName",
"advProductCategory", "purchasedProductId", "purchasedProductGtin",
"purchasedProductMpn", "purchasedProductName", "purchasedProductCategory",
"attributedUnits", "attributedSales", "advEngagement",
"advToPurchasedProductRelationship", "salesChannel", "retailerName",
"pageTypeName", "keyword", "attributionWindow"
],
"data": [
[
"2022-10-21", 16, "2022-10-21", 16, 0,
"1344", "End to end testing", "2602", "LJ Test",
"426292", null, null,
"Arm & Hammer Pure Baking Soda, 13.5 lbs", "hardware > tools > hammers > powered hammers", "426292", null, null,
"Arm & Hammer Pure Baking Soda, 13.5 lbs", "hardware > tools > hammers > powered hammers",
1, 8.6900, "click",
"same sku", "online", "Costco",
"category", "", "C30V01"
]
],
"rows": 1
}