DSP Analytics Endpoints - Criteo Docs

Endpoints

Four separate endpoints support requests to create campaign and line item reports and retrieve the report data and status.

Verb Endpoint Description
POST /reports/campaigns Create a Campaign report request
POST /reports/line-items Create a Line Item 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
id/ids* string / list<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
reportType 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.
Note: whenmetricsanddimensionsare used,reportTypeis ignored.
Accepted values: refer to Report Types page for a complete list of available values
Writeable? N / Nullable? N
dimensions list<enum> Dimension attributes desired for metrics breakdown for the custom report of the campaign(s) / line item(s).
Note: whenmetricsanddimensionsare used,reportTypeis automatically ignored
Accepted values: refer to Metrics and Dimensions page for a complete list of available values
Writeable? N / Nullable? N
metrics list<enum> Quantitative metrics desired in the custom report of the campaign(s) / line item(s).
Note:
- whenmetricsanddimensionsare used, thereportTypeis automatically ignored
- when includingwinRatemetric, it is required to either definecampaignTypeassponsoredProductsor includecampaignTypeNamein the list of dimensions
Accepted values: refer to Metrics and Dimensions page for a complete list of available values
Writeable? N / Nullable? N
startDate* date Start date to report (inclusive)
Accepted values:YYYY-MM-DD
Writeable? N / Nullable? N
endDate* date End date to report (inclusive)
Accepted values:YYYY-MM-DD
Writeable? N / Nullable? N
campaignType enum Campaign type
Accepted values:sponsoredProducts,onSiteDisplays
Writeable? N / Nullable? N
timeZone string Time zone to consider in the report.
Defaults to UTC if omitted.
Accepted values: IANA (TZ database) time zones (example:America/New_York,Europe/Paris,Asia/Tokyo,UTC)
Writeable? N / Nullable? Y
clickAttributionWindow 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 ifviewAttributionWindowis one of the accepted values.
Accepted values:none,7D,14D,30D
Writeable? N / Nullable? Y
viewAttributionWindow 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 toclickAttributionWindow; must be specified ifclickAttributionWindowis one of the accepted values.
Accepted values:none,1D,7D,14D,30D
Writeable? N / Nullable? Y
salesChannel enum Filter on specific sales channel: online or offline
Accepted values:online,offline
Writeable? N / Nullable? Y
format enum Format of the report data returned
Accepted values:json,json-compact,json-newline,csvDefault:json
Writeable? N / Nullable? N
searchTermTypes string The match type used to associate a search term and keywords entered for the campaign.
Accepted values:
Entered: the search term matches exactly what was entered manually by the Commerce Max user
Searched: the search term matches what a shopper searched on the retailer’s website.
searchTermTargeting string Indicates how the keyword was targeted — either manually by the user or automatically by the platform.
Accepted values:
Manual: The search term matches a keyword entered in Commerce Max or a variation created via stemming.
Automatic: The search term was added by the automated keyword tool.
targetedKeywordType string Specifies the conquesting strategy used with the keyword.
Accepted values:
Conquesting: Targets competitors’ branded keywords.Branded: Targets the advertiser’s own branded keywords.
Generic: Targets neutral or non-branded keywords.
mediaType string The type of creative asset used in the ad, such as Display or Video.
Accepted values:video,display,all

*Required*

Reporting Asynchronous Workflow: Step 1 of 3


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 Request

curl -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, "{\n            \"data\": {\n                \"type\": \"RetailMediaReportRequest\",\n                \"attributes\": {\n                    \"id\": \"8343086999167541140\",\n                    \"metrics\": [\n            \t\t\t\t\t\t  \"impressions\"\n      \t\t\t\t\t\t ],\n      \t\t\t\t\t  \"dimensions\": [\n        \t\t\t\t\t   \"date\"\n      \t\t\t\t\t\t ],\n                    \"reportType\": \"summary\",\n                    \"startDate\": \"2025-01-01\",\n                    \"endDate\": \"2025-01-31\",\n                    \"timeZone\": \"America/New_York\",\n                    \"campaignType\": \"sponsoredProducts\",\n      \t\t\t\t\t  \"salesChannel\": \"offline\"\n                }\n            }\n        }");

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 Request

curl -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  \"impressions\"\n      \t\t\t\t\t\t ],\n      \t\t\t\t\t  \"dimensions\": [\n        \t\t\t\t\t   \"date\"\n      \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  \"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('{
            \"data\": {\n                \"type\": \"RetailMediaReportRequest\",\n                \"attributes\": {\n                    \"id\": \"8343086999167541140\",\n                    \"metrics\": [\n       \t\t\t\t\t\t \"impressions\"\n      \t\t\t\t\t\t ],\n      \t\t\t\t\t  \"dimensions\": [\n        \t\t\t\t\t   \"date\"\n      \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  \"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();
}
?>

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
        }
    }
}

Reporting Asynchronous Workflow: Step 2 of 3


Get Status of a Specific Report

This endpoint retrieves the status of a specific report. Status can be pending, 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();
}
?>

Sample Response

{
    "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


Download Output of a Specific Report

This endpoint returns the specific report in the requested format.

Sample Request

curl -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();
}
?>

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", "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
}

Sample Response: Campaign Attribution 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
}

What’s next