Version 2025.10 Release Notes
Version
2025.10of the Criteo Retail Media API is live as of October 21st, 2025 and will be supported until October 27th, 2026. A new Postman collection for2025.10is also available in the Criteo Postman workspace.
New SDK ReleaseA new SDK version will be available for the
2025.10release.
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.10 are:
- a new base URL,
- updated API Troubleshooting Guides,
- updates to Authorization Code application rate limiting,
- updates to endpoints according to Retailer Configuration,
- new endpoints in that of recommend keywords & categories that support Sponsored Products & Display,
- new endpoints for Category Search to increase efficiency,
- new Account Fees endpoints to support Retailers,
- an update to the keyword bid endpoint,
- updates to the Reporting Cache, Report Types, & dimensions within the analytics endpoints, and
- changes coming to the catalog endpoints in 2026.
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-07/retail-media/{endpoint}to the new base URL:
https://api.criteo.com/2025-10/retail-media/{endpoint}What's New
API Troubleshooting Guides
We’re pleased to introduce a new set of API Troubleshooting resources designed to help you efficiently identify and resolve API-related issues. The following pages offer detailed guidance and descriptions:
- The Troubleshooting Guide offers users a concise, structured approach to diagnosing API issues by walking through common error scenarios and checks (e.g. connectivity, request format, server vs client).
- The Escalation Guidelines aims to guide users on when and how to escalate API issues to Criteo—defining the thresholds, required information, and escalation paths to streamline support.
- The API Error Codes page explains the various API error codes that developers might encounter—providing both the numeric/identifier codes and descriptive messages. It helps developers interpret responses from the API accurately and take the appropriate corrective action.
Authorization Code Rate Limiting
We've introduced an updated logic to rate limiting on Authorization Code applications, which focuses on the below:
- The new capability is Auto Scaling, and this capability is exclusively for Auth Code apps, not Client Credentials.
- Accounts will have a rate limit of 10 calls per minute per account. The number of accounts consented to is also taken into account, which means that the rate limit can increase according to the amount of accounts a single consent granter gave an application consent to. For example:
- Bob consented to account 1,2,3 -> the app can call "in the name of Bob" at max rate of 3*10=30calls/min
- Bob would have the ability to use all 30 calls on a single account, but that would impact their ability to call other accounts.
- Alice consented to account 4 but Jen consented to account 5 -> the app can call "in the name of Alice" at a max rate of 1_10=10 calls/min and can call "in the name of Jen" at a max rate of 1_10=10 calls/min.
- Bob consented to account 1,2,3 -> the app can call "in the name of Bob" at max rate of 3*10=30calls/min
- Consent granters and application owners are encouraged to have similar consenters grant consent to accounts to scale the rate limit according to the operations expected on the accounts.
You can find the documentation for the update to Authorization Code rate limits here.
Retailer Configuration Updates
We've introduced an updated logic to the governance layer that determines which parts of a retailer’s inventory (campaign types such as Sponsored Products and buy types such as Auction) are accessible through different demand entry points. This means that in the event that a retailer opts out of receiving demand from Commerce Max, the following will take place:
- The ability to run create or edit operations will be impacted, and a validation error can be expected should a retailer opt out of receiving Commerce Max demand.
- The ability to run read only operations will remain unimpacted, as there may be line items that are existing against retailer inventory that may need to be accessed. Users who want to fetch information against impacted campaigns/line items can expect to still be able to access information associated to these campaigns/line items and still pull reporting for them as well.
Recommended Keywords
In version 2025.10, we've introduced new endpoints that are used by advertisers & retailers to fetch recommended keywords that are desired to be used for targeting on retailer inventory.
You may be wondering how this is different from the /retail-media/line-items/:externalLineItemId/keywords/recommended and it would be a fair question. The key difference is that the endpoint referenced only indicates recommended keywords after they have bee added to a line item. In the new iteration, advertisers & retailers will have the ability to input product IDs, and the endpoint will analyze your products and return the top 100 keywords that your Sponsored Product and/or Onsite Display line items would serve on when shoppers search for related terms.
This means that you will have the ability to preview what the targeting would be before a product is added to a line item. This data-driven approach ensures your campaigns target the most effective keywords based on actual search behavior and product relevance.
You can find the documentation for the Recommended Keywords endpoint here.
Updated Endpoints
The following new endpoint can be found below:
| Verb | Endpoint | Description |
|---|---|---|
| POST | /retail-media/retailers/:retailerId/recommend-keywords | Gets the top 100 recommended keywords for specified products |
Sample Request
For /retail-media/retailers/:retailerId/recommend-keywords:
curl -L -X POST "https://api.criteo.com/2025-10/retail-media/retailers/{retailerId}/recommend-keywords" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"import requests
headers = {
'Authorization': 'Bearer <MY_ACCESS_TOKEN>',
}
response = requests.post(
'https://api.criteo.com/preview/retail-media/retailers/{retailerId}/recommend-keywords',
headers=headers,
)<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.criteo.com/preview/retail-media/retailers/{retailerId}/recommend-keywords');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer <MY_ACCESS_TOKEN>',
]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
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/preview/retail-media/retailers/{retailerId}/recommend-keywords"))
.GET()
.setHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());Sample Response
For /retail-media/retailers/:retailerId/recommend-keywords:
{
"data": {
"type": "RecommendedKeywordsResponseV1",
"attributes": {
"recommendedKeywords": [
"keyword 1",
"keyword 2",
"keyword 3",
"keyword 4",
"keyword 5"
]
}
},
"warnings": [],
"errors": []
}Recommended Categories
In version 2025.10, we've introduced new endpoints that are used by advertisers & retailers to fetch recommended categories that are desired to be used for targeting on retailer inventory.
The Recommended Categories endpoint helps you discover the most relevant product categories for your advertising campaigns by leveraging a retailer's taxonomy structure. This endpoint analyzes your specified products and returns up to 50 recommended categories that align with where your products naturally fit within the retailer's inventory organization.
You can find the documentation for the Recommended Categories endpoint here.
Updated Endpoints
The following new endpoint can be found below:
| Verb | Endpoint | Description |
|---|---|---|
| POST | /retail-media/retailers/:retailerId/recommend-categories | Gets the top 50 recommended categories for specified products |
Sample Request
For retail-media/retailers/:retailerId/recommend-categories:
curl -L -X POST "https://api.criteo.com/2025-10/retail-media/retailers/{retailerId}/recommend-categories" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"import requests
headers = {
'Authorization': 'Bearer <MY_ACCESS_TOKEN>',
}
response = requests.post('https://api.criteo.com/preview/retail-media/retailers/100/recommend-categories', headers=headers)<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.criteo.com/preview/retail-media/retailers/100/recommend-categories');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer <MY_ACCESS_TOKEN>',
]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
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/preview/retail-media/retailers/100/recommend-categories"))
.GET()
.setHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());Sample Response
For retail-media/retailers/:retailerId/recommend-categories:
{
"data": [
{
"id": "12345",
"type": "CategoryV1",
"attributes": {
"text": "taxonmy 1|taxonomy 2|taxobnomy 3",
"name": "taxonomy 3",
"parentId": "12"
}
},
{
"id": "67890",
"type": "CategoryV1",
"attributes": {
"text": "taxonmy 1|taxonomy 2|taxobnomy 3",
"name": "taxonomy 3",
"parentId": "12"
}
}
}
],
"warnings": [],
"errors": []
}Category Search
In version 2025.10, we've introduced new Category Search endpoint enables you to explore and discover available product categories within a retailer's hierarchical taxonomy structure.
This endpoint provides the ability to see what categories are available to serve against a retailer's inventory, making it an essential tool for understanding targeting options and campaign planning. Unlike recommendation endpoints, Category Search allows you to actively explore the retailer's category structure through flexible search parameters.
You can find the Category Search endpoint documentation here.
Updated Endpoints
The following new endpoint can be found below:
| Verb | Endpoint | Description |
|---|---|---|
| POST | /retail-media/retailers/:retailerId/categories/search | Searches for available categories within a retailer's taxonomy |
Sample Request
For /retail-media/retailers/:retailerId/categories/search:
curl -L -X POST "https://api.criteo.com/2025-10/retail-media/retailers/{retailerId}/categories/search?limit=50&offset=0" \
-H "Authorization: Bearer <MY_ACCESS_TOKEN>"import requests
headers = {
'Authorization': 'Bearer <MY_ACCESS_TOKEN>',
}
params = {
'limit': '50',
'offset': '0',
}
response = requests.post(
'https://api.criteo.com/2025-10/retail-media/retailers/{retailerId}/categories/search',
params=params,
headers=headers,
)<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.criteo.com/2025-10/retail-media/retailers/{retailerId}/categories/search?limit=50&offset=0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer <MY_ACCESS_TOKEN>',
]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
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-10/retail-media/retailers/{retailerId}/categories/search?limit=50&offset=0"))
.POST(HttpRequest.BodyPublishers.noBody())
.setHeader("Authorization", "Bearer <MY_ACCESS_TOKEN>")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());Sample Response
For /retail-media/retailers/:retailerId/categories/search:
{
"metadata": {
"count": 2,
"offset": 0,
"limit": 50
},
"data": [
{
"id": "12345",
"type": "CategoryV1",
"attributes": {
"text": "taxonmy 1|taxonomy 2|taxobnomy 3",
"name": "taxobnomy 3",
"parentId": "12"
}
},
{
"id": "67890",
"type": "CategoryV1",
"attributes": {
"text": "taxonmy 1|taxonomy 2|taxobnomy 3",
"name": "taxobnomy 3",
"parentId": "12"
}
}
}
],
"warnings": [],
"errors": []
}NOTE
The addition of the Category Search endpoints will prompt the removal of some existing endpoints in this stable version release as well as future versions due to redundancy since the new endpoint achieves what the below endpoints aim to accomplish:
Endpoints to be removed:
| Verb | Endpoint | Description |
|---|---|---|
| GET | /retail-media/categories/:categoryId | Get categories of the retailer by specific category Id |
| GET | /retail-media/categories | Get all categories of the retailer |
Account Fees
In version 2025.10, we've introduced new account fees endpoints that offer Private Marketplace retailers the ability to search and manage fees for one of more accounts.
You can find the Account Fees endpoint documentation here.
Updated Endpoints Includes
The following new catalog endpoint can be found below:
| Verb | Endpoint | Description |
|---|---|---|
| POST | /retail-media/accounts/fees/search | This endpoint allows users to retrieve fee settings for one or more accounts they have access to. |
| POST | /retail-media/accounts/fees/update | This endpoint allows Private Market retailers to update fees for child seller or demand accounts. |
Sample Request
For Account Fees Search:
curl --location 'https://api.criteo.com/2025-10/retail-media/accounts/fees/search?limit=50&offset=0' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: ••••••' \
--data '{
"data": {
"attributes": {
"accountIds": [
"123",
"456"
]
},
"type": "AccountFeesSearchRequest"
}
}'import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': '••••••',
}
params = {
'limit': '50',
'offset': '0',
}
json_data = {
'data': {
'attributes': {
'accountIds': [
'123',
'456',
],
},
'type': 'AccountFeesSearchRequest',
},
}
response = requests.post(
'https://api.criteo.com/2025-10/retail-media/accounts/fees/search',
params=params,
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-10/retail-media/accounts/fees/search?limit=50&offset=0"))
.POST(BodyPublishers.ofString("{\n \"data\": {\n \"attributes\": {\n \"accountIds\": [\n \"123\",\n \"456\"\n ]\n },\n \"type\": \"AccountFeesSearchRequest\"\n }\n}"))
.setHeader("Content-Type", "application/json")
.setHeader("Accept", "application/json")
.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-10/retail-media/accounts/fees/search?limit=50&offset=0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json',
"Authorization: ••••••",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\n \"data\": {\n \"attributes\": {\n \"accountIds\": [\n \"123\",\n \"456\"\n ]\n },\n \"type\": \"AccountFeesSearchRequest\"\n }\n}");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);Sample Response
For Account Fees Search:
{
"metadata": {
"count": 2,
"offset": 0,
"limit": 50
},
"data": [
{
"type": "PrivateMarketAccountFees",
"attributes": {
"accountId": "123",
"fees": {
"demandManaged": {
"rate": 0.01
},
"managedService": {
"rate": 0.01,
"onsiteSponsoredProductsEnabled": true,
"onsiteDisplayEnabled": true
}
}
}
},
{
"type": "PrivateMarketAccountFees",
"attributes": {
"accountId": "456",
"fees": {
"demandManaged": {
"rate": 0.00
},
"managedService": {
"rate": 0.00,
"onsiteSponsoredProductsEnabled": false,
"onsiteDisplayEnabled": false
}
}
}
}
],
"warnings": [],
"errors": []
}Sample Request
For Updating Account Fees:
curl --location 'https://api.criteo.com/2025-10/retail-media/accounts/fees/update' \
--header 'Content-Type: application/json' \
--header 'Authorization: ••••••' \
--data '{
"data": {
"attributes": {
"accountIds": [
"123"
],
"fees": {
"demandManaged": {
"rate": "0.1"
},
"managedService": {
"onsiteDisplayEnabled": "true",
"onsiteSponsoredProductsEnabled": "true",
"rate": "0.1"
}
}
},
"type": "AccountFeesUpdateRequest"
}
}'import requests
headers = {
'Content-Type': 'application/json',
'Authorization': '••••••',
}
json_data = {
'data': {
'attributes': {
'accountIds': [
'123',
],
'fees': {
'demandManaged': {
'rate': '0.1',
},
'managedService': {
'onsiteDisplayEnabled': 'true',
'onsiteSponsoredProductsEnabled': 'true',
'rate': '0.1',
},
},
},
'type': 'AccountFeesUpdateRequest',
},
}
response = requests.post('https://api.criteo.com/2025-10/retail-media/accounts/fees/update', 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-10/retail-media/accounts/fees/update"))
.POST(BodyPublishers.ofString("{\n \"data\": {\n \"attributes\": {\n \"accountIds\": [\n \"123\"\n ],\n \"fees\": {\n \"demandManaged\": {\n \"rate\": \"0.1\"\n },\n \"managedService\": {\n \"onsiteDisplayEnabled\": \"true\",\n \"onsiteSponsoredProductsEnabled\": \"true\",\n \"rate\": \"0.1\"\n }\n }\n },\n \"type\": \"AccountFeesUpdateRequest\"\n }\n}"))
.setHeader("Content-Type", "application/json")
.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-10/retail-media/accounts/fees/update');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
"Authorization: ••••••",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\n \"data\": {\n \"attributes\": {\n \"accountIds\": [\n \"123\"\n ],\n \"fees\": {\n \"demandManaged\": {\n \"rate\": \"0.1\"\n },\n \"managedService\": {\n \"onsiteDisplayEnabled\": \"true\",\n \"onsiteSponsoredProductsEnabled\": \"true\",\n \"rate\": \"0.1\"\n }\n }\n },\n \"type\": \"AccountFeesUpdateRequest\"\n }\n}");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
curl_close($ch);Sample Response
For Updating Account Fees:
NOTE
A successful response on the
Update Account Feesendpoint will result in an empty204response.
Keyword Bid Endpoint Update
In version 2025.10, we have made updates to our keyword bidding endpoints to enhance the keyword targeting experience.
Originally, keyword bid overrides used to only be able to be applied to manually targeted keywords. Now, users will have the ability to apply keyword bid overrides on not only manually targeted keywords but also automatically targeted keywords that have been derived from our keyword relevancy model. The functionality of the impacted endpoints remains the same, the difference will be that when you attempt to apply a keyword bid to an automatically targeted keyword, you will now receive a successful response.
You can find the Keyword Bid endpoint documentation here.
Updated Endpoints
See below for the impacted endpoints:
Impacted Endpoint:
| Verb | Endpoint | Description |
|---|---|---|
| POST | /retail-media/line-items/{lineItemId}/keywords/set-bid | Set a bid override at keyword level |
New Reporting Dimensions & Filters
In version 2025.10, we've introduced updates to the Reporting cache as well as updates to existing Report Types within the analytics endpoints.
The reporting cache behavior has been improved to take steps towards enhancing performance and consistency:
- While reports with an end date equal to the current date have been cached for 1 hour,
- Reports with an end date earlier than the current date are cached for 24 hours.
This update ensures faster response times for commonly requested reports while maintaining data accuracy for current-date reporting.
The updated analytics endpoints provide users with deeper, more comprehensive insights, enabling them to explore data more effectively. Additionally, the enhancements to the 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, there have been updates to the capout report type. Now, the capoutMissedTraffic dimension has had it's calculation updated to align with the support of the release of the Adaptive CPC launch in Preview. It is now defined as the percent of traffic events that the advertiser did not participate in throughout the day, weighted based on the number of traffic events throughout the day.
You also now have the flexibility to generate reporting with a focus on the advertised Product Category dimension to more precisely identify the category the advertised product is associated to.
Lastly, we have added new dimensions to the Attributed Transactions report. The following dimensions can now be found when calling for the reportType:
| Key-Values | Description |
|---|---|
saleSellerId | The ID of the seller responsible for the sale |
saleSellerName | The name of the seller responsible for the sale |
activitySellerId | The ID of the seller responsible for the advertising event |
activitySellerName | The name of the seller responsible for the advertising event |
These Report Types & dimensions are available across the DSP endpoints.
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 | /retail-media/reports/campaigns | Create a Campaign Report Request |
| POST | /reports/line-items | Create a Line Item Report Request |
Updates To Catalog Endpoints in 2026
With the release of the Catalog Export endpoints in version 2025-07, we want to provide an early announcement that older versions of the catalog endpoints will no longer be released in stable versions scheduled for release after the second half of 2026.
This change reflects our commitment to providing a more flexible and user-friendly API experience. The new endpoint versions offer enhanced functionality and usability, making the older versions redundant.
See below for the impacted endpoints:
Impacted Endpoints (in 2H 2026):
| Verb | Endpoint | Description |
|---|---|---|
| POST | /retail-media/accounts/:accountId/catalogs | Create a catalog request to generate a new catalog for Brand account |
| POST | /retail-media/accounts/:accountId/catalogs/sellers | Create a catalog request to generate a new catalog for Seller account |
We ask that you begin migration to the below endpoints:
| 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 |