Automate the reordering process for frequently purchased products.
Recurring Orders automates the reordering process for a Customer. You can define the Cart containing the products to be ordered, the reorder frequency, and the start and end dates. Once configured, orders are placed automatically for the Customer at the scheduled interval. Recurring Orders can be modified, paused, or canceled to accommodate changes in demand.
Representations
RecurringOrder
id ​String​ | Unique identifier of the RecurringOrder. |
version ​Int​ | Current version of the RecurringOrder. |
key ​String​ | User-defined unique identifier of the RecurringOrder. MinLength:Â2 ​MaxLength: 256 ​Pattern: ^[A-Za-z0-9_-]+$ ​ |
cart ​ | Reference to the Cart for a RecurringOrder.
The referenced Cart will have the RecurringOrder CartOrigin. |
originOrder ​ | |
startsAt ​DateTime​ | Date and time (UTC) when the RecurringOrder starts creating new Orders. |
resumesAt ​DateTime​ | Date and time (UTC) when the RecurringOrder resumes creating Orders after being unpaused. |
expiresAt ​DateTime​ | Date and time (UTC) when the RecurringOrder expires. |
lastOrderAt ​DateTime​ | Date and time (UTC) when the last Order was created from this RecurringOrder. |
nextOrderAt ​DateTime​ | Date and time (UTC) when the next Order will be created from this RecurringOrder. |
skipConfiguration ​ | Information about current and future skips for this RecurringOrder. |
store ​ | Reference to a Store. |
businessUnit ​ | Reference to the Business Unit that the RecurringOrder belongs to. |
state ​ | State of the RecurringOrder.
This reference can point to a State in a custom workflow. |
recurringOrderState ​ | Current state of the RecurringOrder. |
schedule ​ | Schedule of the RecurringOrder. |
customer ​ | The Customer that the RecurringOrder belongs to. |
customerEmail ​String​ | Email address of the Customer that the RecurringOrder belongs to. |
custom ​CustomFields​ | Custom Fields of the RecurringOrder. |
createdAt ​DateTime​ | Date and time (UTC) when the RecurringOrder was created. |
createdBy ​BETACreatedBy​ | IDs and references that created the RecurringOrder. |
lastModifiedAt ​DateTime​ | Date and time (UTC) when the RecurringOrder was last updated. |
lastModifiedBy ​BETA | IDs and references that last modified the RecurringOrder. |
RecurringOrderDraft
Recurring Orders are automatically assigned the Store and/or Business Unit from the associated Cart.
key ​String​ | User-defined unique identifier of the RecurringOrder. MinLength: 2 ​MaxLength: 256 ​Pattern: ^[A-Za-z0-9_-]+$ ​ |
cart ​ | ResourceIdentifier to the Cart from which the RecurringOrder is created. |
cartVersion ​Int​ | Current version of the referenced Cart. |
startsAt ​DateTime​ | Date and time (UTC) when the RecurringOrder will start. |
state ​ | State for the RecurringOrder in a custom workflow. |
custom ​ | Custom Fields to be added to the RecurringOrder. |
RecurringOrderPagedQueryResponse
limit ​Int​ | Number of results requested. Default: 20 ​Minimum: 0 ​Maximum: 500 ​ |
offset ​Int​ | Number of elements skipped. Default: 0 ​Minimum: 0 ​Maximum: 10000 ​ |
count ​Int​ | Actual number of results returned. |
total ​Int​ | Total number of results matching the query.
This number is an estimation that is not strongly consistent.
This field is returned by default.
For improved performance, calculating this field can be deactivated by using the query parameter withTotal=false .
When the results are filtered with a Query Predicate, total is subject to a limit. |
results ​Array of RecurringOrder​ | RecurringOrders matching the query. |
RecurringOrderReference
id ​String​ | Unique identifier of the referenced RecurringOrder. |
typeId ​ | recurring-order Type of referenced resource. |
obj ​ | Contains the representation of the expanded RecurringOrder. Only present in responses to requests with Reference Expansion for RecurringOrders. |
RecurringOrderResourceIdentifier
id
or key
is required. If both are set, an InvalidJsonInput error is returned.id ​String​ | Unique identifier of the referenced RecurringOrder. Required if key is absent. |
key ​String​ | User-defined unique identifier of the referenced RecurringOrder. Required if id is absent. |
typeId ​ | recurring-order Type of referenced resource. If given, it must match the expected ReferenceTypeId of the referenced resource. |
RecurringOrderState
Active
The default state of a new RecurringOrder.
Paused
Indicates that the RecurringOrder is paused.
Expired
Indicates that the RecurringOrder is expired.
Canceled
Indicates that the RecurringOrder is canceled.
RecurringOrderStateDraft
type ​String​ |
RecurringOrderActive
Changes the Recurring Order state to active.
type ​String​ | "active" |
resumesAt ​DateTime​ | If set, the Recurring Order will automatically resume at the date and time (UTC) specified. |
RecurringOrderPaused
Changes the Recurring Order state to paused.
type ​String​ | "paused" |
RecurringOrderExpired
Changes the Recurring Order state to expired.
type ​String​ | "expired" |
RecurringOrderCanceled
Changes the Recurring Order state to canceled.
type ​String​ | "canceled" |
reason ​String​ | The reason for the cancelation. |
SkipConfiguration
Defines how the next orders are going to be skipped.
Counter
type ​String​ | "counter" |
totalToSkip ​Int​ | Number of Orders that are going to be skipped. |
skipped ​Int​ | Amount of Orders that were already skipped. |
lastSkippedAt ​DateTime​ | Date and time (UTC) when the last Order creation was skipped. |
CounterDraft
Configuration that uses a counter to track the number of Orders that will be skipped.
type ​String​ | "counter" |
totalToSkip ​Int​ | Number of Orders that are going to be skipped. |
PriceSelectionMode
Fixed
- The price set when the Recurring Order was created is used for each subsequent order.
Dynamic
The price is updated each time a new Order is created.
Get RecurringOrder
Get RecurringOrder by ID
id
.view_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
id String ​ | id of the RecurringOrder. |
expand | The parameter can be passed multiple times. |
application/json
curl --get https://api.{region}.commercetools.com/{projectKey}/recurring-orders/{id} -i \
--header "Authorization: Bearer ${BEARER_TOKEN}"
{
"id": "42c72ffb-d1e6-4eb2-b05f-17d227f8422d",
"version": 1,
"createdAt": "2025-01-06T20:09:33.751Z",
"lastModifiedAt": "2025-01-06T20:09:33.751Z",
"cart": {
"typeId": "cart",
"id": "d688de05-dc0a-43de-91dc-94ab30f21c1e"
},
"originOrder": {
"typeId": "order",
"id": "68c20103-fc7b-430f-8f00-094c312b19e6"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"startsAt": "2025-01-02T20:09:33.644Z",
"lastOrderAt": "2025-01-06T16:00:25.657Z",
"nextOrderAt": "2025-01-07T20:09:33.644Z",
"recurringOrderState": "Active",
"schedule": {
"type": "standard",
"value": 1,
"intervalUnit": "Days"
}
}
Get RecurringOrder by Key
key
.view_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
key String ​ | key of the RecurringOrder. |
expand | The parameter can be passed multiple times. |
application/json
curl --get https://api.{region}.commercetools.com/{projectKey}/recurring-orders/key={key} -i \
--header "Authorization: Bearer ${BEARER_TOKEN}"
{
"id": "42c72ffb-d1e6-4eb2-b05f-17d227f8422d",
"version": 1,
"createdAt": "2025-01-06T20:09:33.751Z",
"lastModifiedAt": "2025-01-06T20:09:33.751Z",
"cart": {
"typeId": "cart",
"id": "d688de05-dc0a-43de-91dc-94ab30f21c1e"
},
"originOrder": {
"typeId": "order",
"id": "68c20103-fc7b-430f-8f00-094c312b19e6"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"startsAt": "2025-01-02T20:09:33.644Z",
"lastOrderAt": "2025-01-06T16:00:25.657Z",
"nextOrderAt": "2025-01-07T20:09:33.644Z",
"recurringOrderState": "Active",
"schedule": {
"type": "standard",
"value": 1,
"intervalUnit": "Days"
}
}
Query RecurringOrders
view_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
where | The parameter can be passed multiple times. |
sort | The parameter can be passed multiple times. |
expand | The parameter can be passed multiple times. |
limit Int ​ | Number of results requested. Default: 20 ​Minimum: 0 ​Maximum: 500 ​ |
offset Int ​ | Number of elements skipped. Default: 0 ​Maximum: 10000 ​ |
withTotal Boolean ​ | Controls the calculation of the total number of query results. Set to false to improve query performance when the total is not needed.Default: true ​ |
var.<varName> String ​ | Predicate parameter values. The parameter can be passed multiple times. |
RecurringOrderPagedQueryResponse
asapplication/json
curl --get https://api.{region}.commercetools.com/{projectKey}/recurring-orders -i \
--header "Authorization: Bearer ${BEARER_TOKEN}"
{
"limit": 20,
"offset": 0,
"count": 1,
"total": 1,
"results": [
{
"id": "42c72ffb-d1e6-4eb2-b05f-17d227f8422d",
"version": 1,
"createdAt": "2025-01-06T20:09:33.751Z",
"lastModifiedAt": "2025-01-06T20:09:33.751Z",
"cart": {
"typeId": "cart",
"id": "d688de05-dc0a-43de-91dc-94ab30f21c1e"
},
"originOrder": {
"typeId": "order",
"id": "68c20103-fc7b-430f-8f00-094c312b19e6"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"startsAt": "2025-01-02T20:09:33.644Z",
"lastOrderAt": "2025-01-06T16:00:25.657Z",
"nextOrderAt": "2025-01-07T20:09:33.644Z",
"recurringOrderState": "Active",
"schedule": {
"type": "standard",
"value": 1,
"intervalUnit": "Days"
}
}
]
}
Check if RecurringOrder exists
Check if RecurringOrder exists by ID
id
. Returns a 200 OK
status if the Recurring Order exists, or a NotFound error otherwise.view_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
id String ​ | id of the RecurringOrder. |
curl --head https://api.{region}.commercetools.com/{projectKey}/recurring-orders/{id} -i \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Check if RecurringOrder exists by Key
key
. Returns a 200 OK
status if the Recurring Order exists, or a NotFound error otherwise.view_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
key String ​ | key of the RecurringOrder. |
curl --head https://api.{region}.commercetools.com/{projectKey}/recurring-orders/key={key} -i \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Check if RecurringOrder exists by Query Predicate
200 OK
status if any Recurring Orders match the query predicate, or a NotFound error otherwise.view_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
where | The parameter can be passed multiple times. |
curl --head https://api.{region}.commercetools.com/{projectKey}/recurring-orders -i \
--header "Authorization: Bearer ${BEARER_TOKEN}"
Create RecurringOrder
If a server-side problem occurs, indicated by a 500 Internal Server Error HTTP response, the Recurring Order creation may still successfully complete after the error is returned. If you receive this error, you should verify the status of the Recurring Order by querying a unique identifier supplied during the creation request, such as the key.
manage_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
expand | The parameter can be passed multiple times. |
application/json
application/json
curl https://api.{region}.commercetools.com/{projectKey}/recurring-orders -i \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--header 'Content-Type: application/json' \
--data-binary @- << DATA
{
"cart" : {
"id" : "7c2e2694-aefe-43d7-888e-6a99514caaca",
"typeId" : "cart"
},
"cartVersion" : 10,
"startsAt" : "2017-01-04T19:54:49.797Z"
}
DATA
{
"id": "42c72ffb-d1e6-4eb2-b05f-17d227f8422d",
"version": 1,
"createdAt": "2025-01-06T20:09:33.751Z",
"lastModifiedAt": "2025-01-06T20:09:33.751Z",
"cart": {
"typeId": "cart",
"id": "d688de05-dc0a-43de-91dc-94ab30f21c1e"
},
"originOrder": {
"typeId": "order",
"id": "68c20103-fc7b-430f-8f00-094c312b19e6"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"startsAt": "2025-01-02T20:09:33.644Z",
"lastOrderAt": "2025-01-06T16:00:25.657Z",
"nextOrderAt": "2025-01-07T20:09:33.644Z",
"recurringOrderState": "Active",
"schedule": {
"type": "standard",
"value": 1,
"intervalUnit": "Days"
}
}
Update RecurringOrder
Update RecurringOrder by ID
manage_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
id String ​ | id of the RecurringOrder. |
expand | The parameter can be passed multiple times. |
application/json
version ​Int​ | Expected version of the RecurringOrder on which the changes should be applied.
If the expected version does not match the actual version, a ConcurrentModification error will be returned. |
actions ​Array of RecurringOrderUpdateAction​ | Update actions to be performed on the RecurringOrder. |
application/json
curl https://api.{region}.commercetools.com/{projectKey}/recurring-orders/{id} -i \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--header 'Content-Type: application/json' \
--data-binary @- << DATA
{
"version" : 1,
"actions" : [ {
"action" : "setKey",
"key" : "new-key"
} ]
}
DATA
{
"id": "42c72ffb-d1e6-4eb2-b05f-17d227f8422d",
"version": 1,
"createdAt": "2025-01-06T20:09:33.751Z",
"lastModifiedAt": "2025-01-06T20:09:33.751Z",
"cart": {
"typeId": "cart",
"id": "d688de05-dc0a-43de-91dc-94ab30f21c1e"
},
"originOrder": {
"typeId": "order",
"id": "68c20103-fc7b-430f-8f00-094c312b19e6"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"startsAt": "2025-01-02T20:09:33.644Z",
"lastOrderAt": "2025-01-06T16:00:25.657Z",
"nextOrderAt": "2025-01-07T20:09:33.644Z",
"recurringOrderState": "Active",
"schedule": {
"type": "standard",
"value": 1,
"intervalUnit": "Days"
}
}
Update RecurringOrder by Key
manage_recurring_orders:{projectKey}
region String ​ | Region in which the Project is hosted. |
projectKey String ​ | key of the Project. |
key String ​ | key of the RecurringOrder. |
expand | The parameter can be passed multiple times. |
application/json
version ​Int​ | Expected version of the RecurringOrder on which the changes should be applied.
If the expected version does not match the actual version, a ConcurrentModification error will be returned. |
actions ​Array of RecurringOrderUpdateAction​ | Update actions to be performed on the RecurringOrder. |
application/json
curl https://api.{region}.commercetools.com/{projectKey}/recurring-orders/key={key} -i \
--header "Authorization: Bearer ${BEARER_TOKEN}" \
--header 'Content-Type: application/json' \
--data-binary @- << DATA
{
"version" : 1,
"actions" : [ {
"action" : "setKey",
"key" : "new-key"
} ]
}
DATA
{
"id": "42c72ffb-d1e6-4eb2-b05f-17d227f8422d",
"version": 1,
"createdAt": "2025-01-06T20:09:33.751Z",
"lastModifiedAt": "2025-01-06T20:09:33.751Z",
"cart": {
"typeId": "cart",
"id": "d688de05-dc0a-43de-91dc-94ab30f21c1e"
},
"originOrder": {
"typeId": "order",
"id": "68c20103-fc7b-430f-8f00-094c312b19e6"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"startsAt": "2025-01-02T20:09:33.644Z",
"lastOrderAt": "2025-01-06T16:00:25.657Z",
"nextOrderAt": "2025-01-07T20:09:33.644Z",
"recurringOrderState": "Active",
"schedule": {
"type": "standard",
"value": 1,
"intervalUnit": "Days"
}
}
Update actions
Set Key
action ​String​ | "setKey" |
key ​String​ | Value to set. If empty, any existing key will be removed. MinLength:Â2 ​MaxLength: 256 ​Pattern: ^[A-Za-z0-9_-]+$ ​ |
{
"action": "setKey",
"key": "new-key"
}
Transition State
transitions
, there must be a direct transition to the new State.
If transitions
is not set, no validation is performed.action ​String​ | "transitionState" |
state ​ | Value to set. If there is no State yet, the new State must be an initial State. |
force ​Boolean​ | Set to Default: true to turn off validation.false ​ |
{
"action": "transitionState",
"state": {
"typeId": "state",
"id": "{{state-id}}"
}
}
Set RecurringOrderState
action ​String​ | "setRecurringOrderState" |
recurringOrderState ​ | New state of the RecurringOrder. |
{
"action": "setRecurringOrderState",
"recurringOrderState": {
"type": "active"
}
}
Set CustomField
action ​String​ | "setCustomField" |
name ​String​ | Name of the Custom Field. |
value ​ | If value is absent or null , this field will be removed if it exists.
Removing a field that does not exist returns an InvalidOperation error.
If value is provided, it is set for the field defined by name . |
{
"action": "setCustomField",
"name": "ExampleStringTypeField",
"value": "TextString"
}
Set Custom Type
action ​String​ | "setCustomType" |
type ​ | Defines the Type that extends the RecurringOrder with Custom Fields.
If absent, any existing Type and Custom Fields are removed from the RecurringOrder. |
fields ​ | Sets the Custom Fields fields for the RecurringOrder. |
{
"action": "setCustomType",
"type": {
"id": "{{type-id}}",
"typeId": "type"
},
"fields": {
"exampleStringField": "TextString"
}
}
Set Skip Configuration
action ​String​ | "setOrderSkipConfiguration" |
skipConfiguration ​SkipConfigurationDraft​ | Configuration for skipping the next orders of the Recurring Order. |
updatedExpiresAt ​DateTime​ | Date and time (UTC) the Recurring Order will resume and start to generate new orders. |
{
"action": "setOrderSkipConfiguration",
"skipConfiguration": {
"type": "counter",
"totalToSkip": 3
},
"updatedExpiresAt": "2025-10-15T15:00:00.000Z"
}
Set Starts At
action ​String​ | "setStartsAt" |
startsAt ​DateTime​ | Date and time (UTC) the Recurring Order should be started. The date and time must be in the future. |
{
"action": "setStartsAt",
"startsAt": "2025-10-15T15:00:00.000Z"
}
Set Schedule
action ​String​ | "setSchedule" |
recurrencePolicy ​ | Value to set. |
{
"action": "setSchedule",
"recurrencePolicy": {
"typeId": "recurrence-policy",
"id": "{{recurrence-policy-id}}"
}
}