> ## Documentation Index
> Fetch the complete documentation index at: https://developers.criteo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Change History

> Retrieve a paginated log of configuration changes to campaigns and line items within an account or retailer.

> [!NOTE]
>
> This endpoint is available in the **Experimental** version of the Retail Media API only.
> Experimental endpoints may change without prior notice. See the [versioning policy](https://developers.criteo.com/criteo-apis/docs/versioning-policy.md) for details.

## Overview

The change history endpoints return a time-ordered log of configuration changes made to Retail Media objects — campaigns, line items, and related entities. Each entry records what changed, on which entity, when it occurred, and the role of the actor who made the change.

Two scopes are available: account-level (demand side) and retailer-level (supply side). Changes are returned in descending order by time. Only changes the caller has access to are returned; inaccessible entries are silently omitted.

## Prerequisites

* **Authentication**: a valid access token. See [Authentication](https://developers.criteo.com/retail-media/experimental/docs/authentication).
* **App permissions**: the `RetailMedia_Campaign_Read` scope must be enabled on your app. See [App Scopes](https://developers.criteo.com/retail-media/experimental/docs/app-scopes.md).
* **Account or retailer access**: the authenticated app must have access to the requested account or retailer. A `403` is returned for unknown or inaccessible identifiers.

## Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/accounts/{account-id}/change-history-entries` | List configuration changes within an account. |
| `GET` | `/retailers/{retailer-id}/change-history-entries` | List configuration changes within a retailer. |

***

## Get Change History Entries

GET

```http theme={null}
https://api.criteo.com/experimental/retail-media/accounts/{account-id}/change-history-entries
```

### Path Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `account-id` | string | Yes | Identifier of the advertiser account whose change history is requested. |

### Query Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `campaign-ids` | array\[string] | No | Filter to changes on these campaigns. Campaigns the caller cannot access are silently excluded. |
| `line-item-ids` | array\[string] | No | Filter to changes on these line items. Line items the caller cannot access are silently excluded. |
| `entity-types` | array\[string] | No | Filter to these entity types. Unknown values match no entries and do not error. |
| `event-types` | array\[string] | No | Filter to these event types. Unknown values match no entries and do not error. |
| `start-time` | string (ISO 8601) | No | Inclusive lower bound on change timestamp. Defaults to 7 days before the request time. |
| `end-time` | string (ISO 8601) | No | Inclusive upper bound on change timestamp. Defaults to the request time. |
| `limit` | integer | No | Maximum number of entries per page. Between `1` and `100`. Default: `25`. |
| `offset` | integer | No | Zero-based starting position. Default: `0`. `offset + limit` must not exceed `10,000`. Narrow the time range to retrieve more history. |

Array parameters use repeated query keys. For example: `event-types=lineItemCreated&event-types=lineItemUpdated`. A comma-separated list is treated as a single value and may silently return no results.

### Response Attributes

Each `data[]` item has a `type` field (`ChangeHistoryEntryResponse`) and an `attributes` object:

| Attribute | Type | Description |
| - | - | - |
| `occurredAt` | string (ISO 8601) | When the change was recorded. Results are sorted descending by this field. |
| `eventType` | string | Type of event that produced the change (e.g. `lineItemCreated`, `lineItemUpdated`). The set of values is extensible. |
| `actorRole` | string | Role of the actor who made the change. One of: `unknown`, `internal`, `external`, `api`, `automatedTask`. User identifiers are not returned. |
| `entity.id` | string | Identifier of the changed entity. |
| `entity.type` | string | Type of the changed entity (e.g. `lineItem`, `campaign`). The set of values is extensible. |
| `entity.campaignId` | string or null | Identifier of the parent campaign, when applicable. |
| `changes[]` | array | List of field-level changes. |
| `changes[].field` | string | Name of the field that changed. |
| `changes[].previousValue` | string or null | Value before the change. Null for newly created fields. |
| `changes[].newValue` | string or null | Value after the change. Null for deleted fields. |

Pagination metadata is returned in the `meta` object:

| Field | Type | Description |
| - | - | - |
| `offset` | integer | Starting position echoed from the request. |
| `limit` | integer | Page size echoed from the request. |
| `count` | integer | Total number of entries across all pages. The number of entries on the current page is `data.length`. |

**Sample Request**

```bash theme={null}
curl -L -X GET 'https://api.criteo.com/experimental/retail-media/accounts/{account-id}/change-history-entries?start-time=2026-10-01T00:00:00Z&end-time=2026-10-15T00:00:00Z&limit=25&offset=0' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <MY_ACCESS_TOKEN>'
```

**Sample Response** — `200 OK`

```json theme={null}
{
  "data": [
    {
      "id": "abc123",
      "attributes": {
        "occurredAt": "2026-10-14T09:32:11Z",
        "eventType": "lineItemUpdated",
        "actorRole": "api",
        "entity": {
          "id": "112233445566778899",
          "type": "lineItem",
          "campaignId": "987654321"
        },
        "changes": [
          {
            "field": "isPaused",
            "previousValue": "false",
            "newValue": "true"
          }
        ]
      }
    }
  ],
  "meta": {
    "offset": 0,
    "limit": 25,
    "count": 1
  },
  "errors": [],
  "warnings": []
}
```

***

## Get Change History Entries (Retailer)

GET

```http theme={null}
https://api.criteo.com/experimental/retail-media/retailers/{retailer-id}/change-history-entries
```

### Path Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `retailer-id` | string | Yes | Identifier of the retailer whose change history is requested. |

### Query Parameters

Same as the [account endpoint](#get-change-history-entries) above.

### Response Attributes

Same shape as the [account endpoint](#get-change-history-entries) above.

> [!NOTE]
>
> Campaign-level changes are not returned by this endpoint — only line-item and other retailer-scoped entity changes are included. This applies to both onsite and offsite campaign changes.

**Sample Request**

```bash theme={null}
curl -L -X GET 'https://api.criteo.com/experimental/retail-media/retailers/{retailer-id}/change-history-entries?start-time=2026-10-01T00:00:00Z&end-time=2026-10-15T00:00:00Z&limit=25&offset=0' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <MY_ACCESS_TOKEN>'
```

**Sample Response** — `200 OK`

```json theme={null}
{
  "data": [
    {
      "id": "def456",
      "attributes": {
        "occurredAt": "2026-10-13T14:05:22Z",
        "eventType": "lineItemUpdated",
        "actorRole": "internal",
        "entity": {
          "id": "556677889900112233",
          "type": "lineItem",
          "campaignId": "123456789"
        },
        "changes": [
          {
            "field": "budget",
            "previousValue": "500.00",
            "newValue": "750.00"
          }
        ]
      }
    }
  ],
  "meta": {
    "offset": 0,
    "limit": 25,
    "count": 1
  },
  "errors": [],
  "warnings": []
}
```

***

## Known Limitations

* The default time window is the last 7 days. There is no documented maximum lookback period.
* User identifiers are not returned — only the actor's role (`api`, `internal`, etc.).
* The order of entries with identical `occurredAt` timestamps is not defined.
* `entity-types` and `event-types` enum values are not yet published in the spec. Unknown values are accepted but match no entries.

## Error Codes

| HTTP Status | `errors[].code` | `errors[].type` | When it occurs |
| - | - | - | - |
| `400` | `model-validation-error` | `validation` | Malformed dates or non-integer/out-of-range pagination parameters. `limit` must be 1–100 and `offset` must be nonnegative. |
| `400` | `invalid-time-range` | `validation` | The effective `start-time` is later than `end-time`, including when one bound uses its default. |
| `400` | `invalid-pagination` | `validation` | `offset + limit` exceeds 10,000. Narrow the time range to retrieve more history. |
| `401` | `authorization-token-invalid` or `authorization-token-expired` | `authorization` | Missing, invalid, or expired bearer token. |
| `403` | `missing-scope` | `authorization` | The app lacks `RetailMedia_Campaign_Read`. |
| `403` | `not-authorized` | `access-control` | The requested account or retailer is unknown or inaccessible. These cases are intentionally indistinguishable. |
| `429` | — | — | Request rate limit exceeded. |

Unknown `event-types` or `entity-types` values are not validation errors — they match no entries and return `200` with an empty result.
