DSP Analytics Endpoints
Endpoints
Those endpoints support requests to create campaign, line item and account reports and allow retrieving the report data and status.
Among the endpoints presented on this page, four are available in our
Stable
version. Only the Accounts level report request is currently inPreview
. For more details on this endpoint, visit our dedicated guide.
Verb | Endpoint | Description |
---|---|---|
POST | /reports/campaigns | Create a Campaign Level Report Request |
POST | /reports/line-items | Create a Line Item Level Report Request |
POST | /reports/accounts | Create an Account Level Report Request |
GET | /reports/{reportId}/status | Get Status of a Specific Report |
GET | /reports/{reportId}/output | Download Output of a Specific Report |
Report Request Attributes
Attribute | Data Type | Description |
---|---|---|
| string | Campaign or Line Item ID(s) of the desired report Examples: id: "12345" ids: ["12345", "67890"] Accepted values: single or list of string/int64 (max 50 IDs per call) Writeable? N / Nullable? N |
| string | Account ID(s) of the desired report Examples:
Accepted values: single or list of string/int64 (max 5 IDs per call) Writeable? N / Nullable? N |
| enum | Accepted values: |
| enum | Report types are pre-packaged reports that allow the specification of the report breakdown. See Report Types for more details about each of them.
Accepted values: refer to Report Types page for a complete list of available values Writeable? N / Nullable? N |
| list | Dimension attributes desired for metrics breakdown for the custom report of the campaign(s) / line item(s).
Accepted values: refer to Metrics and Dimensions page for a complete list of available values Writeable? N / Nullable? N |
| list | Quantitative metrics desired in the custom report of the campaign(s) / line item(s).
Accepted values: refer to Metrics and Dimensions page for a complete list of available values Writeable? N / Nullable? N |
| date | Start date to report (inclusive) Accepted values: |
| date | End date to report (inclusive) Accepted values: |
| enum | Campaign type Accepted values: |
| string | Time zone to consider in the report Accepted values: IANA (TZ database) time zones (example: |
| enum | The post-click attribution window, defined as the maximum number of days considered between a click and a conversion for attribution; conversions are attributed to the date of conversion, not the date of click; defaults to campaign settings if omitted; must be specified if The post-click attribution window, defined as the maximum number of days considered between a click and a conversion for attribution; conversions are attributed to the date of conversion, not the date of click.
Defaults to campaign settings if omitted; must be specified if Accepted values: |
| enum | The post-view attribution window, defined as the maximum number of days considered between an impression and a conversion for attribution; conversions are attributed to the date of conversion, not the date of impression; defaults to campaign settings if omitted; must be less than or equal to The post-view attribution window, defined as the maximum number of days considered between an impression and a conversion for attribution; conversions are attributed to the date of conversion, not the date of impression.
Defaults to campaign settings if omitted; must be less than or equal to Accepted values: |
| enum | Filter on specific sales channel: online or offline Accepted values: |
| enum | Format of the report data returned Accepted values: |
| 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.
|
| string | Specifies the conquesting strategy used with the keyword.
|
| 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
reportId
representing 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

https://api.criteo.com/preview/retail-media/reports/campaigns
Sample Request
curl -X POST "https://api.criteo.com/preview/retail-media/reports/campaigns" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "8343086999167541140",
"reportType": "summary",
"startDate": "2020-04-06",
"endDate": "2020-06-04",
"timeZone": "America/New_York"
}
}
}'
import requests
import json
url = "https://api.criteo.com/preview/retail-media/reports/campaigns"
payload = json.dumps({
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "1285",
"reportType": "summary",
"startDate": "2022-06-06",
"endDate": "2022-07-04",
"timeZone": "America/New_York"
}
}
})
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\": \"1285\",\n \"reportType\": \"summary\",\n \"startDate\": \"2022-06-06\",\n \"endDate\": \"2022-07-04\",\n \"timeZone\": \"America/New_York\"\n }\n }\n }");
Request request = new Request.Builder()
.url("https://api.criteo.com/preview/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/preview/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('{\n "data": {\n "type": "RetailMediaReportRequest",\n "attributes": {\n "id": "1285",\n "reportType": "summary",\n "startDate": "2022-06-06",\n "endDate": "2022-07-04",\n "timeZone": "America/New_York"\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();
}
Line Items Level Report

https://api.criteo.com/preview/retail-media/reports/line-items
Sample Request
curl -X POST "https://api.criteo.com/preview/retail-media/reports/line-items" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "8343086999167541140",
"reportType": "summary",
"startDate": "2020-04-06",
"endDate": "2020-06-04",
"timeZone": "America/New_York"
}
}
}'
import requests
import json
url = "https://api.criteo.com/preview/retail-media/reports/line-items"
payload = json.dumps({
"data": {
"type": "RetailMediaReportRequest",
"attributes": {
"id": "135404148467060736",
"reportType": "summary",
"startDate": "2022-04-06",
"endDate": "2022-06-04",
"timeZone": "America/New_York"
}
}
})
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\": \"135404148467060736\",\n \"reportType\": \"summary\",\n \"startDate\": \"2022-04-06\",\n \"endDate\": \"2022-06-04\",\n \"timeZone\": \"America/New_York\"\n }\n }\n }");
Request request = new Request.Builder()
.url("https://api.criteo.com/preview/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/preview/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": "135404148467060736",\n "reportType": "summary",\n "startDate": "2022-04-06",\n "endDate": "2022-06-04",\n "timeZone": "America/New_York"\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();
}
Sample Response
{
"data": {
"type": "RetailMediaReportStatus",
"id": "2e733b8c-9983-4237-aab9-17a42f4267cb",
"attributes": {
"status": "pending",
"rowCount": null,
"fileSizeBytes": null,
"md5Checksum": null,
"createdAt": null,
"expiresAt": null,
"message": null
}
}
}
Account Level Report

https://api.criteo.com/preview/retail-media/reports/accounts \
Sample request
curl -X POST https://api.criteo.com/preview/retail-media/reports/accounts \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "AsyncAccountsReportRequest",
"attributes": {
"accountIds": ["12345", "67890"],
"reportType": "summary",
"aggregationLevel": "campaign",
"searchTermTypes": ["entered"],
"searchTermTargetings": ["automatic"],
"targetedKeywordTypes": ["generic"],
"campaignType": "all",
"salesChannel": "all",
"mediaType": "all",
"format": "json-compact",
"clickAttributionWindow": "none",
"viewAttributionWindow": "none",
"dimensions": ["date", "accountId"],
"metrics": ["impressions"],
"startDate": "2025-10-10",
"endDate": "2025-10-10",
"timezone": "UTC"
}
}
}'
import requests
url = "https://api.criteo.com/preview/retail-media/reports/accounts"
headers = {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
}
payload = {
"data": {
"type": "AsyncAccountsReportRequest",
"attributes": {
"accountIds": ["12345", "67890"],
"reportType": "summary",
"searchTermTypes": ["entered"],
"searchTermTargetings": ["automatic"],
"targetedKeywordTypes": ["generic"],
"campaignType": "all",
"salesChannel": "all",
"mediaType": "all",
"format": "json-compact",
"clickAttributionWindow": "none",
"viewAttributionWindow": "none",
"dimensions": ["date", "accountId"],
"metrics": ["impressions"],
"startDate": "2025-10-10",
"endDate": "2025-10-10",
"timezone": "UTC"
}
}
}
response = requests.post(url, headers=headers, json=payload)
print("Status Code:", response.status_code)
print("Response Body:", response.json())
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class CriteoAccountReport {
public static void main(String[] args) {
try {
URL url = new URL("https://api.criteo.com/preview/retail-media/reports/accounts");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer YOUR_ACCESS_TOKEN");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
String jsonInputString = """
{
"data": {
"type": "AsyncAccountsReportRequest",
"attributes": {
"accountIds": ["12345", "67890"],
"reportType": "summary",
"searchTermTypes": ["entered"],
"searchTermTargetings": ["automatic"],
"targetedKeywordTypes": ["generic"],
"campaignType": "all",
"salesChannel": "all",
"mediaType": "all",
"format": "json-compact",
"clickAttributionWindow": "none",
"viewAttributionWindow": "none",
"dimensions": ["date", "accountId"],
"metrics": ["impressions"],
"startDate": "2025-10-10",
"endDate": "2025-10-10",
"timezone": "UTC"
}
}
}
""";
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
int responseCode = conn.getResponseCode();
System.out.println("Response Code: " + responseCode);
// Optionally read the response body here with InputStream if needed
} catch (Exception e) {
e.printStackTrace();
}
}
}
<?php
$accessToken = 'YOUR_ACCESS_TOKEN'; // Replace with your token
$apiUrl = 'https://api.criteo.com/preview/retail-media/reports/accounts'; // Replace {version} accordingly
$data = [
"data" => [
"type" => "AsyncAccountsReportRequest",
"attributes" => [
"accountIds" => ["12345", "67890"],
"reportType" => "summary",
"searchTermTypes" => ["entered"],
"searchTermTargetings" => ["automatic"],
"targetedKeywordTypes" => ["generic"],
"campaignType" => "all",
"salesChannel" => "all",
"mediaType" => "all",
"format" => "json-compact",
"clickAttributionWindow" => "none",
"viewAttributionWindow" => "none",
"dimensions" => ["date", "accountId"],
"metrics" => ["impressions"],
"startDate" => "2025-10-10",
"endDate" => "2025-10-10",
"timezone" => "UTC"
]
]
];
$ch = curl_init($apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $accessToken,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
echo 'Curl error: ' . curl_error($ch);
} else {
echo "HTTP Code: $httpCode\n";
echo "Response:\n$response";
}
curl_close($ch);
Sample response
{
"data": {
"type": "RetailMediaReportStatus",
"id": "f5a2cd3d-1e83-41b1-98b1-abcde1234567",
"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
reportId
to 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 be pending
, success
, failure
, or expired

https://api.criteo.com/preview/retail-media/reports/{reportId}/status
Sample Request
curl -X GET "https://api.criteo.com/preview/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/status" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/preview/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/preview/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/preview/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();
}
Sample Response
{
"data": {
"type": "RetailMediaReportStatus",
"id": "2e733b8c-9983-4237-aab9-17a42f4267cb",
"attributes": {
"status": "success",
"rowCount": null,
"fileSizeBytes": null,
"md5Checksum": null,
"createdAt": null,
"expiresAt": null,
"message": null
}
}
}
Sample Request
curl -X GET "https://api.criteo.com/preview/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/status" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
Sample Response
{
"data": {
"type": "RetailMediaReportStatus",
"id": "2e733b8c-9983-4237-aab9-17a42f4267cb",
"attributes": {
"status": "success",
"rowCount": 60,
"fileSizeBytes": 28967,
"md5Checksum": "2c15b77740028435ca476823df7fb4f8",
"createdAt": "2020-07-18T04:27:59.658Z",
"expiresAt": "2020-07-25T04:27:59.658Z",
"message": null
}
}
}
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
expiresAt
field in the /status response
Download Output of a Specific Report
This endpoint returns the specific report in the requested format

https://api.criteo.com/preview/retail-media/reports/{reportId}/output
Sample Request
curl -X GET "https://api.criteo.com/preview/retail-media/reports/2e733b8c-9983-4237-aab9-17a42f4267cb/output" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests
url = "https://api.criteo.com/preview/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/preview/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/preview/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();
}
Sample Response
Campaign Summary Report
{
"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", "2021-01-31", 0, 0, 1, 1, 76.9400, null, 0.0000, null, 0.0000, null, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2021-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", "2021-02-04", 0, 0, 1, 1, 99.4600, null, 0.0000, null, 0.0000, null, null, null
],
[
"1285", "End of Summer Sale", "Open Auction", "2021-01-28", 35087, 107, 25, 25, 4381.2700, 0.0030, 96.3000, 0.9000, 3.8520, 45.4961, null, null
]
],
"rows":4
}
Line Item Summary Report
{
"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
}
Updated 3 days ago