Version 2025.07 Release Notes

📘

Version 2025.07 of the Criteo Retail Media API is live as of July 22nd, 2025 and will be supported until July 28th, 2026. A new Postman collection for 2025.07 is also available in the Criteo Postman workspace.

📘

New SDK Release

A new SDK version will be available for the 2025.07 release.

This version introduces new capabilities to Criteo Retail Media API and changes to existing endpoints. This page aims at listing all changes that happened endpoint per endpoint. Only endpoints with changes are listed here.

The changes of versions 2025.07 are:

  • a new base URL,
  • new endpoints to Review Keywords for retailers,
  • new endpoints for Catalog to increase efficiency,
  • a new Brand Search endpoint,
  • new endpoints for Retailer Billing
  • new Reporting Dimensions & Filters within the analytics endpoints,

New Base URL

With the introduction of this new version, the base URL will now change from the old base URL:

https://api.criteo.com/2025-04/retail-media/{endpoint}

to the new base URL:

https://api.criteo.com/2025-07/retail-media/{endpoint}

What's New

Keyword Review & Approval

In version 2025.07, we've introduced new endpoints that are used by retailers to review keywords that are desired to be used for targeting on retailer inventory.

When an advertiser proposes a set of keywords for review, these keywords are then forwarded to the retailer reviewer, who evaluates them based on predefined criteria such as relevance, accuracy, and compliance with retailer guidelines.

📘

You can find the documentation for the Keyword review endpoints here.


Updated Endpoints

The following new catalog endpoint can be found below:

VerbEndpointDescription
GET/retail-media/accounts/:account-id/keywords/in-review-reportGenerate a list of reports for line items which contain one or more actionable keyword reviews
GET/retail-media/line-items/:id/keywords *Fetch keywords associated with the specified line item
POST/retail-media/line-items/:line-item-id/keywords/reviewUpdate the status of keyword reviews under a line item

⚠️

NOTE

The asterisk next to the /retail-media/line-items/:id/keywords is because this endpoint is undergoing a breaking change, because this endpoint has been updated to allow for retailers to be able to view the keywords that are inReview status for line items targeting their inventory.

Please see here for more information on breaking changes and please note that older versions of this endpoint will still be supported in alignment with their support window as defined in our Versioning Policy.


Sample Request

For /retail-media/accounts/:account-id/keywords/in-review-report:

curl -L -X GET "https://api.criteo.com/2025-07/retail-media/accounts/368477770340928512/keywords/in-review-report?offset=0&limit=25" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests

url = "https://api.criteo.com/2025-07/retail-media/accounts/368477770340928512/keywords/in-review-report?offset=0&limit=25"

payload={}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/2025-07/retail-media/accounts/368477770340928512/keywords/in-review-report?offset=0&limit=25');
$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();
}
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/2025-07/retail-media/accounts/368477770340928512/keywords/in-review-report?offset=0&limit=25")
  .method("GET", body)
  .addHeader("Accept", "application/json")
  .addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
  .build();

Response response = client.newCall(request).execute();

Sample Response

For /retail-media/accounts/:account-id/keywords/in-review-report:

{
    "meta": {
        "count": 2,
        "offset": 0,
        "limit": 25
    },
    "data": [
        {
            "id": "12475533336215680",
            "type": "LineItemKeywordReviewReport",
            "attributes": {
                "lineItemId": "124444617126215680",
                "lineItemName": "LI_Test12101403",
                "retailerId": "299",
                "retailerName": "z_CriteoTest_299",
                "campaignId": "12455551383269376",
                "campaignName": "Test12101403_Update",
                "accountId": "97397777059194368",
                "accountName": "Test Account",
                "countKeywords": 2
            }
        },
        {
            "id": "124773333405488128",
            "type": "LineItemKeywordReviewReport",
            "attributes": {
                "lineItemId": "124777703405488128",
                "lineItemName": "LI——Test12101403",
                "retailerId": "299",
                "retailerName": "z_CriteoTest_299",
                "campaignId": "124755555383269376",
                "campaignName": "Test12101403_Update",
                "accountId": "97393333059194368",
                "accountName": "Test Account",
                "countKeywords": 4
            }
        }
    ],
    "warnings": [],
    "errors": []
}

Sample Request

For /retail-media/line-items/:id/keywords:

curl -L -X GET "https://api.criteo.com/2025-07/retail-media/line-items/358669999976373760/keywords" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests

url = "https://api.criteo.com/2025-07/retail-media/line-items/358669652999973760/keywords"

payload={}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://api.criteo.com/2025-07/retail-media/line-items/358669999976373760/keywords');
$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();
}
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/2025-07/retail-media/line-items/358669999976373760/keywords")
  .method("GET", body)
  .addHeader("Accept", "application/json")
  .addHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
  .build();

Response response = client.newCall(request).execute();

Sample Response

For /retail-media/line-items/:id/keywords:

{
    "data": {
        "id": "124755555126215680",
        "type": "RetailMediaKeywordsModel",
        "attributes": {
            "keywords": {
                "ww": {
                    "reviewState": "Approved",
                    "matchType": "PositiveExactMatch",
                    "bid": 2.00,
                    "inputKeywords": {
                        "positiveExact": [
                            "ww"
                        ]
                    },
                    "createdAt": "2024-07-30T02:16:57.1437069",
                    "updatedAt": "2025-03-27T17:57:29.81817"
                },
                "testaddallkeyword": {
                    "reviewState": "InReview",
                    "matchType": "PositiveExactMatch",
                    "bid": 1.30,
                    "inputKeywords": {
                        "positiveExact": [
                            "testaddallkeyword"
                        ]
                    },
                    "createdAt": "2024-07-30T06:55:40.5533984",
                    "updatedAt": "2024-07-30T06:55:41.3464883"
                },
                "testallkeyword0730": {
                    "reviewState": "InReview",
                    "matchType": "PositiveExactMatch",
                    "bid": 1.99,
                    "inputKeywords": {
                        "positiveExact": [
                            "testallkeyword0730"
                        ]
                    },
                    "createdAt": "2024-07-30T11:10:44.0215413",
                    "updatedAt": "2024-07-30T11:10:44.9437715"
                },
                "pasta": {
                    "reviewState": "Approved",
                    "matchType": "PositiveExactMatch",
                    "bid": null,
                    "inputKeywords": {
                        "positiveExact": [
                            "pasta",
                            "pastas"
                        ]
                    },
                    "createdAt": "2025-04-17T15:59:46.1603449",
                    "updatedAt": "2025-04-17T16:20:13.7929382"
                }
            }
        }
    }
}

Sample Request

For /retail-media/line-items/:line-item-id/keywords/review:

curl -L -X POST "https://api.criteo.com/2025-07/retail-media/line-items/358669652976373760/keywords/review" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>" \
    -H "Content-Type: application/json" \
    -d '{
            "data": {
                "attributes": {
                    "keywords": [
                        {
                            "phrase": "top",
                            "reviewState": "rejected"
                        },
                        {
                            "phrase": "t-shirt",
                            "reviewState": "approved"
                        }
                    ]
                }
            }
        }'
import requests

headers = {
    'Authorization': 'Bearer <MY_ACCESS_TOKEN>',
    'Content-Type': 'application/json',
}

json_data = {
    'data': {
        'attributes': {
            'keywords': [
                {
                    'phrase': 'top',
                    'reviewState': 'rejected',
                },
                {
                    'phrase': 't-shirt',
                    'reviewState': 'approved',
                },
            ],
        },
    },
}

response = requests.post(
    'https://api.criteo.com/2025-07/retail-media/line-items/358669652976373760/keywords/review',
    headers=headers,
    json=json_data,
)
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.criteo.com/2025-07/retail-media/line-items/358669652976373760/keywords/review"))
    .POST(BodyPublishers.ofString("{\n            \"data\": {\n                \"attributes\": {\n                    \"keywords\": [\n                        {\n                            \"phrase\": \"top\",\n                            \"reviewState\": \"rejected\"\n                        },\n                        {\n                            \"phrase\": \"t-shirt\",\n                            \"reviewState\": \"approved\"\n                        }\n                    ]\n                }\n            }\n        }"))
    .setHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
    .setHeader("Content-Type", "application/json")
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.criteo.com/2025-07/retail-media/line-items/358669652976373760/keywords/review');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer <MY_ACCESS_TOKEN>',
    'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\n            \"data\": {\n                \"attributes\": {\n                    \"keywords\": [\n                        {\n                            \"phrase\": \"top\",\n                            \"reviewState\": \"rejected\"\n                        },\n                        {\n                            \"phrase\": \"t-shirt\",\n                            \"reviewState\": \"approved\"\n                        }\n                    ]\n                }\n            }\n        }");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

$response = curl_exec($ch);

curl_close($ch);

Sample Response

For /retail-media/line-items/:line-item-id/keywords/review:

{
    "data": {
        "type": "RetailMediaKeywordsReviewResult",
        "attributes": {
            "keywords": [
                {
                    "phrase": "top",
                    "reviewState": "Rejected"
                },
                {
                    "phrase": "t-shirt",
                    "reviewState": "Approved"
                },
                {
                    "phrase": "top woman",
                    "reviewState": "InReview"
                }
            ]
        }
    },
    "warnings": [],
    "errors": []
}

Catalog Export

In version 2025.07, we've introduced new catalog endpoints with the inclusion of new fields and features, such as the includeFields, modifiedAfter, and a new retailerIdFilter in the brand-catalog-export endpoint.

The includeFields is a new filter that gives users the option of focusing on what information you want in the catalog call, as some fields may be irrelevant to specific use cases and impacts the speed of the request. The modifiedAfter is a way to focus further on SKUs that have been modified after a specified time for both seller and brand endpoints. The upper limit of this field is set to -18 hours from the current time. After this, a user will be asked to run a full export instead.

📘

You can find the Catalog endpoints documentation here.


Updated Endpoints

The following new catalog endpoint can be found below:

VerbEndpointDescription
POST/accounts/{accountId}/brand-catalog-exportCreate a request to export existing catalogs from a Brand account
POST/accounts/{accountId}/seller-catalog-exportCreate a request to export existing catalogs from a Seller account
GET/catalogs/{catalogId}/statusRetrieve the status of a specific catalog request.
GET/catalogs/{catalogId}/outputDownload the output of a specific catalog once it's ready.

Sample Request

For /accounts/{accountId}/brand-catalog-export:

https://api.criteo.com/2025-07/retail-media/accounts/{accountId}/brand-catalog-export
curl -L -X POST 'https://api.criteo.com/2025-07/retail-media/accounts/123/brand-catalog-export' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
--data-raw '{
  "data": {
    "type": "CatalogRequest",
    "attributes": {
      "brandIdFilter": [
        "123"
      ],
      "retailerIdFilter": [
        "456"
      ],
      "modifiedAfter": "2025-03-21T08:00:00-5:00",
      "includeFields": ["ImageUrl","GoogleCategory", "RetailerName", "Category", "BrandName","Description"]
    }
  }
}'
import requests
import json

url = "https://api.criteo.com/2025-07/retail-media/accounts/123/brand-catalog-export"

payload = json.dumps({
  "data": {
    "type": "<string>",
    "attributes": {
      "brandIdFilter": [
        "123"
      ],
      "retailerIdFilter": [
        "456"
      ],
      "modifiedAfter": "2025-03-21T08:00:00-5:00",
      "includeFields": ["ImageUrl","GoogleCategory", "RetailerName", "Category", "BrandName","Description"]
    }
  }
})
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\": \"<string>\",\n   \"attributes\": {\n     \"brandIdFilter\": [\n       \"123\"\n     ],\n     \"retailerIdFilter\": [\n       \"456\"\n     ],\n     \"modifiedAfter\": \"2025-03-21T08:00:00-5:00\",\n     \"includeFields\": [\"ImageUrl\",\"GoogleCategory\", \"RetailerName\", \"Category\", \"BrandName\",\"Description\"]\n   }\n }\n}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/2025-07/retail-media/accounts/123/brand-catalog-export")
  .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/2025-07/retail-media/accounts/123/brand-catalog-export');
$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": "<string>",\n   "attributes": {\n     "brandIdFilter": [\n       "123"\n     ],\n     "retailerIdFilter": [\n       "456"\n     ],\n     "modifiedAfter": "2025-03-21T08:00:00-5:00",\n     "includeFields": ["ImageUrl","GoogleCategory", "RetailerName", "Category", "BrandName","Description"]\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

For /accounts/{accountId}/brand-catalog-export:

{
    "data": {
        "type": "RetailMediaCatalogStatus",
        "id": "1122850670915847014",
        "attributes": {
            "status": "pending",
            "currency": null,
            "rowCount": null,
            "fileSizeBytes": null,
            "md5Checksum": null,
            "createdAt": "2025-01-22T23:10:12.21+00:00",
            "message": null
        }
    }
}

Sample Request

For /accounts/{accountId}/seller-catalog-export:

https://api.criteo.com/2025-07/retail-media/accounts/{accountId}/seller-catalog-export
curl -L -X POST 'https://api.criteo.com/2025-07/retail-media/accounts/123/seller-catalog-export' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
--data-raw '{
  "data": {
    "type": "<string>",
    "attributes": {
      "sellers": [
        {
          "retailerId": "123",
          "sellerId": "5e0axxxxxxxxxx"
        }
      ],
      "modifiedAfter": "",
      "includeFields": [
        "ImageUrl",
        "Description"
      ]
    }
  }
}'
import requests
import json

url = "https://api.criteo.com/2025-07/retail-media/accounts/123/seller-catalog-export"

payload = json.dumps({
  "data": {
    "type": "<string>",
    "attributes": {
      "sellers": [
        {
          "retailerId": "123",
          "sellerId": "5e0axxxxxxxxxx"
        }
      ],
      "modifiedAfter": "",
      "includeFields": [
        "ImageUrl",
        "Description"
      ]
    }
  }
})
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\": \"<string>\",\n   \"attributes\": {\n     \"sellers\": [\n       {\n         \"retailerId\": \"123\",\n         \"sellerId\": \"5e0axxxxxxxxxx\"\n       }\n     ],\n     \"modifiedAfter\": \"\",\n     \"includeFields\": [\n     \"ImageUrl\",\n     \"Description\"\n     ]\n   }\n }}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/2025-07/retail-media/accounts/123/seller-catalog-export")
  .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/2025-07/retail-media/accounts/123/seller-catalog-export');
$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": "<string>",\n   "attributes": {\n     "sellers": [\n       {\n         "retailerId": "123",\n         "sellerId": "5e0axxxxxxxxxx"\n       }\n     ],\n     "modifiedAfter": "",\n     "includeFields": [\n     "ImageUrl",\n     "Description"\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

For /accounts/{accountId}/seller-catalog-export:

{
    "data": {
        "type": "RetailMediaCatalogStatus",
        "id": "1122850670915847014",
        "attributes": {
            "status": "pending",
            "currency": null,
            "rowCount": null,
            "fileSizeBytes": null,
            "md5Checksum": null,
            "createdAt": "2025-01-22T23:10:12.21+00:00",
            "message": null
        }
    }
}

Get Status of a Specific Catalog

This endpoint retrieves the status of a specific catalog. Status can be pending, success, failure, or expired

Sample Request

For /catalogs/{catalogId}/status:

curl -X GET "https://api.criteo.com/2025-07/retail-media/catalogs/1122888880915847014/status" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import requests

url = "https://api.criteo.com/2025-07/retail-media/catalogs/357957888889011328/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/2025-07/retail-media/catalogs/35795788888011328/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/2025-07/retail-media/catalogs/357957888889011328/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

For /catalogs/{catalogId}/status:

{
    "data": {
        "type": "RetailMediaCatalogStatus",
        "id": "1122850670915847014",
        "attributes": {
            "status": "success",
            "currency": "USD",
            "rowCount": 1001,
            "fileSizeBytes": 353293,
            "md5Checksum": "2c15b77740028435ca476823df7fb4f8",
            "createdAt": "2020-04-06T05:11:41.351+00:00",
            "message": null
        }
    }
}

Download Output of a Specific Catalog

This endpoint returns the products in a specific catalog as a newline-delimited JSON byte stream

⚠️

The limit will be capped at 100 000 rows. If a user reaches this limit, they will need to revise their request to fall within the limit.

Sample Request

For /catalogs/{catalogId}/output:

curl -X GET "https://api.criteo.com/2025-07/retail-media/catalogs/1122850670915847014/output" \
    -H "Authorization: Bearer <MY_ACCESS_TOKEN>"
import http.client

conn = http.client.HTTPSConnection("api.criteo.com")
payload = ''
headers = {
  'Accept': 'application/x-json-stream',
  'Authorization': 'Bearer <MY_ACCESS_TOKEN>'
}
conn.request("GET", "/2025-07/retail-media/catalogs/357957813719011328/output", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
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/2025-07/retail-media/catalogs/357957813719011328/output")
  .method("GET", body)
  .addHeader("Accept", "application/x-json-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/2025-07/retail-media/catalogs/357957813719011328/output');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'Accept' => 'application/x-json-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

For /catalogs/{catalogId}/output:

{ \
    "id": "sku_1", \
    "name": "Product Name", \
    "category": "clothing, shoes & accessories|men’s clothing|bottoms|shorts", \
    "categoryId": "1234xxxx", \
    "brandId": "123456xxxxxx", \
    "brandName": "Brand Name", \
    "retailerId": "54321xxxxxx", \
    "retailerName": "Retailer Name", \
    "price": 1.00, \
    "isInStock": true, \
    "minBid": 0.30, \
    "gtin": "abc12xx", \
    "mpn": "34abxxx", \
    "imageUrl": "/image1.jpg", \
    "updatedAt": "2020-04-06T02:23:07Z", \
    "sellerId": "60axxxxxxxxxxxxxxxx", \
    "sellerName": "Seller Name", \
    "googleCategory": null, \
    "description": "Product's Description" \
}
 
// ... newline-delimited, no comma
 
{ \
    "id": "sku_2", \
    "name": "Product Name", \
    "category": "clothing, shoes & accessories|men’s clothing|bottoms|shorts", \
    "categoryId": "1234xxxx", \
    "brandId": "567890xxxxxx", \
    "brandName": "Brand Name", \
    "retailerId": "098765xxxxxx", \
    "retailerName": "Retailer Name", \
    "price": 1.00, \
    "isInStock": true, \
    "minBid": 0.30, \
    "gtin": "xyz12xx", \
    "mpn": "78asdxxx", \
    "imageUrl": "/image1.jpg", \
    "updatedAt": "2020-04-06T02:23:07Z", \
    "sellerId": null, \
    "sellerName": "Seller Name", \
    "googleCategory": null, \
    "description": "Product's Description" \
}

// ... newline-delimited, no comma
 
{ \
    "id": "sku_3", \
    "name": "Product Name", \
    "category": "clothing, shoes & accessories|men’s clothing|bottoms|shorts", \
    "categoryId": "4568xxxx", \
    "brandId": "96385xxxxxx", \
    "brandName": "Brand Name", \
    "retailerId": "412587xxxxxx", \
    "retailerName": "Retailer Name", \
    "price": 1.00, \
    "isInStock": true, \
    "minBid": 0.30, \
    "gtin": "xyz12xx", \
    "mpn": "56wsdxxx", \
    "imageUrl": "/image1.jpg", \
    "updatedAt": "2020-04-06T02:23:07Z", \
    "sellerId": null, \
    "sellerName": null, \
    "googleCategory": null, \
    "description": "Product's Description" \
}

Brand Search

In version 2025.07, we've introduced a new brand search endpoint that offers an enhanced experience to the brand lookup operation.

In the initial brand lookup workflow, users were required to search for brands specific to the account ID of interest. This endpoint offers an experience which enables users to search for the brand by name, with the ability to indicate if this is a brand from our universal catalog (for brands) or a retailer brand (for retailers) or both.

📘

You can find the Brand Search endpoint documentation here.


Updated Endpoints Includes

The following new catalog endpoint can be found below:

VerbEndpointDescription
POST/brands/searchSearch for Brands by name in Retailer(s) Catalogs

For other related endpoints, check our stable version in Brands


Sample Request

ForBrand Search:

curl -L -X POST 'https://api.criteo.com/2025-07/retail-media/brands/search?offset=0&limit=25' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
    -d '{
            "data": {
                "type": "<string>",
                "attributes": {
                    "retailerIds": [
                        "123",
                        "456"
                    ],
                    "name": "brand abc",
                    "brandType": "all"
                }
            }
        }'
import requests
import json

url = "https://api.criteo.com/2025-07/retail-media/brands/search?offset=0&limit=25"

payload = json.dumps({
    "data": {
        "type": "<string>",
        "attributes": {
            "retailerIds": [
                "123",
                "456"
            ],
            "name": "brand abc",
            "brandType": "all"
        }
    }
})
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\":\"<string>\",\"attributes\":{\"retailerIds\":[\"123\",\"456\"],\"name\":\"brand abc\",\"brandType\":\"all\"}}}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/2025-07/retail-media/brands/search?offset=0&limit=25")
  .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/2025-07/retail-media/brands/search?offset=0&limit=25');
$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":"<string>","attributes":{"retailerIds":["123","456"],"name":"brand abc","brandType":"all"}}}');
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

For Brand Search:

{
    "metadata": {
        "count": 2,
        "offset": 0,
        "limit": 25
    },
    "data": [
        {
            "id": "2149023412134133",
            "type": "BrandIdSearchResult",
            "attributes": {
                "id": "2149023412134133",
                "name": "brand abcdef",
                "brandType": "Retailer",
                "retailerIds": [
                    123
                ]
            }
        },
        {
            "id": "62342",
            "type": "BrandIdSearchResult",
            "attributes": {
                "id": "62342",
                "name": "Brand ABC",
                "brandType": "UC",
                "retailerIds": [
                    123,
                    456
                ]
            }
        }
    ],
    "warnings": [],
    "errors": []
}

Partner Billing Report

In version 2025.07, we've introduced the Partner Billing Report (PBR) endpoints which enable retailers to bill their retailer-contracted advertisers, manage invoicing, and track payments for advertisers who have contracted directly with them, especially in private market setups.

It also enables the ability to verify retailer-related fees and media costs associated with campaigns managed through CMax & CYield. This ensures transparency and accuracy in financial reconciliations.

📘

You can find the Partner Billing Report documentation here.


Updated Endpoints Include

The following new catalog endpoint can be found below:

VerbEndpointDescription
POST/billing/partner-reportRequest a partner billing report creation
GET/billing/partner-report/{reportId}/statusGet status of a specific report
GET/billing/partner-report/{reportId}/outputDownload output of a specific report

Sample Request

For /billing/partner-report:

https://api.criteo.com/2025-07/retail-media/billing/partner-report
curl -L -X POST 'https://api.criteo.com/2025-07/retail-media/billing/partner-report' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer <MY_ACCESS_TOKEN>' \
    -d '{
            "data": {
                "type": "<string>",
                "attributes": {
                    "accountIds": [
                        "4257354444567401216"
                    ],
                    "retailerIds": [
                        "1234",
                        "5678"
                    ],
                    "startDate": "2025-01-01",
                    "endDate": "2025-01-31",
                    "format": "json"
                }
            }
        }'
import requests
import json

url = "https://api.criteo.com/2025-07/retail-media/billing/partner-report"

payload = json.dumps({
    "data": {
        "type": "<string>",
        "attributes": {
            "accountIds": [
                "4257354444567401216"
            ],
            "retailerIds": [
                "1234",
                "5678"
            ],
            "startDate": "2025-01-01",
            "endDate": "2025-01-31",
            "format": "json"
        }
    }
})
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\":\"<string>\",\"attributes\":{\"accountIds\":[\"4257354444567401216\"],\"retailerIds\":[\"1234\",\"5678\"],\"startDate\":\"2025-01-01\",\"endDate\":\"2025-01-31\",\"format\":\"json\"}}}");

Request request = new Request.Builder()
  .url("https://api.criteo.com/2025-07/retail-media/billing/partner-report")
  .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/2025-07/retail-media/billing/partner-report');
$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":"<string>","attributes":{"accountIds":["4257354444567401216"],"retailerIds":["1234","5678"],"startDate":"2025-01-01","endDate":"2025-01-31","format":"json"}}}');
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

For /billing/partner-report:

{
    "data": {
        "id": "c19ed799-6747-4815-aa09-d3e04898xxxx",
        "type": "PartnerBillingReportStatusV1",
        "attributes": {
            "status": "success",
            "errorMessage": null,
            "createdAt": "2025-03-27T14:43:28.3788206+00:00"
        }
    },
    "warnings": [],
    "errors": []
}

Sample Request

For /billing/partner-report/{reportId}/status:

https://api.criteo.com/2025-07/retail-media/billing/partner-report/{reportId}/status
curl -L 'https://api.criteo.com/2025-07/retail-media/billing/partner-report/c19ed799-6747-4815-aa09-d3e04898xxxx/status' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer <MY_ACCESS_TOKEN>'

Sample Response

For /billing/partner-report/{reportId}/status:

{
    "data": {
        "id": "c19ed799-6747-4815-aa09-d3e04898xxxx",
        "type": "PartnerBillingReportStatusV1",
        "attributes": {
            "status": "pending",
            "errorMessage": null,
            "createdAt": "2025-03-27T14:43:28.3788206+00:00"
        }
    },
    "warnings": [],
    "errors": []
}

Sample Request

For /billing/partner-report/{reportId}/output:

Once the report creation is completed ("status": "success" in response above), the report output will be available to download in this endpoint.

https://api.criteo.com/2025-07/retail-media/billing/partner-report/{reportId}/output

Sample Response

For /billing/partner-report/{reportId}/output:

[
    {
        "AccountName": "Brand A US",
        "AccountExternalId": "525404033764731234",
        "IsUnbillable": "No",
        "AccountCategory": "Network Demand",
        "RetailerName": "My Retailer Shop",
        "AccountService": null,
        "AccountCurrencyCode": "USD",
        "ExternalBalanceId": "525746374845021111",
        "BalanceName": null,
        "PurchaseOrder": null,
        "BalanceStartDate": null,
        "PrivateMarketPaymentOption": null,
        "CampaignExternalId": null,
        "CampaignName": "Brand A - Campaign Jan2025",
        "CampaignType": "SponsoredProducts",
        "BuyType": "Auction",
        "LineItemId": 530088677885964287,
        "LineItemName": "Brand A - My Retailer Shop - Jan2025",
        "WorkingMediaSpend": 100.72000000,
        "CreditSpend": 0.00000000,
        "ValueAddSpend": 0.00000000,
        "Clicks": 394,
        "Impressions": 0,
        "SupplyFeeAmount": 0.0000000,
        "RetailerManagedFeeRate": 0.0,
        "RetailerManagedFeeAmount": 0.0,
        "RetailerAudienceDataFeeAmount": null,
        "CriteoRetailerDataFeeAmount": null,
        "UtcOffset": "-05:00"
    },
    // ...
    {
        "AccountName": "Brand B US",
        "AccountExternalId": "137955447513525678",
        "IsUnbillable": "No",
        "AccountCategory": "Network Demand",
        "RetailerName": "My Retailer Shop",
        "AccountService": null,
        "AccountCurrencyCode": "USD",
        "ExternalBalanceId": "390893529643232222",
        "BalanceName": null,
        "PurchaseOrder": null,
        "BalanceStartDate": null,
        "PrivateMarketPaymentOption": null,
        "CampaignExternalId": null,
        "CampaignName": "Brand B - Auction 2025",
        "CampaignType": "SponsoredProducts",
        "BuyType": "Auction",
        "LineItemId": 592048399992061951,
        "LineItemName": "Brand B - My Retailer Shop - Jan2025",
        "WorkingMediaSpend": 1497.28125424,
        "CreditSpend": 0.00000000,
        "ValueAddSpend": 0.00000000,
        "Clicks": 5312,
        "Impressions": 0,
        "SupplyFeeAmount": 0.00000000,
        "RetailerManagedFeeRate": 0.0,
        "RetailerManagedFeeAmount": 0.0,
        "RetailerAudienceDataFeeAmount": null,
        "CriteoRetailerDataFeeAmount": null,
        "UtcOffset": "-05:00"
    }
]

New Reporting Dimensions & Filters

In version 2025.07, we've introduced new reporting dimensions & filters within the analytics endpoints.

The updated analytics endpoints provide users with deeper, more comprehensive insights, enabling them to explore data more effectively. Additionally, the introduction of new report types empowers users to make more informed, data-driven decisions by offering tailored, actionable insights that better align with your strategic goals.

In the latest version, you now have the flexibility to generate reporting with a focus on Media Type to allow users to more precisely identify performance against Display or Video. The Media Type dimension is available across the DSP & SSP endpoints and is available not only as a dimension but a filter as well.

There are also new filters with a focus on Attribution designed to provide deeper insights into our performance according to the click match level and view match level for post-click and post-impression attribution levels. These metrics are available in the SSP API only.


Updated Endpoints Includes

The following new reporting changes apply for both the asynchronous campaign and line-item endpoints for report generation:

VerbEndpointDescription
POST/reports/campaignsCreate a Campaign Report Request
POST/reports/line-itemsCreate a Line Item Report Request
POST/reports/revenueCreate a Revenue Report Request

Sample Request with mediaType Attribute & Dimension

For Campaign Report:

curl --location 'https://api.criteo.com/2025-07/retail-media/reports/campaigns' \
--header 'Content-Type: application/json' \
--header 'Accept: text/plain' \
--header 'Authorization: Bearer ****' \
--data '{
  "data": {
    "attributes": {
      "endDate": "2025-04-22",
      "startDate": "2025-04-01",
      "campaignType": "all",
      "clickAttributionWindow": "none",
      "dimensions": [
        "campaignName",
        "campaignId",
				"mediaType"
      ],
      "format": "csv",
      "id": "1234",
      "metrics": [
        "impressions",
        "clicks",
        "winRate"
      ],
      "reportType": "summary",
      "salesChannel": "all",
			"mediaType": "all"
      "timezone": "UTC",
      "viewAttributionWindow": "none"
    },
    "type": "AsyncCampaignsReportRequest"
  }
}'
import http.client
import json

conn = http.client.HTTPSConnection('api.criteo.com')
headers = {
    'Content-Type': 'application/json',
    'Accept': 'text/plain',
    'Authorization': '••••••',
}
json_data = {
    'data': {
        'attributes': {
            'endDate': '2025-03-31',
            'startDate': '2025-03-01',
            'accountIds': [
                '1234',
            ],
            'advertiserTypes': [
                'brand',
                'seller',
            ],
            'buyType': 'auction',
            'campaignIds': [
                '123',
            ],
            'campaignType': 'all',
            'clickAttributionWindow': 'none',
            'clickMatchLevel': 'campaign',
            'dimensions': [
                'retailerCategoryName',
                'brandId',
            ],
            'format': 'json',
            'id': '1234567890',
            'lineItemIds': [
                '12345',
            ],
            'metrics': [
                'impressions',
                'roas',
            ],
            'retailerIds': [
                '111',
            ],
            'revenueType': 'auction',
            'salesChannel': 'all',
            'skuRelations': [
                'sameBrand',
                'sameCategory',
            ],
            'soldBy': 'directSold',
            'timezone': 'UTC',
            'viewAttributionWindow': 'none',
            'viewMatchLevel': 'campaign',
        },
        'type': 'RevenueReportRequest',
    },
}
conn.request(
    'POST',
    '/2025-07/retail-media/reports/revenue',
    json.dumps(json_data),
    headers
)
response = conn.getresponse()
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.criteo.com/2025-07/retail-media/reports/campaigns"))
    .POST(BodyPublishers.ofString("{\n  \"data\": {\n    \"attributes\": {\n      \"endDate\": \"2025-04-22\",\n      \"startDate\": \"2025-04-01\",\n      \"campaignType\": \"all\",\n      \"clickAttributionWindow\": \"none\",\n      \"dimensions\": [\n        \"campaignName\",\n        \"campaignId\",\n\t\t\t\t\"mediaType\"\n      ],\n      \"format\": \"csv\",\n      \"id\": \"1234\",\n      \"metrics\": [\n        \"impressions\",\n        \"clicks\",\n        \"winRate\"\n      ],\n      \"reportType\": \"summary\",\n      \"salesChannel\": \"all\",\n\t\t\t\"mediaType\": \"all\"\n      \"timezone\": \"UTC\",\n      \"viewAttributionWindow\": \"none\"\n    },\n    \"type\": \"AsyncCampaignsReportRequest\"\n  }\n}"))
    .setHeader("Content-Type", "application/json")
    .setHeader("Accept", "text/plain")
    .setHeader("Authorization", "Bearer ****")
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.criteo.com/2025-07/retail-media/reports/campaigns');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: text/plain',
    'Authorization: Bearer ****',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\n  \"data\": {\n    \"attributes\": {\n      \"endDate\": \"2025-04-22\",\n      \"startDate\": \"2025-04-01\",\n      \"campaignType\": \"all\",\n      \"clickAttributionWindow\": \"none\",\n      \"dimensions\": [\n        \"campaignName\",\n        \"campaignId\",\n\t\t\t\t\"mediaType\"\n      ],\n      \"format\": \"csv\",\n      \"id\": \"1234\",\n      \"metrics\": [\n        \"impressions\",\n        \"clicks\",\n        \"winRate\"\n      ],\n      \"reportType\": \"summary\",\n      \"salesChannel\": \"all\",\n\t\t\t\"mediaType\": \"all\"\n      \"timezone\": \"UTC\",\n      \"viewAttributionWindow\": \"none\"\n    },\n    \"type\": \"AsyncCampaignsReportRequest\"\n  }\n}");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

$response = curl_exec($ch);

curl_close($ch);

Sample Request with clickMatchLevel and viewMatchLevel Attributes

ForRevenue Report:

curl --location 'https://api.criteo.com/2025-07/retail-media/reports/revenue' \
--header 'Content-Type: application/json' \
--header 'Accept: text/plain' \
--header 'Authorization: ••••••' \
--data '{
  "data": {
    "attributes": {
      "endDate": "2025-03-31",
      "startDate": "2025-03-01",
      "accountIds": [
        "1234"
      ],
      "advertiserTypes": [
        "brand",
        "seller"
      ],
      "buyType": "auction",
      "campaignIds": [
        "123"
      ],
      "campaignType": "all",
      "clickAttributionWindow": "none",
      "clickMatchLevel": "campaign",
      "dimensions": [
        "retailerCategoryName",
        "brandId"
      ],
      "format": "json",
      "id": "1234567890",
      "lineItemIds": [
        "12345"
      ],
      "metrics": [
        "impressions",
        "roas"
      ],
      "retailerIds": [
        "111"
      ],
      "revenueType": "auction",
      "salesChannel": "all",
      "skuRelations": [
        "sameBrand",
        "sameCategory"
      ],
      "soldBy": "directSold",
      "timezone": "UTC",
      "viewAttributionWindow": "none",
      "viewMatchLevel": "campaign"
    },
    "type": "RevenueReportRequest"
  }
}'
import http.client

conn = http.client.HTTPSConnection('api.criteo.com')
headers = {
    'Content-Type': 'application/json',
    'Accept': 'text/plain',
    'Authorization': 'Bearer ****',
}
conn.request(
    'POST',
    '/2025-07/retail-media/reports/campaigns',
    '{\n  "data": {\n    "attributes": {\n      "endDate": "2025-04-22",\n      "startDate": "2025-04-01",\n      "campaignType": "all",\n      "clickAttributionWindow": "none",\n      "dimensions": [\n        "campaignName",\n        "campaignId",\n\t\t\t\t"mediaType"\n      ],\n      "format": "csv",\n      "id": "1234",\n      "metrics": [\n        "impressions",\n        "clicks",\n        "winRate"\n      ],\n      "reportType": "summary",\n      "salesChannel": "all",\n\t\t\t"mediaType": "all"\n      "timezone": "UTC",\n      "viewAttributionWindow": "none"\n    },\n    "type": "AsyncCampaignsReportRequest"\n  }\n}',
    headers
)
response = conn.getresponse()
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.criteo.com/2025-07/retail-media/reports/revenue"))
    .POST(BodyPublishers.ofString("{\n  \"data\": {\n    \"attributes\": {\n      \"endDate\": \"2025-03-31\",\n      \"startDate\": \"2025-03-01\",\n      \"accountIds\": [\n        \"1234\"\n      ],\n      \"advertiserTypes\": [\n        \"brand\",\n        \"seller\"\n      ],\n      \"buyType\": \"auction\",\n      \"campaignIds\": [\n        \"123\"\n      ],\n      \"campaignType\": \"all\",\n      \"clickAttributionWindow\": \"none\",\n      \"clickMatchLevel\": \"campaign\",\n      \"dimensions\": [\n        \"retailerCategoryName\",\n        \"brandId\"\n      ],\n      \"format\": \"json\",\n      \"id\": \"1234567890\",\n      \"lineItemIds\": [\n        \"12345\"\n      ],\n      \"metrics\": [\n        \"impressions\",\n        \"roas\"\n      ],\n      \"retailerIds\": [\n        \"111\"\n      ],\n      \"revenueType\": \"auction\",\n      \"salesChannel\": \"all\",\n      \"skuRelations\": [\n        \"sameBrand\",\n        \"sameCategory\"\n      ],\n      \"soldBy\": \"directSold\",\n      \"timezone\": \"UTC\",\n      \"viewAttributionWindow\": \"none\",\n      \"viewMatchLevel\": \"campaign\"\n    },\n    \"type\": \"RevenueReportRequest\"\n  }\n}"))
    .setHeader("Content-Type", "application/json")
    .setHeader("Accept", "text/plain")
    .setHeader("Authorization", "••••••")
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.criteo.com/2025-07/retail-media/reports/revenue');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: text/plain',
    "Authorization: ••••••",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\n  \"data\": {\n    \"attributes\": {\n      \"endDate\": \"2025-03-31\",\n      \"startDate\": \"2025-03-01\",\n      \"accountIds\": [\n        \"1234\"\n      ],\n      \"advertiserTypes\": [\n        \"brand\",\n        \"seller\"\n      ],\n      \"buyType\": \"auction\",\n      \"campaignIds\": [\n        \"123\"\n      ],\n      \"campaignType\": \"all\",\n      \"clickAttributionWindow\": \"none\",\n      \"clickMatchLevel\": \"campaign\",\n      \"dimensions\": [\n        \"retailerCategoryName\",\n        \"brandId\"\n      ],\n      \"format\": \"json\",\n      \"id\": \"1234567890\",\n      \"lineItemIds\": [\n        \"12345\"\n      ],\n      \"metrics\": [\n        \"impressions\",\n        \"roas\"\n      ],\n      \"retailerIds\": [\n        \"111\"\n      ],\n      \"revenueType\": \"auction\",\n      \"salesChannel\": \"all\",\n      \"skuRelations\": [\n        \"sameBrand\",\n        \"sameCategory\"\n      ],\n      \"soldBy\": \"directSold\",\n      \"timezone\": \"UTC\",\n      \"viewAttributionWindow\": \"none\",\n      \"viewMatchLevel\": \"campaign\"\n    },\n    \"type\": \"RevenueReportRequest\"\n  }\n}");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

$response = curl_exec($ch);

curl_close($ch);