Approval Flows

This feature is part of Composable Commerce for B2B and will be subject to additional terms and pricing.

Approval Flows represent the entire approval process for an Order within a Business Unit and contain information about the status of approvals, rejections, and the Associates involved in the process.

Approval Flows are automatically generated when a new Order matches any defined Approval Rules.

An Approval Flow, along with its corresponding Order, achieves full approval once all necessary approvers, as per individual rule approver hierarchies, from all its Approval Rules, give their approval. However, a single instance of rejection will lead to the rejection of the entire Approval Flow.

Representations

ApprovalFlow

id
String

Unique identifier of the Approval Flow.

version
Int

Current version of the Approval Flow.

order

Order that needs to be approved.

businessUnit

Business Unit the Approval Flow belongs to.

rules
Array of ApprovalRule

Approval Rules that matched the Order.

status

Indicates whether the Approval Flow is under review, approved, or rejected.

Default: Pending
rejection

Present when the status of the Approval Flow is Rejected.

approvals

Existing approvals in the Approval Flow.

eligibleApprovers
Array of RuleApprover

Associate Roles that can approve according to the approver hierarchy tiers defined in rules. Associates are allowed to reject even after they have given approval, as long as the current approver hierarchy tier still contains their role.

pendingApprovers
Array of RuleApprover

Associate Roles required for approval based on the approver hierarchy tiers defined in rules across all remaining tiers.

currentTierPendingApprovers
Array of RuleApprover

Associate Roles required for approval based on the approver hierarchy tiers defined in rules only for the currently active tier(s).

custom

Custom Fields on the Approval Flow.

createdAt

Date and time (UTC) the Approval Flow was initially created.

createdByBETA

IDs and references that created the ApprovalFlow.

lastModifiedAt

Date and time (UTC) the Approval Flow was last updated.

lastModifiedByBETA

IDs and references that last modified the ApprovalFlow.

ApprovalFlowPagedQueryResponse

PagedQueryResult with results containing an array of ApprovalFlow.

limit
Int
offset
Int

Number of elements skipped.

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 ApprovalFlow

Approval Flows matching the query.

ApprovalFlowStatus

Indicates whether the Approval Flow is under review, approved, or rejected.

Pending

Default status of Approval Flows, indicating that the Approval Flow has not been fully approved or rejected.

Approved

Automatically set when all approvers from matching Approval Rules have approved. It indicates that the Approval Flow has been fully approved and is completed.

Rejected

Automatically set when a rejection occurs in the Approval Flow. A single rejection is sufficient to reject the entire Approval Flow.

ApprovalFlowRejection

rejecter

Associate who rejected the Approval Flow.

rejectedAt

Date and time (UTC) the Approval Flow was rejected.

reason
String

The reason for the rejection of the Approval Flow.

ApprovalFlowApproval

approver

Associate who approved the Approval Flow.

approvedAt

Date and time (UTC) the Approval Flow was approved.

Get ApprovalFlow

Get ApprovalFlow in BusinessUnit by ID

GET
https://api.{region}.commercetools.com/{projectKey}/as-associate/{associateId}/in-business-unit/key={businessUnitKey}/approval-flows/{id}
OAuth 2.0 Scopes:
view_approval_flows:{projectKey}
Path parameters:
region
String

Region in which the Project is hosted.

projectKey
String

key of the Project.

associateId
String

id of the Customer who is acting on behalf of the BusinessUnit.

businessUnitKey
String

key of the BusinessUnit.

id
String

id of the ApprovalFlow.

Query parameters:
expand
The parameter can be passed multiple times.
Response:
200ApprovalFlowasapplication/json
Request Example:cURL
curl --get https://api.{region}.commercetools.com/{projectKey}/as-associate/{associateId}/in-business-unit/key={businessUnitKey}/approval-flows/{id} -i \
--header 'Authorization: Bearer ${BEARER_TOKEN}'
200 Response Example: ApprovalFlowjson
{
"id": "0bd46ab0-ab12-4191-be2a-749e4f0453ef",
"version": 2,
"createdAt": "2023-06-12T14:43:46.096Z",
"lastModifiedAt": "2023-06-12T14:43:46.202Z",
"lastModifiedBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"createdBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"order": {
"typeId": "order",
"id": "f6c6cd95-0a09-4dd6-9253-1cd27c70b184"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"rules": [
{
"id": "ff806a85-1457-4cef-929a-79aefe85f02d",
"version": 1,
"createdAt": "2023-06-12T14:43:45.732Z",
"lastModifiedAt": "2023-06-12T14:43:45.732Z",
"lastModifiedBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"createdBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"key": "ar-key",
"name": "name",
"description": "description",
"status": "Active",
"predicate": "customer.email = \"example@example.org\"",
"approvers": {
"tiers": [
{
"and": [
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver0"
}
}
]
},
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
}
]
}
]
},
{
"and": [
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver2"
}
}
]
}
]
}
]
},
"requesters": [
{
"associateRole": {
"typeId": "associate-role",
"key": "requester"
}
}
],
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
}
}
],
"status": "Pending",
"approvals": [
{
"approver": {
"customer": {
"typeId": "customer",
"id": "9c95aece-ccfa-4cc2-98c5-6b7a5e474361"
},
"associateRoleAssignments": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver0"
},
"inheritance": "Disabled"
}
]
},
"approvedAt": "2023-04-06T17:41:28.123Z"
}
],
"eligibleApprovers": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver0"
}
},
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
},
{
"associateRole": {
"typeId": "associate-role",
"key": "approver2"
}
}
],
"pendingApprovers": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
},
{
"associateRole": {
"typeId": "associate-role",
"key": "approver2"
}
}
],
"currentTierPendingApprovers": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
}
]
}

Query ApprovalFlow in BusinessUnit

GET
https://api.{region}.commercetools.com/{projectKey}/as-associate/{associateId}/in-business-unit/key={businessUnitKey}/approval-flows
OAuth 2.0 Scopes:
view_approval_flows:{projectKey}
Path parameters:
region
String

Region in which the Project is hosted.

projectKey
String

key of the Project.

associateId
String

id of the Customer who is acting on behalf of the BusinessUnit.

businessUnitKey
String

key of the BusinessUnit.

Query parameters:
where
The parameter can be passed multiple times.
/^var[.][a-zA-Z0-9]+$/
Any string parameter matching this regular expression

Predicate parameter values.

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
offset
Int

Number of elements skipped.

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.

Response:
200ApprovalFlowPagedQueryResponseasapplication/json
Request Example:cURL
curl --get https://api.{region}.commercetools.com/{projectKey}/as-associate/{associateId}/in-business-unit/key={businessUnitKey}/approval-flows -i \
--header 'Authorization: Bearer ${BEARER_TOKEN}'
200 Response Example: ApprovalFlowPagedQueryResponsejson
{
"limit": 20,
"offset": 0,
"count": 1,
"total": 1,
"results": [
{
"id": "0bd46ab0-ab12-4191-be2a-749e4f0453ef",
"version": 2,
"createdAt": "2023-06-12T14:43:46.096Z",
"lastModifiedAt": "2023-06-12T14:43:46.202Z",
"lastModifiedBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"createdBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"order": {
"typeId": "order",
"id": "f6c6cd95-0a09-4dd6-9253-1cd27c70b184"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"rules": [
{
"id": "ff806a85-1457-4cef-929a-79aefe85f02d",
"version": 1,
"createdAt": "2023-06-12T14:43:45.732Z",
"lastModifiedAt": "2023-06-12T14:43:45.732Z",
"lastModifiedBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"createdBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"key": "ar-key",
"name": "name",
"description": "description",
"status": "Active",
"predicate": "customer.email = \"example@example.org\"",
"approvers": {
"tiers": [
{
"and": [
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver0"
}
}
]
},
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
}
]
}
]
},
{
"and": [
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver2"
}
}
]
}
]
}
]
},
"requesters": [
{
"associateRole": {
"typeId": "associate-role",
"key": "requester"
}
}
],
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
}
}
],
"status": "Pending",
"approvals": [
{
"approver": {
"customer": {
"typeId": "customer",
"id": "9c95aece-ccfa-4cc2-98c5-6b7a5e474361"
},
"associateRoleAssignments": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver0"
},
"inheritance": "Disabled"
}
]
},
"approvedAt": "2023-04-06T17:41:28.123Z"
}
],
"eligibleApprovers": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver0"
}
},
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
},
{
"associateRole": {
"typeId": "associate-role",
"key": "approver2"
}
}
],
"pendingApprovers": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
},
{
"associateRole": {
"typeId": "associate-role",
"key": "approver2"
}
}
],
"currentTierPendingApprovers": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver1"
}
}
]
}
]
}

Update ApprovalFlow

Update ApprovalFlow in BusinessUnit by ID

POST
https://api.{region}.commercetools.com/{projectKey}/as-associate/{associateId}/in-business-unit/key={businessUnitKey}/approval-flows/{id}
OAuth 2.0 Scopes:
manage_approval_flows:{projectKey}
Path parameters:
region
String

Region in which the Project is hosted.

projectKey
String

key of the Project.

associateId
String

id of the Customer who is acting on behalf of the BusinessUnit.

businessUnitKey
String

key of the BusinessUnit.

id
String

id of the ApprovalFlow.

Query parameters:
expand
The parameter can be passed multiple times.
Request Body:
application/json
version
Int

Expected version of the Approval Flow to which the changes should be applied. If the expected version does not match the actual version, a ConcurrentModification error will be returned.

actions

Update actions to be performed on the Approval Flow.

Response:
200ApprovalFlowasapplication/json
Request Example:cURL
curl https://api.{region}.commercetools.com/{projectKey}/as-associate/{associateId}/in-business-unit/key={businessUnitKey}/approval-flows/{id} -i \
--header 'Authorization: Bearer ${BEARER_TOKEN}' \
--header 'Content-Type: application/json' \
--data-binary @- << DATA
{
"version" : 1,
"actions" : [ {
"action" : "reject",
"reason" : "Out of policy"
} ]
}
DATA
200 Response Example: ApprovalFlowjson
{
"id": "0bd46ab0-ab12-4191-be2a-749e4f0453ef",
"version": 3,
"createdAt": "2023-06-12T14:43:46.096Z",
"lastModifiedAt": "2023-06-12T14:43:46.242Z",
"lastModifiedBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"createdBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"order": {
"typeId": "order",
"id": "f6c6cd95-0a09-4dd6-9253-1cd27c70b184"
},
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
},
"rules": [
{
"id": "ff806a85-1457-4cef-929a-79aefe85f02d",
"version": 1,
"createdAt": "2023-06-12T14:43:45.732Z",
"lastModifiedAt": "2023-06-12T14:43:45.732Z",
"lastModifiedBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"createdBy": {
"clientId": "EH-PdRPKst38wygJuKChVlBS",
"isPlatformClient": false
},
"key": "ar-key",
"name": "name",
"description": "description",
"status": "Active",
"predicate": "customer.email = \"example@example.org\"",
"approvers": {
"tiers": [
{
"and": [
{
"or": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver"
}
}
]
}
]
}
]
},
"requesters": [
{
"associateRole": {
"typeId": "associate-role",
"key": "requester"
}
}
],
"businessUnit": {
"typeId": "business-unit",
"key": "bu-key"
}
}
],
"status": "Rejected",
"rejection": {
"rejecter": {
"customer": {
"typeId": "customer",
"id": "49b7011c-f1a6-411a-a69b-724b96dab934"
},
"roles": [],
"associateRoleAssignments": [
{
"associateRole": {
"typeId": "associate-role",
"key": "approver"
},
"inheritance": "Disabled"
}
]
},
"rejectedAt": "2023-06-12T14:43:46.239Z",
"reason": "Out of policy"
},
"approvals": [],
"eligibleApprovers": [],
"pendingApprovers": [],
"currentTierPendingApprovers": []
}

Update actions

Approve

This update action allows an Associate to approve an Approval Flow. The process takes into account all Associate Roles held by the Associate, aligning with the matched Approval Rules and their respective approver hierarchies.

When every required Associate has given their approval, the Approval Flow achieves a fully approved state, automatically updating its status to Approved. An Associate is eligible to approve only if their roles are within tiers of the Approval Rule hierarchy that are yet to be fully approved or rejected. As such, an Associate may be able to give their approval more than once.

action
String
"approve"
Example: json
{
"action": "approve"
}

Reject

This update action allows an Associate to reject an Approval Flow, setting its status to Rejected. The process takes into account all Associate Roles held by the Associate, aligning with the matched Approval Rules and their respective approver hierarchies. Even a single rejection in the process will result in the rejection of the entire Approval Flow.

An Associate is eligible to reject only if their roles are within tiers of the Approval Rule hierarchy that are yet to be rejected. An Associate may alter a prior approval into a rejection.

action
String
"reject"
reason
String

The reason for the rejection of the Approval Flow.

Example: json
{
"action": "reject",
"reason": "Out of policy"
}

Set Custom Type

action
String
"setCustomType"

Defines the Type that extends the ApprovalFlow with Custom Fields. If absent, any existing Type and Custom Fields are removed from the ApprovalFlow.

fields

Sets the Custom Fields fields for the ApprovalFlow.

Example: json
{
"action": "setCustomType",
"type": {
"id": "{{type-id}}",
"typeId": "type"
},
"fields": {
"exampleStringTypeField": "TextString"
}
}

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.

Example: json
{
"action": "setCustomField",
"name": "ExampleStringTypeField",
"value": "TextString"
}