Change History

Change History is an Audit Log feature that tracks creations, deletions, and updates of resources on commercetools Composable Commerce.

Change History provides a historical view into your Project’s resource changes. Changes made against resources are stored along with the time of change, source of the change, and, if provided, the user who made the change. These eventually consistent changes can then be retrieved via the Change History API or via the Merchant Center.

The Audit Log tracks and stores resource changes made after 15 March 2021. The tracked changes are represented as Records containing a list of Changes that happened together. Changes have varying data representations depending on the type of change. These are documented in the change types documentation.

The default limits are:

  • tracks changes originating from within the Merchant Center only. (See the information box below.)
  • maximum of 100 000 Records stored.
  • maximum of 1 year retention of Records.

Extension of these limits is possible by contacting Support via the Support Portal. Such extension might be subject to a separate fee.

The API response data is based on the changes tracked and stored by Audit Log. The default Audit Log setting is to only track Merchant Center originated changes, and therefore any response data targeted at a source other than Merchant Center is an empty set.

Hosts

The Change History API has different hosts from the HTTP API. The Change History API is hosted at the following URLs:

RegionAPI URL
Europe (Google Cloud, Belgium)https://history.europe-west1.gcp.commercetools.com/
North America (Google Cloud, Iowa)https://history.us-central1.gcp.commercetools.com/
Australia (Google Cloud, Sydney)https://history.australia-southeast1.gcp.commercetools.com/

If documentation refers to https://history.{region}.commercetools.com, the {region} placeholder has to be replaced with the actual value.

The Change History API is available only in the Google Cloud Regions.

Representations

RecordPagedQueryResponse

Response to a query request for Record.

limit
Int

Number of results requested.

count
Int

Actual number of results returned.

total
Int

Total number of results matching the query. This number is an estimation and not strongly consistent.

offset
Int

Number of elements skipped.

results
Array of Record
Example: json
{
"limit" : 20,
"offset" : 0,
"count" : 1,
"total" : 0,
"results" : [ {
"version" : 2,
"previousVersion" : 1,
"type" : "ResourceUpdated",
"modifiedAt" : "2020-03-22T23:00:00.000Z",
"modifiedBy" : {
"isPlatformClient" : true,
"id" : "example_user_123",
"type" : "user",
"customer" : {
"id" : "test1",
"typeId" : "customer"
},
"anonymousId" : "",
"clientId" : ""
},
"resource" : {
"id" : "some_entity_id_123",
"typeId" : "product"
},
"label" : {
"value" : "some_label",
"type" : "StringLabel"
},
"previousLabel" : {
"value" : "some_label",
"type" : "StringLabel"
},
"withoutChanges" : false,
"stores" : [ {
"key" : "store-1",
"typeId" : "store"
} ],
"changes" : [ {
"change" : "setKey",
"previousValue" : "Key 1",
"nextValue" : "Key 2",
"type" : "SetKeyChange"
} ]
} ]
}

Record

The default maximum number of Records that can be stored is 100 000. The default maximum retention period of Records is 1 year.

A Record captures the differences in a resource between one version and the next. (Recall that the version number is not always incremented by one; see Optimistic Concurrency Control.)

version
Int

Version of the resource after the change.

previousVersion
Int

Version of the resource before the change.

type
String

Type of the change (creation, update or deletion).

Can be "ResourceUpdated", "ResourceCreated", or "ResourceDeleted"
modifiedBy

Information about the user or the API client who performed the change.

modifiedAt
String

Date and time when the change was made.

label
Label

Information that describes the resource after the change.

previousLabel
Label

Information that describes the resource before the change.

changes
Array of Change

Shows the differences in the resource between previousVersion and version. The value is not identical to the actual array of update actions sent and is not limited to update actions (see, for example, Optimistic Concurrency Control).

resource
Reference

Reference to the changed resource.

stores
Array of KeyReference

References to the Stores attached to the Change.

withoutChanges
Boolean

true if no change was detected. The version number of the resource can be increased even without any change in the resource.

Example: json
{
"version" : 2,
"previousVersion" : 1,
"type" : "ResourceUpdated",
"modifiedAt" : "2020-03-22T23:00:00.000Z",
"modifiedBy" : {
"isPlatformClient" : true,
"id" : "example_user_123",
"type" : "user",
"customer" : {
"id" : "test1",
"typeId" : "customer"
},
"anonymousId" : "",
"clientId" : ""
},
"resource" : {
"id" : "some_entity_id_123",
"typeId" : "product"
},
"label" : {
"value" : "some_label",
"type" : "StringLabel"
},
"previousLabel" : {
"value" : "some_label",
"type" : "StringLabel"
},
"withoutChanges" : false,
"stores" : [ ],
"changes" : [ {
"change" : "setKey",
"previousValue" : "Key 1",
"nextValue" : "Key 2",
"type" : "SetKeyChange"
} ]
}

ModifiedBy

Information about the user or the API client who performed the change. This is a variant of LastModifiedBy.

id
String

ID of the Merchant Center user who made the change. Present only if the change was made in the Merchant Center.

type
String

Indicates whether the change was made by a user or the API client with or without an External user ID.

Can be "user", or "external-user"
customer
Reference

Reference to the Customer who made the change. Present only if the change was made using a token from the Password Flow.

anonymousId
String

Present only if the change was made using a token from an Anonymous Session.

clientId
String

ID of the API Client that made the change. Present only if the change was made using an API Client.

isPlatformClient
Boolean

true if the change was made via Merchant Center or ImpEx.

Example: json
{
"isPlatformClient" : true,
"id" : "example_user_123",
"type" : "user",
"customer" : {
"id" : "test1",
"typeId" : "customer"
},
"anonymousId" : "",
"clientId" : ""
}

ChangeHistoryResourceType

Represents the supported resource types. The value must be one of the following:

Label

Labels provide human readable descriptive information specific to the change.

CustomerLabel

type
String
"CustomerLabel"
firstName
String
lastName
String
customerNumber
String

CustomObjectLabel

key
String
type
String
"CustomObjectLabel"
container
String

LocalizedLabel

type
String
"LocalizedLabel"
value
LocalizedString

OrderLabel

type
String
"OrderLabel"
customerEmail
String
orderNumber
String

PaymentLabel

key
String
type
String
"PaymentLabel"
amountPlanned
Money

ProductLabel

type
String
"ProductLabel"
slug
LocalizedString
name
LocalizedString

QuoteRequestLabel

key
String
type
String
"QuoteRequestLabel"
customer
Reference

QuoteLabel

key
String
type
String
"QuoteLabel"
customer
Reference
stagedQuote
Reference
quoteRequest
Reference

ReviewLabel

key
String
type
String
"ReviewLabel"
title
String

StagedQuoteLabel

key
String
type
String
"StagedQuoteLabel"
customer
Reference
quoteRequest
Reference

StringLabel

type
String
"StringLabel"
value
String

DateStringFilter

This type consists of one enum value:

now

PlatformInitiatedChange

excludeAll
changeLineItemName
changeReviewRatingStatistics
setApplicationVersion
setIsValid
setVariantAvailability

Query Records

Query Records

The view_audit_log:{projectKey} scope is always required in addition to the respective scopes for the resource type to query for.

GET
https://history.{region}.commercetools.com/{projectKey}
OAuth 2.0 Scopes:
view_audit_log:{projectKey}, view_cart_discounts:{projectKey}, view_categories:{projectKey}, view_customers:{projectKey}, view_customer_groups:{projectKey}, view_discount_codes:{projectKey}, view_key_value_documents:{projectKey}, view_orders:{projectKey}, view_orders:{projectKey}:{storeKey}, view_payments:{projectKey}, view_products:{projectKey}, view_product_selections:{projectKey}, view_quotes:{projectKey}, view_quote_requests:{projectKey}, view_shopping_lists:{projectKey}, view_states:{projectKey}, view_staged_quotes:{projectKey}, view_stores:{projectKey}, view_tax_categories:{projectKey}, view_types:{projectKey}
Path parameters:
region
String

The Region in which the project is hosted.

projectKey
String

key of the Project.

Query parameters:
expand
Boolean

If true, CustomFieldExpandedValue is made available.

limit
Int
offset
Int

Number of elements skipped.

resourceType

Can be used to filter for Records of specified resource types. By default, the API returns the Records of all supported resource types.

The parameter can be passed multiple times.
date.from
Number | datetime | DateStringFilter

Can be DateTime, non-negative integer, or "now". The non-negative integer represents the point in time in the past from now measured in hours. For example, 24 signifies 24 hours ago. The time range must be valid. Assigning date.from a time point later than date.to will fail with an error. The default value for date.from (resp., date.to) is 24 (resp., "now").

date.to
Number | datetime | DateStringFilter

See date.from.

userId
String

ID of the Merchant Center user who made the change. Can be used to query changes made by a Merchant Center user.

type
String

Can be "ResourceCreated", "ResourceUpdated", or "ResourceDeleted". Can be used to filter for a specific type of change.

clientId
String

ID of the API Client that made the change.

resourceId
String

ID of the changed resource.

source
String

Name of the source with which changes were made. Can be "MerchantCenter", "ImpEx", or "ApiClient".

changes
String

Restrict the types of Changes returned by passing the value of the change field. The values must belong to the resource type specified in the path parameter.

The parameter can be passed multiple times.
stores
String

key of the Store linked to the Change.

The parameter can be passed multiple times.
customerId
String

ID of the Customer who made the change using a token from the Password Flow.

excludePlatformInitiatedChanges

Exclude Changes initiated by background processes by passing the values of the change field. Only Changes of resource type product, product-discount, discount-code, and shopping-list can be filtered. Allowed values depend on resource types.

  • To filter Product Changes, excludeAll, changeReviewRatingStatistics, and setVariantAvailability can be passed.
  • To filter Product Discount Changes, excludeAll and setIsValid can be passed.
  • To filter Discount Code Changes, excludeAll and setApplicationVersion can be passed.
  • To filter Shopping List Changes, excludeAll and changeLineItemNamecan be passed.

excludeAll excludes all applicable changes.

The parameter can be passed multiple times.
Response:

200RecordPagedQueryResponse

Request Example:cURL
curl -X GET https://history.{region}.commercetools.com/{projectKey} -i \
--header 'Authorization: Bearer ${BEARER_TOKEN}'
200 Response Example: RecordPagedQueryResponsejson
{
"limit" : 20,
"offset" : 0,
"count" : 1,
"total" : 0,
"results" : [ {
"version" : 2,
"previousVersion" : 1,
"type" : "ResourceUpdated",
"modifiedAt" : "2020-03-22T23:00:00.000Z",
"modifiedBy" : {
"isPlatformClient" : true,
"id" : "example_user_123",
"type" : "user",
"customer" : {
"id" : "test1",
"typeId" : "customer"
},
"anonymousId" : "",
"clientId" : ""
},
"resource" : {
"id" : "some_entity_id_123",
"typeId" : "product"
},
"label" : {
"value" : "some_label",
"type" : "StringLabel"
},
"previousLabel" : {
"value" : "some_label",
"type" : "StringLabel"
},
"withoutChanges" : false,
"stores" : [ {
"key" : "store-1",
"typeId" : "store"
} ],
"changes" : [ {
"change" : "setKey",
"previousValue" : "Key 1",
"nextValue" : "Key 2",
"type" : "SetKeyChange"
} ]
} ]
}

Query Records for specific resource type

The view_audit_log:{projectKey} scope is always required in addition to the respective scopes for the resource type to query for.

GET
https://history.{region}.commercetools.com/{projectKey}/{resourceType}
OAuth 2.0 Scopes:
view_audit_log:{projectKey}, view_cart_discounts:{projectKey}, view_categories:{projectKey}, view_customers:{projectKey}, view_customer_groups:{projectKey}, view_discount_codes:{projectKey}, view_key_value_documents:{projectKey}, view_orders:{projectKey}, view_orders:{projectKey}:{storeKey}, view_payments:{projectKey}, view_products:{projectKey}, view_product_selections:{projectKey}, view_quotes:{projectKey}, view_quote_requests:{projectKey}, view_shopping_lists:{projectKey}, view_states:{projectKey}, view_staged_quotes:{projectKey}, view_stores:{projectKey}, view_tax_categories:{projectKey}, view_types:{projectKey}
Path parameters:
region
String

The Region in which the project is hosted.

projectKey
String

key of the Project.

resourceType
ChangeHistoryResourceType

Resource type for which a query is made.

Query parameters:
expand
Boolean

If true, CustomFieldExpandedValue is made available.

limit
Int
offset
Int

Number of elements skipped.

date.from
Number | datetime | DateStringFilter

Can be DateTime, non-negative integer, or "now". The non-negative integer represents the time point in the past in hours. For example, 24 signifies 24 hours ago. The time range must be valid. Assigning date.from a time point later than date.to will fail with an error. The default value for date.from (resp., date.to) is 24 (resp., "now").

date.to
Number | datetime | DateStringFilter

See date.from.

userId
String

ID of the Merchant Center user who made the change. Can be used to query changes made by a Merchant Center user.

type
String

Can be "ResourceCreated", "ResourceUpdated", or "ResourceDeleted". Can be used to filter for a specific type of change.

clientId
String

ID of the API Client that made the change.

resourceId
String

ID of the changed resource.

source
String

Name of the source with which changes were made. Can be "MerchantCenter", "ImpEx", or "ApiClient".

changes
String

Restrict the types of Changes returned by passing the value of the change field. The values must belong to the resource type specified in the path parameter.

The parameter can be passed multiple times.
stores
String

key of the Store linked to the Change.

The parameter can be passed multiple times.
customerId
String

ID of the Customer who made the change using a token from the Password Flow.

excludePlatformInitiatedChanges

Exclude Changes initiated by background processes by passing the values of the change field. Only Changes of resource type product, product-discount, discount-code, and shopping-list can be filtered. Allowed values depend on resource types.

  • To filter Product Changes, excludeAll, changeReviewRatingStatistics, and setVariantAvailability can be passed.
  • To filter Product Discount Changes, excludeAll and setIsValid can be passed.
  • To filter Discount Code Changes, excludeAll and setApplicationVersion can be passed.
  • To filter Shopping List Changes, excludeAll and changeLineItemNamecan be passed.

excludeAll excludes all applicable changes.

The parameter can be passed multiple times.
Response:

200RecordPagedQueryResponse

Request Example:cURL
curl -X GET https://history.{region}.commercetools.com/{projectKey}/{resourceType} -i \
--header 'Authorization: Bearer ${BEARER_TOKEN}'
200 Response Example: RecordPagedQueryResponsejson
{
"limit" : 20,
"offset" : 0,
"count" : 1,
"total" : 0,
"results" : [ {
"version" : 2,
"previousVersion" : 1,
"type" : "ResourceUpdated",
"modifiedAt" : "2020-03-22T23:00:00.000Z",
"modifiedBy" : {
"isPlatformClient" : true,
"id" : "example_user_123",
"type" : "user",
"customer" : {
"id" : "test1",
"typeId" : "customer"
},
"anonymousId" : "",
"clientId" : ""
},
"resource" : {
"id" : "some_entity_id_123",
"typeId" : "product"
},
"label" : {
"value" : "some_label",
"type" : "StringLabel"
},
"previousLabel" : {
"value" : "some_label",
"type" : "StringLabel"
},
"withoutChanges" : false,
"stores" : [ {
"key" : "store-1",
"typeId" : "store"
} ],
"changes" : [ {
"change" : "setKey",
"previousValue" : "Key 1",
"nextValue" : "Key 2",
"type" : "SetKeyChange"
} ]
} ]
}

Query Records by resource ID

The view_audit_log:{projectKey} scope is always required in addition to the respective scopes for the resource type to query for.

GET
https://history.{region}.commercetools.com/{projectKey}/{resourceType}/{id}
OAuth 2.0 Scopes:
view_audit_log:{projectKey}, view_cart_discounts:{projectKey}, view_orders:{projectKey}, view_orders:{projectKey}:{storeKey}, view_categories:{projectKey}, view_products:{projectKey}, view_customers:{projectKey}, view_customer_groups:{projectKey}, view_discount_codes:{projectKey}, view_key_value_documents:{projectKey}, view_payments:{projectKey}, view_product_selections:{projectKey}, view_quotes:{projectKey}, view_quote_requests:{projectKey}, view_shopping_lists:{projectKey}, view_states:{projectKey}, view_staged_quotes:{projectKey}, view_stores:{projectKey}, view_tax_categories:{projectKey}, view_types:{projectKey}
Path parameters:
region
String

The Region in which the project is hosted.

projectKey
String

key of the Project.

resourceType
ChangeHistoryResourceType

Resource type for which a query is made.

id
String

ID of the resource for which a query is made.

Query parameters:
expand
Boolean

If true, CustomFieldExpandedValue is made available.

limit
Int
offset
Int

Number of elements skipped.

date.from
Number | datetime | DateStringFilter

Can be DateTime, non-negative integer, or "now". The non-negative integer represents the time point in the past in hours. For example, 24 signifies 24 hours ago. The time range must be valid. Assigning date.from a time point later than date.to will fail with an error. The default value for date.from (resp., date.to) is 24 (resp., "now").

date.to
Number | datetime | DateStringFilter

See date.from.

userId
String

ID of the Merchant Center user who made the change. Can be used to query changes made by a Merchant Center user.

type
String

Can be "ResourceCreated", "ResourceUpdated", or "ResourceDeleted". Can be used to filter for a specific type of change.

clientId
String

ID of the API Client that made the change.

source
String

Name of the source with which changes were made. Can be "MerchantCenter", "ImpEx", or "ApiClient".

changes
String

Restrict the types of Changes returned by passing the value of the change field. The values must belong to the resource type specified in the path parameter.

The parameter can be passed multiple times.
stores
String

key of the Store linked to the Change.

The parameter can be passed multiple times.
customerId
String

ID of the Customer who made the change using a token from the Password Flow.

excludePlatformInitiatedChanges

Exclude Changes initiated by background processes by passing the values of the change field. Only Changes of resource type product, product-discount, discount-code, and shopping-list can be filtered. Allowed values depend on resource types.

  • To filter Product Changes, excludeAll, changeReviewRatingStatistics, and setVariantAvailability can be passed.
  • To filter Product Discount Changes, excludeAll and setIsValid can be passed.
  • To filter Discount Code Changes, excludeAll and setApplicationVersion can be passed.
  • To filter Shopping List Changes, excludeAll and changeLineItemNamecan be passed.

excludeAll excludes all applicable changes.

The parameter can be passed multiple times.
Response:

200RecordPagedQueryResponse

Request Example:cURL
curl -X GET https://history.{region}.commercetools.com/{projectKey}/{resourceType}/{id} -i \
--header 'Authorization: Bearer ${BEARER_TOKEN}'
200 Response Example: RecordPagedQueryResponsejson
{
"limit" : 20,
"offset" : 0,
"count" : 1,
"total" : 0,
"results" : [ {
"version" : 2,
"previousVersion" : 1,
"type" : "ResourceUpdated",
"modifiedAt" : "2020-03-22T23:00:00.000Z",
"modifiedBy" : {
"isPlatformClient" : true,
"id" : "example_user_123",
"type" : "user",
"customer" : {
"id" : "test1",
"typeId" : "customer"
},
"anonymousId" : "",
"clientId" : ""
},
"resource" : {
"id" : "some_entity_id_123",
"typeId" : "product"
},
"label" : {
"value" : "some_label",
"type" : "StringLabel"
},
"previousLabel" : {
"value" : "some_label",
"type" : "StringLabel"
},
"withoutChanges" : false,
"stores" : [ {
"key" : "store-1",
"typeId" : "store"
} ],
"changes" : [ {
"change" : "setKey",
"previousValue" : "Key 1",
"nextValue" : "Key 2",
"type" : "SetKeyChange"
} ]
} ]
}

Query Records via GraphQL

GraphQL endpoint

You can access the GraphQL endpoint with following URL:

https://history.{region}.commercetools.com/{projectKey}/graphql

The endpoint accepts HTTP POST requests with following fields in a JSON body:

  • query - String - GraphQL query as a string
  • variables - Object - Optional - containing JSON object that defines variables for your query
  • operationName - String - Optional - the name of the operation, in case you defined several of them in the query

Find below an example for a query for changes on Products to be executed as cURL command:

$ curl -X POST https://history.{region}.commercetools.com/{projectKey}/graphql \
-H "Content-Type:application/json" \
-H "Authorization:Bearer ..." \
-d '{"query": "query (resourceTypes: Product) {results {type changes {previousValue nextValue change} }}" }'

Interactive GraphQL console

To query for the Records via GraphQL you can use an interactive GraphiQL environment that is available on following URL:

https://history.{region}.commercetools.com/{projectKey}/graphiql

To be able to use it, you need to provide a valid OAuth token for an API Client that has the above mentioned scopes.

{
"authorization": "Bearer XXXXXXX"
}

GraphiQL Change History

This console lets you explore the docs for the supported GraphQL queries and to introspect the GraphQL schema.

Scopes

Application of OAuth 2.0 scopes

You always need to grant the view_audit_log:{projectKey} scope to the query, plus (depending on the resource type you query for), the respective scopes additionally:

  • view_cart_discounts:{projectKey}
  • view_categories:{projectKey}
  • view_customers:{projectKey}
  • view_customer_groups:{projectKey}
  • view_discount_codes:{projectKey}
  • view_key_value_documents:{projectKey}
  • view_orders:{projectKey}
  • view_orders:{projectKey}:{storeKey}
  • view_payments:{projectKey}
  • view_product_selections:{projectKey}
  • view_products:{projectKey}
  • view_quote_requests:{projectKey}
  • view_quotes:{projectKey}
  • view_shopping_lists:{projectKey}
  • view_states:{projectKey}
  • view_staged_quotes:{projectKey}
  • view_stores:{projectKey}
  • view_tax_categories:{projectKey}
  • view_types:{projectKey}

Stores data fencing

Stores provide an extra level of granularity to Project data.

If Audit Log tracked a Change on a supported resource that has stores linked to it, then the Audit log Record has attached the store or stores that were linked at the time the Change was initiated.

A Record attached to a Store means that users would have limited access to the change depending on the store they are assigned to. The access will vary depending on the entity type.

Audit Log considers the two following premises:

  • A Record without Stores is considered a global change.
  • A Record with a Store attached to it is considered a Store-specific change.

See below how store-specific scopes are applied on queries for Changes on supported resource types:

Customers

If an API Client only has the view_customers:{projectKey}:store-1 scope it can only see changes on Customers associated with store-1 and global changes.

Orders

If an API Client only has the view_orders:{projectKey}:store-1 scope it can only see changes on Orders associated with store-1.

Shopping Lists

If an API Client only has the view_shopping_lists:{projectKey}:store-1 scope it can only see changes on Shopping Lists associated with store-1.