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:
Verb | Endpoint | Description |
---|---|---|
GET | /retail-media/accounts/:account-id/keywords/in-review-report | Generate 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/review | Update 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 areinReview
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:
Verb | Endpoint | Description |
---|---|---|
POST | /accounts/{accountId}/brand-catalog-export | Create a request to export existing catalogs from a Brand account |
POST | /accounts/{accountId}/seller-catalog-export | Create a request to export existing catalogs from a Seller account |
GET | /catalogs/{catalogId}/status | Retrieve the status of a specific catalog request. |
GET | /catalogs/{catalogId}/output | Download 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:
Verb | Endpoint | Description |
---|---|---|
POST | /brands/search | Search 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:
Verb | Endpoint | Description |
---|---|---|
POST | /billing/partner-report | Request a partner billing report creation |
GET | /billing/partner-report/{reportId}/status | Get status of a specific report |
GET | /billing/partner-report/{reportId}/output | Download 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:
Verb | Endpoint | Description |
---|---|---|
POST | /reports/campaigns | Create a Campaign Report Request |
POST | /reports/line-items | Create a Line Item Report Request |
POST | /reports/revenue | Create a Revenue Report Request |
Sample Request with mediaType
Attribute & Dimension
mediaType
Attribute & DimensionFor 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
clickMatchLevel
and viewMatchLevel
AttributesForRevenue 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);