Generate Appeasements
Appeasements are a way that you can alleviate customer dissatisfaction.
Should one of your shoppers have a bad experience with their order, issuing an appeasement is a way to prevent them from canceling their orders. Appeasements allow an Agent to provide some form of monetary, or non-monetary, compensation.
For example, if a shopper places an order and is unsatisfied with the products, an Agent could issue an appeasement for a single item in the order, or for the total order and shipping charges.
Authorized Agents have the capability to provide appeasements to your shoppers by offering a refund, store credit, credit memo or other method. Once the appeasement has been made, an email is sent to the shopper with the appeasement information.
Understand appeasements
You can use the Admin and the Agent API to develop an appeasement workflow. The Agent API contains endpoints that allow an Agent to create and review appeasements, as well as to submit appeasements. Agents who have the role of Supervisor can issue appeasements for a submitted or fulfilled order. Appeasements can be issued using one or more appeasement refunds. When an Agent issues an appeasement, they also provide notes and reasons for the appeasement. Agents are able to see a history of any previous appeasements for a customer or an order.
Appeasements are typically associated with an order, and the default appeasement type is order
. You can provide custom properties for the order at both the appeasement level and the refund level. Appeasements totals are limited by the order total, meaning that the total number of appeasements and returns cannot exceed the total of the order. However, you can add limits and provide additional validation as needed by using a validation webhook.
You can issue appeasements in any currency, but when performing order-based appeasements, the currency must match that used in the order. If an order contains multiple currencies, such as in both dollars and loyalty points, appeasements for that order can be issued in both dollars and loyalty points.
Once generated, the system associates the appeasement with the Agent who performed the appeasement. All submitted appeasements are validated by default. For example, the system validates that an appeasement does not exceed the total value of the order.
Use appeasements
There are several scenarios where you might want to use appeasements. For example, if a shopper places an order with priority shipping, and the order arrives late, the Agent could create an appeasement for the order.
Should a shopper not receive their order on time, and then discover that one of the items within the order is damaged, an Agent can create multiple appeasements associated with the order. For example, the Agent could provide an appeasement for the shipping total, and then another appeasement for store credit for the damaged item.
Agents can refund the appeasement value using the payment instrument used to create the order. The refund structure and refund type used for different payment types is described later in this section. Although the amount credited and other details of the original payment method used in the order are updated automatically, an Agent can issue appeasement refunds to another payment method, such as issue store credit or loyalty points.
When issuing an appeasement, the Agent must set an appeasement value that does not exceed the order total. Earlier appeasements and refund values are also included in the equation when creating a new appeasement.
You can configure your appeasement process to include work with an external system, which receives and returns appeasement information. An Agent can send appeasement details to use, as well as get, validations from an external system.
You cannot create appeasements for invalid or deleted sites, but you can create an appeasement for an inactive organization. This applies only to Agent-based appeasements, and does not apply to Admin-based appeasements.
Use the Appeasement API
Use the Appeasement API to generate appeasements, which includes an Agent API and an Admin API. The Agent API allows an Agent to create and submit an appeasement. The Admin API allows you to create and submit appeasements, as well as update the status of an appeasement. In general, the Agent API has more restrictions, such as it allows only the creation and review of appeasements. However, the appeasements are made in the INCOMPLETE
state for the Agent API. The Admin API allows actions in appeasements that are in any state.
The Admin APIs allow you to configure the type of appeasement that can be provided by the Agent Supervisor, as well as the reason for appeasements
When an appeasement is made using the Agent API, the default OriginOfAppeasement
is set to contactCenter
. An Agent can create an appeasement for a submitted or fulfilled order or any custom appeasement types that have been created in the API.
You can use the Admin API to import appeasements form an external appeasement system. The Admin API can also provide a way to configure appeasement types and appeasement reasons. Whenever the originOfAppeasement
does not contain a value, the default is external
. You can also create custom properties for appeasement and refunds.
The following properties are used by the endpoints in the Appeasement API:
Property | Description |
---|---|
agentId |
The ID of the Agent who issued the appeasement. |
amount |
Indicates the amount to be appeased with a specific payment instrument. This optional field is used for each refund in the appeasementRefunds array.
|
appeasementRefund |
This array includes the following properties:
|
comments |
Comments, stored in a JSON array format, added by the Agent. |
creationDate |
The date and time that the appeasement was initiated. Different than submittedDate , which identifies when an appeasement has been submitted.
|
currencyCode |
This indicates the currency in which a monetary appeasement is to be paid. The currency code is added to the appeasement refund level to support orders that use multiple currencies. |
id |
The ID of the appeasement. |
notes |
Notes that provide additional information regarding the appeasement. |
orderId |
The order ID is mandatory for all appeasement types. The order must be a fulfilled order or a submitted order that is past its remorse period. |
originOfAppeasement |
If you are using the Agent API, this defaults to contactCenter . If you are using the Admin API, this defaults to external .
|
paymentGroupId |
The payment group ID, which is part of the appeasementRefund property, is required to identify to which card the refund should be applied.
|
profileId |
The profile ID be should be that of a registered customer. Customers who are pending self-registration are not valid. |
reason |
The reason for the appeasement. Reasons are created in by using the
|
refundType |
This property, which is in
|
state |
The state of the appeasement, which is available at both the appeasement and appeasementRefund level. Note that the state can be updated if you use the Admin API, however, when using the Agent API, you can only view the property.
|
submittedDate |
Identifies when an appeasement has been submitted. Different than creationDate , which identifies when an appeasement has been initiated.
|
type |
Provides the type of the appeasement. The default type is order .
|
Initiate an appeasement
The initiateAppeasement
endpoint in the Agent API validates the order and returns the appeasement refund types with the maximum amount that can be issued. To initiate an appeasement, issue a POST
command. Use this endpoint to see the possible refund types, refund structure and the maximum refund amount allowed for each refund type.
For example, you could create an appeasement by issuing the following command:
POST /ccagent/v1/appeasements/initiate
{
“orderId”:”o30425”
}
If you do not specify an order ID, the system returns information for an appeasementRefund
of an externalRefundType
. You can use the response to create a new appeasement or update and submit an existing incomplete appeasement. The response payload might be similar to the following:
{
"orderId": "o30425",
"appeasementRefunds": [
{
"paymentGroupId": "pg30442",
"refundType": "tokenizedCreditCard",
"amount": 0,
"maximumRefundAmount": 97.18,
"id": "100020",
"state": "INCOMPLETE",
"currencyCode": "USD"
}
],
"links": [
{
"rel": "self",
"href": "http://localhost:9080/ccagent/v1/appeasements/initiate"
}
]
}
Create an appeasement
When you create an appeasement, it must have at least one associated appeasementRefund
that contains the mandatory refundType
property. With the exception of refunds that use the externalRefund
refund type, all refunds require the paymentgGroupId
and the amount properties.
Create an appeasement with the Agent API
You can use the Agent API createAppeasement
endpoint to create an appeasement. Use the endpoint when working with a valid site or organization. The endpoint performs a number of validations. A POST request might be similar to the following:
POST /ccagent/v1/appeasements
{
"notes": "The customer complained that the order arrived late,
and asked for a refund of the shipping amount. Providing 15 USD.",
"orderId": "o30444",
"appeasementRefunds": [
{
"currencyCode": "USD",
"amount": 5,
"refundType": "externalRefund",
},
{
"amount": 10,
"description": "Store Credit",
"refundType": "storeCredit",
"paymentGroupId": 1223232
}
],
"profileId": "120222",
"type": "order",
"reason": "orderArrivedLate",
"comments": [
{
"comment": "Appeasement to be settled as a priority. Valued customer."
}
]
}
The response payload to the POST
request may be similar to the following:
{
"agentId": "BobAFrette",
"notes": "The customer complained that the order arrived late, and asked for a
refund of shipping amount. Providing 15 USD.",
"orderId": "o30444",
"damagedLineItemId": "ci56873",
"lastModifiedDate": "2020-03-31T10:35:14.016Z",
"appeasementRefunds": [
{
"amount": 5,
"customerPreferredGiftCardId": "FC13213",
"id": "1100005",
"state": "INCOMPLETE",
"refundType": "externalRefund",
"currencyCode": "USD",
"paymentGroupId": null
},
{
"amount": 10,
"id": "1100006",
"state": "INCOMPLETE",
"refundType": "storeCredit",
"currencyCode": "USD",
"paymentGroupId": 1324255
}
],
"creationDate": "2020-03-31T10:35:14.016Z",
"profileId": "120222",
"state": "INCOMPLETE",
"id": "app160003",
"originOfAppeasement": "agent",
"type": "order",
"reason": "orderArrivedLate",
"links": [
{
"rel": "self",
"href": "http://localhost:9080/ccagent/v1/appeasements"
}
],
"comments": [
{
"agentId": " BobAFrette ",
"comment": "Appeasement to be settled on priority. Valued customer.",
"id": 100001,
"creationDate": "2020-03-20T04:56:13.935Z"
}
]
}
Once the appeasement has been created, it remains in the INCOMPLETE
state. The SUBMITTED
state is available only in the Admin API.
Create an appeasement with the Admin API
The Admin API createAppeasement
endpoint creates an appeasement, and is also used to import appeasements from an external system. Whenever the originOfAppeasement
does not contain a value, the default is external
.
The following example POST
request issues an appeasement because an item arrived late:
POST /ccadmin/v1/appeasements
{
"notes": "The customer complained that the order arrived late,
and asked for a refund of the shipping amount. Providing 15 USD.",
"orderId": "o30444",
"appeasementRefunds": [
{
"currencyCode": "USD",
"amount": 5,
"refundType": "externalRefund",
"state": "COMPLETE"
},
{
"amount": 10,
"description": "Store Credit",
"refundType": "storeCredit",
"paymentGroupId": 1223232,
"state": "COMPLETE"
}
],
"profileId": "120222",
"type": "order",
"reason": "orderArrivedLate",
"comments": [
{
"comment": "Appeasement to be settled as a priority. Valued customer."
}
],
"state": "COMPLETE"
}
The response may be something similar to the following:
{
"reason": {
"id": "itemArrivedLate",
"readableDescription": "Item Arrived Late"
},
"type": {
"id": "order",
"displayName": "Order",
"description": "Appeasement to be applied on a given order."
},
"agentId": " BobAFrette",
"notes": "The customer complained that the order arrived late, and asked for
a refund of shipping amount. Providing 15 USD.",
"appeasementRefunds": [
{
"amount": 10,
"currencyCode": "USD",
"id": "1100006",
"state": "INCOMPLETE",
"refundType": "storeCredit",
"paymentGroupId": "pg100122"
},
{
"mode": "giftCard",
"amount": 5,
"currencyCode": "USD",
"state": "INCOMPLETE",
"id": "1100005",
"refundType": "externalRefund",
"paymentGroupId": "pg100111"
}
],
"orderId": "o10052",
"lastModifiedDate": "2020-03-06T14:49:48.546Z",
"creationDate": "2020-03-06T14:49:48.546Z",
"profileId": null,
"state": "INCOMPLETE",
"originOfAppeasement": "external",
"id": "app30024",
"comments": [
{
"agentId": " BobAFrette",
"comment": "Appeasement to be settled as a priority. Valued customer.",
"id": 100001,
"creationDate": "2020-03-20T04:56:13.935Z"
}
]
}
Update an appeasement
The updateAppeasement
endpoint allows you to update an existing appeasement when you issue a PUT
command and specify the appeasement ID.
Update an appeasement with the Agent API
Note that only incomplete appeasements can be updated in the Agent API. For example:
PUT /ccagent/v1/appeasements/{id}
The following is an example of a request payload:
{
"notes": "The customer complained that the order arrived late, and asked for a
refund of shipping amount. Providing 15 USD.",
"appeasementRefunds": [
{
"amount": 5,
"refundType": "externalRefund",
"id": "1100005",
"customerPreferredGiftCardId": "FC13213",
"paymentGroupId": "122323",
"currencyCode": "USD"
},
{
"amount": 10,
"id": "1100006",
"refundType": "storeCredit",
"paymentGroupId": 1223234,
"currencyCode": "USD"
}
],
"comments": [
{
"comment": "Appeasement to be settled as a priority. Valued customer."
}
]
}
Note that the damagedLineItemId
and the customerPreferredGiftCardId
are custom properties that have been created at the appeasement level and the appeasement refund level.
The response payload to the above request might be similar to the following:
{
"agentId": " BobAFrette",
"notes": "The customer complained that the order arrived late, and asked for a
refund of shipping amount. Providing 15 USD.",
"orderId": "o30444",
"damagedLineItemId": "ci56873",
"lastModifiedDate": "2020-03-31T10:35:14.016Z",
"appeasementRefunds": [
{
"amount": 5,
"customerPreferredGiftCardId": "FC13213",
"id": "1100005",
"state": "INCOMPLETE",
"refundType": "externalRefund",
"currencyCode": "USD",
"paymentGroupId": null
},
{
"amount": 10,
"id": "1100006",
"state": "INCOMPLETE",
"refundType": "storeCredit",
"currencyCode": "USD",
"paymentGroupId": 1324255
}
],
"creationDate": "2020-03-31T10:35:14.016Z",
"profileId": "120222",
"state": "INCOMPLETE",
"id": "app160003",
"originOfAppeasement": "agent",
"type": "order",
"reason": "orderArrivedLate",
"links": [
{
"rel": "self",
"href": "http://localhost:9080/ccagent/v1/appeasements/app10001"
}
],
"comments": [
{
"agentId": " BobAFrette",
"comment": "Appeasement to be settled as a priority. Valued customer.",
"id": 100001,
"creationDate": "2020-03-20T04:56:13.935Z"
}
]
}
Update an appeasement using the Admin API
The Admin API updateAppeasement
endpoint updates an appeasement with the information provided. This endpoint also updates appeasements refund information. To use this endpoint, issue a PUT
command:
PUT /ccadmin/v1/appeasements/{id}
A request may be similar to the following:
{
"appeasementRefunds": [
{
"state": "COMPLETE",
"id": "1100005",
"refundType": "externalRefund"
},
{
"state": "COMPLETE",
"id": "1100006",
"refundType": "storeCredit"
}
],
"state": "COMPLETE",
"comments": [
{
"agentId": " BobAFrette",
"comment": "Appeasement to be settled as a priority. Valued customer.",
"id": 100001,
"creationDate": "2020-03-20T04:56:13.935Z"
},
{
"agentId": " BobAFrette",
"comment": "Appeasement settled",
"creationDate": "2020-04-20T04:56:13.935Z"
}
]
}
The response might be something similar to the following:
{
"reason": {
"id": "itemArrivedLate",
"readableDescription": "Item Arrived Late"
},
"type": {
"id": "order",
"displayName": "Order",
"description": "Appeasement to be applied on a given order"
},
"agentId": " BobAFrette",
"notes": "The customer complained that the order arrived late, and asked for
a refund of shipping amount. Providing 15 USD.",
"appeasementRefunds": [
{
"mode": null,
"amount": 20,
"currencyCode": "USD",
"transactionNumber": "TRX1006",
"description": "Store Credit",
"id": "1100006",
"state": "COMPLETE",
"refundType": "storeCredit",
"paymentGroupId": "pg100122"
},
{
"mode": "giftCard",
"amount": 10,
"currencyCode": "USD",
"transactionNumber": "TRX1089",
"description": "Amazon Gift Card",
"state": "COMPLETE",
"id": "1100005",
"refundType": "externalRefund",
"paymentGroupId": "pg100111"
}
],
"orderId": "o10052",
"lastModifiedDate": "2020-03-06T14:49:48.546Z",
"creationDate": "2020-03-06T14:49:48.546Z",
"profileId": null,
"state": "COMPLETE",
"originOfAppeasement": "external",
"id": "app30024",
"comments": [
{
"agentId": " BobAFrette",
"comment": "Appeasement to be settled as a priority. Valued customer.",
"id": 100001,
"creationDate": "2020-03-20T04:56:13.935Z"
},
{
"agentId": " BobAFrette",
"comment": "Appeasement settled",
"id": 100010,
"creationDate": "2020-03-20T04:56:13.935Z"
}
]
}
Submit an appeasement
The submitAppeasement
endpoint in the Agent API allows you to submit an incomplete appeasement to the system when you issue a POST
command. You can also use it to create and immediately submit a new appeasement or to submit an existing incomplete appeasement by providing the existing appeasement ID in the payload.
Note that only INCOMPLETE
appeasements may be submitted using the Agent API.
The following example displays the format you should use to submit a request:
POST /ccagent/v1/appeasement/submit
A request payload might look like the following:
{
"notes": "The customer complained that the order arrived late, and asked for a
refund of shipping amount. Providing 15 USD.",
"appeasementRefunds": [
{
"amount": 5,
"refundType": "externalRefund",
"id": "1100005",
"customerPreferredGiftCardId": "FC13213",
"paymentGroupId": "122323",
"currencyCode": "USD"
},
{
"amount": 10,
"id": "1100006",
"refundType": "storeCredit",
"paymentGroupId": 1223234,
"currencyCode": "USD"
}
],
"comments": [
{
"comment": "Appeasement to be settled as a priority. Valued customer."
}
]
}
Delete an appeasement
The deleteAppeasement
endpoints in both the Agent and the Admin API allow you to delete an incomplete appeasement from the system. Note that this endpoint in the Agent API is restricted to incomplete appeasements. The following is the format you should use to create a DELETE
command:
DELETE /ccagent/v1/appeasements/{id}
Note: When you delete an order-based appeasement that is in the COMPLETE
state, the appeasement history for that order will not contain that appeasement, allowing you to inadvertently provide appeasements that total more than the amount of the order.
List appeasements
The listAppeasements
endpoints in both the Agent and Admin API list the appeasements that match a specified search criteria provided in SCIM query format. The following example looks for a specific profile that starts with the first name “Kim”:
GET /ccagent/v1/appeasements?q=profile.fistName co “kim”
This command might return a response such as this:
{
"total": 2,
"totalResults": 2,
"offset": 0,
"limit": 8,
"items": [
{
"reason": {
"id": "itemArrivedLate",
"readableDescription": "Item Arrived Late"
},
"type": {
"id": "order",
"displayName": "Order",
"description": "Appeasement to be applied on a given order"
},
"agentId": " BobAFrette",
"notes": "Appeasement issued on customer's complaint about item delivery.",
"appeasementRefunds": [
{
"amount": 100,
"currencyCode": "USD",
"description": "Appeasement refund on item purchase",
"state": "INCOMPLETE",
"id": "AppRef0211",
"refundType": "externalRefund",
"paymentGroupId": "pg10331"
}
],
"orderId": "o10050",
"lastModifiedDate": "2020-03-20T05:15:05.645Z",
"creationDate": "2020-03-20T04:56:13.935Z",
"profileId": "se-570031",
"state": "PENDING_REFUND",
"originOfAppeasement": "external",
"id": "App00090",
"comments": [
{
"agentId": "service",
"comment": "Appeasement settlement has been expedite.",
"id": 100011,
"creationDate": "2020-03-20T04:26:13.935Z"
}
]
},
{
"reason": {
"id": "itemArrivedLate",
"readableDescription": "Item Arrived Late"
},
"type": {
"id": "order",
"displayName": "Order",
"description": "Appeasement to be applied on a given order."
},
"agentId": " BobAFrette",
"notes": "Appeasement issued because of a bad shipping experience.",
"appeasementRefunds": [
{
"amount": 20,
"currencyCode": "USD",
"state": "COMPLETE",
"id": "101001",
"refundType": "storeCredit",
"paymentGroupId": "pg100992"
}
],
"orderId": "o10052",
"lastModifiedDate": "2020-03-18T19:44:31.156Z",
"creationDate": "2020-03-18T19:44:31.156Z",
"profileId": "se-570031",
"state": "COMPLETE",
"originOfAppeasement": "external",
"id": "App10001",
"comments": [
{
"agentId": " BobAFrette",
"comment": "Customer asked to settle appeasement amount to the same
credit card used for order payment.",
"id": 100011,
"creationDate": "2020-03-20T04:26:13.935Z"
}
]
}
]
}
Get an appeasement type
The getType
endpoints in both the Agent and Admin API allow you to get details of a specific appeasement type by ID. The types that follow certain criteria can be obtained using the SCIM query format on the list appeasement types endpoint. Issue a GET
command to list appeasement types:
GET /ccagent/v1/appeasementTypes/{id}
Provide a valid appeasement type, such as shipping, and the response may look similar to the following:
{
"displayName": "Shipping Level",
"description": "This option can be chosen to provide appeasement for
the shipping amount in an order.",
"active": true,
"id": "shipping",
"isOrderRequired" : true
}
List all appeasements types
The listTypes
endpoints in both the Agent and Admin API provide a list of appeasement types when you issue a GET
command. For example the following would return all active appeasement types:
GET /ccagent/v1/appeasementsTypes?q=active eq true
The default appeasement type is order
. However, you can create custom appeasement types such as profile, shipping, item level, shipping group level, etc.
Create a type of appeasement
The createType
endpoint in the Admin API allows you to create an appeasement type, as well as any associated translations. You can create an appeasement type by issuing a POST
command. For example:
POST /ccadmin/v1/appeasementTypes
The following example shows how to create a new Shipping appeasement type:
{
"id": "shipping",
"displayName": "Shipping Level",
"description": "This appeasement type can be chosen to provide appeasement for
the shipping amount in an order.",
"active": true,
"isOrderRequired" : true
}
You can extend the default appeasement types, which contain the following properties:
description
active
isOrderRequired
type
id
Update appeasement types
The updateType
endpoint in the Admin API allows you to update an appeasement type by issuing a PUT
command using the following format:
PUT /ccadmin/v1/appeasementTypes/{id}
The following is an example of updating the a newly created Shipping appeasement type:
{
"description": "This option can be chosen to provide appeasement for the shipping amount in an order.",
"isOrderRequired" : true
}
Get an appeasement reason
Appeasements contain appeasement reasons that identify why the appeasement was made. Default appeasement reasons include the following:
orderArrivedLate
orderArrivedDamaged
itemArrivedLate
itemArrivedDamaged
didNotLikeItem
goodwillGesture
productComplaint
The getReason
endpoint in the Agent API obtains the appeasement reason corresponding to the reason ID you provide in the path parameter when you issue a GET
command. Use the following format when using this endpoint:
GET /ccagent/v1/reasons/{id}?type=appeasementReason
The getReasons
endpoint in the Admin API gets all of the appeasement reasons available when you issue a GET
command with the type query parameter. Use the following format:
GET /ccadmin/v1/reasons?type=appeasementReason
Use the following format to get a specific reason by its ID:
GET /ccadmin/v1/reasons?type=appeasementReason&id={id}
List all appeasement reasons for specific criteria
The listReasons
endpoint displays all of the appeasement reasons that match the search criteria for reasons that you specify using the SCIM query format. The following example searches for all appeasement reasons that are active:
GET /ccagent/v1/reasons?q=active eq true&type=appeasementReason
The response to the example request might be similar to the following:
{
"total": 2,
"totalResults": 2,
"offset": 0,
"limit": 8,
"items": [
{
"id": "goodwillGesture",
"active": false,
"description": "goodwillGesture",
"readableDescription": "Goodwill Gesture"
},
{
"id": "itemArrivedLate",
"active": true,
"description": "itemArrivedLate",
"readableDescription": "Item Arrived Late"
}
]
}
Create an appeasement reason
The createReason
endpoint in the Admin API allows you to create an appeasement reason, as well as any translations needed when you issue a POST
command. Use the following format:
POST /ccadmin/v1/reasons?type=appeasementReason
The following is an example of creating a Goodwill Gesture appeasement reason:
{
"id": "goodwillGesture",
"active": true,
"description": "goodwillGesture",
"readableDescription": "Goodwill Gesture"
}
Note that an external ID can be used if it is passed in with the request payload. The system generated ID is used by default.
The active
, description
and readableDescription
properties are used to support additional reason types used in addition to appeasements and should be provided when you create an appeasement reason.
Update an appeasement reason
The updateReason
endpoint in the Admin API updates an appeasement reason when you issue a PUT
command. Use the following format:
PUT /ccadmin/v1/reasons?type=appeasementReason&id={id}
The following is an example of updating the Goodwill Gesture appeasement reason so that it is no longer active:
{
"active": false,
"description": "goodwillGesture",
"readableDescription": "Goodwill Gesture"
}
Delete an appeasement reason
The deleteReason
endpoint in the Admin API allows you to delete an appeasement reason when you issue a DELETE
command using the following format:
DELETE /ccadmin/v1/reasons?type=appeasementReason&id={id}
Get appeasement information
You can use the getItemType
endpoint in the Admin API to get information about an appeasement, an appeasement refund or an appeasement comment item descriptor by issuing a GET
command in the following format:
GET /ccadmin/v1/itemTypes/{id}
Note that the id
can be appeasement
, appeasementRefund
or appeasementComment
.
Update an existing appeasement
You can use the updateItemType
endpoint in the Admin API to update an existing appeasement or an appeasement refund item type. You can also create custom properties at the appeasement or appeasement refund level with this endpoint. Use the following format:
PUT /ccadmin/v1/itemTypes/{itemTypeIdentifier}
Note that the itemTypeIdentifier
can be appeasement
, appeasementRefund
or appeasementComment
.
Create Comments
You can create a comment on an appeasement. The comments
property at the appeasement level is a list of comments provided by the Agent with the Agent API, or an external system using the Admin API. Comments is a separate entity referenced by the appeasement. The appeasement level comments are a list of the references to different associated comments. Comments are created/updated with the appeasement payload using appeasement endpoints. Note that comments can never be deleted. There is no separate endpoint for comments.
Comments
have the following properties for the API:
id
– The ID of the comment, which can identify a previous comments that should be updated, and should also be associated to the appeasement that is being updated.comment
– The actual text of the comment, which is required to create comments.agentId
– The ID of the Agent who saved the comment. This can also be the ID of an Agent that is provided by an external system. If this field is not provided in the payload, it defaults toexternal
. If the comment is added using the Agent API, theagentId
will automatically be the ID of the logged in Agent.createDate
– The date that the comment was created.
The following is an example of a comment that was added to a request:
"comments": [
{
"agentId": " BobAFrette",
"comment": "Customer asked to settle the appeasement amount to the same
credit card he used to pay for the order.",
"id": 100011,
"creationDate": "2020-03-20T04:26:13.935Z"
}
]
Use the Appeasement Webhook API
When you want to work with an external system to issue refund types, there are two webhooks that can help you configure your environment. The first webhook provides validation and the second webhook submits the appeasement.
To enable an Agent to select the payment tender type for the amount credited/refunded to the shopper, you must use an Server Side Extension (SSE) to build logic of what instruments are available.
Use the Appeasement Validation Webhook
The system performs validation, such as the appeasement amount cannot exceed the order total, but also allows you to create custom validations using a webhook. The validation webhook validates the appeasement request with a JSON response that contains a success and a failure responseCode
. If an external system requires additional data, it must use the API to obtain the necessary data. Note that because validation is synchronous, it could possibly create a performance lag.
Once the appeasement has been validated, it is sent to the external system through the AppeasementSubmitWebhook
event webhook. Any external system needs to settle the appeasement, and then update the appeasement using the update Admin API.
The AppeasementValidationWebhook
validates the appeasement with an external system. The webhook payload contains the following:
- Current appeasement information
- Current site, profile and organization context
- Agent information, including name, role and email
- Complete order information if the appeasement is associated with an order
- Complete profile information if the appeasement is associated with a non-anonymous order or a profile
- All return request details of the current order
- The latest 50 appeasements associated with the shopper
The entirety of the order and the profile data is included, which is the same as the submit order and update profile webhooks. This webhook contains order data that is similar to the submit order webhook, with the return data corresponding to the return request webhook.
The following is an example of an AppeasementValidationWebhook
request:
{
"appeasement": {
"reason": {
"readableDescription": "Order Arrived Late",
"id": "orderArrivedLate"
},
"agentId": "BobAFrette",
"notes": "The customer complained that the order arrived late, and asked for a
refund of shipping amount. Providing 15 USD.",
"comments": [],
"orderId": "o10411",
"lastModifiedDate": null,
"submittedTime": null,
"appeasementRefunds": [
{
"paymentGroupId": null,
"refundType": "externalRefund",
"amount": 0.01,
"id": "100004",
"state": "INCOMPLETE",
"currencyCode": "USD"
}
],
"submittedDate": "2020-06-23T17:02:55.502Z",
"type": {
"displayName": "Order",
"description": "Appeasement to be applied on a given order",
"id": "order"
},
"creationDate": "2020-06-23T17:02:55.519Z",
"profileId": "se-570031",
"appeasementAmount": 0,
"state": "INCOMPLETE",
"id": "app10004",
"originOfAppeasement": "agent"
},
"site": {
"name": "Commerce Cloud Site",
"id": "siteUS",
"url": "http://kkm00aqi.in.example.com:8080"
},
"agentInfo": {
"lastName": "Weber",
"firstName": "Damon",
"roles": [
{
"name": "CS Agent Supervisor",
"description": "CS Agent Supervisor Role",
"accessRights": [],
"id": "csAgentSupervisorRole",
"category": "Agent App"
}
],
"id": "service",
"email": null
},
"previousAppeasements": [
{
"reason": {
"readableDescription": "Order Arrived Late",
"id": "orderArrivedLate"
},
"agentId": "service",
"notes": "The customer complained that the order arrived late, and asked for a
refund of shipping amount. Providing 15 USD.",
"comments": [],
"orderId": "o10411",
"lastModifiedDate": "2020-06-23T13:52:40.748Z",
"submittedTime": null,
"appeasementRefunds": [
{
"paymentGroupId": null,
"refundType": "externalRefund",
"amount": 0.01,
"id": "100001",
"state": "INCOMPLETE",
"currencyCode": "USD"
}
],
"submittedDate": "2020-06-23T13:52:40.720Z",
"type": {
"displayName": "Order",
"description": "Appeasement to be applied on a given order.",
"id": "order"
},
"creationDate": "2020-06-23T13:52:40.748Z",
"profileId": "se-570031",
"appeasementAmount": 0,
"state": "SUBMITTED",
"id": "app10001",
"originOfAppeasement": "agent"
}
],
"profile": {
"lastPurchaseDate": "2020-06-23T13:50:49.686Z",
"dynamicPropertyMapLong": {},
"GDPRProfileP13nConsentDate": null,
"GDPRProfileP13n ConsentGranted": false,
"secondaryAddresses": {
"Work": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Buffalo",
"address2": "",
"prefix": null,
"address1": "451 Brooks Ave",
"postalCode": "14201",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-2150",
"item-id": null,
"repositoryId": "se-970031",
"faxNumber": null,
"middleName": null,
"state": "NY"
},
"Mom' s house": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Dewitt",
"address2": null,
"prefix": null,
"address1": "41 Wexford Rd ",
"postalCode": "13214",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Dolores",
"phoneNumber": "212-555-4321",
"item-id": null,
"repositoryId": "se-140010",
"faxNumber": null,
"middleName": null,
"state": "NY"
},
"Home": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Syracuse",
"address2": "",
"prefix": null,
"address1": "21 Cedar Ave",
"postalCode": "13202",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-1977",
"item-id": null,
"repositoryId": "se-980031",
"faxNumber": null,
"middleName": null,
"state": "NY"
}
},
"shippingSurchargePriceList": {},
"firstPurchaseDate": "2020-06-23T13:50:49.686Z",
"profileType": null,
"loyaltyPrograms": [],
"lastPurchaseAmount": 80.99,
"registrationDate": "2020-06-23T12:36:03.000Z",
"sessionOrganization": null,
"lifetimeAOV": 80.99,
"id": "se-570031",
"derivedSalePriceList": null,
"homeAddress": {
"country": "US",
"lastName": null,
"types": [],
"address3": null,
"city": "Not available",
"address2": null,
"prefix": null,
"address1": "Not available",
"postalCode": "14201",
"companyName": null,
"county": null,
"suffix": null,
"firstName": null,
"phoneNumber": null,
"item-id": null,
"repositoryId": "se-960031",
"faxNumber": null,
"middleName": null,
"state": "Not available"
},
"daytimeTelephoneNumber": null,
"customerContactId": null,
"taxExempt": false,
"dynamicPropertyMapBigString": {},
"active": true,
"lastVisitDate": null,
"taxExemptionCode": null,
"previousVisitDate": null,
"version": 8,
"abandonedOrderCount": 0,
"firstName": "Kim",
"defaultCreditCard": {
"expirationYear": "2017",
"tokenExpiryDate": null,
"gatewayConfigId": null,
"expirationMonth": "1",
"creditCardType": "Visa",
"source": null,
"iin": null,
"token": null,
"cardProps": {},
"nameOnCard": null,
"creditCardNumber": "4539082039396288",
"tokenCreatedDate": "2020-06-23T12:36:03.388Z",
"cardSavedDate": null,
"billingAddress": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Buffalo",
"address2": "",
"prefix": null,
"address1": "451 Brooks Ave",
"postalCode": "14201",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-2150",
"item-id": null,
"repositoryId": "se-990031",
"faxNumber": null,
"middleName": null,
"state": "NY"
},
"id": "se-usercc110031",
"expirationDayOfMonth": null
},
"lifetimeCurrencyCode": "USD",
"derivedTaxExemptionCode": null,
"currentOrganization": null,
"secondaryOrganizations": [],
"shippingAddresses": [
{
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Syracuse",
"address2": "",
"prefix": null,
"address1": "21 Cedar Ave",
"postalCode": "13202",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-1977",
"item-id": null,
"repositoryId": "se-980031",
"faxNumber": null,
"middleName": null,
"state": "NY"
}
],
"derivedPriceListGroup": null,
"lastName": "Anderson",
"roles": [],
"numberOfOrders": 1,
"locale": "en",
"login": "kim@example.com",
"receiveEmailDate": null,
"sitePropertiesList": [
{
"site": {
"id": "siteUS"
},
"properties": {
"numberOfVisits": 0,
"GDPRProfileP13nConsentDate": null,
"GDPRProfileP13nConsentGranted": false,
"receiveEmail": "no",
"receiveEmailDate": null
}
}
],
"lifetimeSpend": 80.99,
"dynamicPropertyMapString": {},
"email": "kim@example.com",
"numberOfVisits": 0,
"siteProperties": {
"siteUS": {
"numberOfVisits": 0,
"GDPRProfileP13nConsentDate": null,
"GDPRProfileP13nConsentGranted": false,
"receiveEmail": "no",
"receiveEmailDate": null
}
},
"comments": [],
"receiveEmail": "no",
"priceListGroup": {
"isTaxIncluded": false,
"endDate": null,
"displayName": "Default Price Group",
"listPriceList": {},
"active": true,
"isPointsBased": false,
"locale": "en_US",
"basePriceListGroup": null,
"shippingSurchargePriceList": {},
"deleted": false,
"taxCalculationType": null,
"ancestorPriceListGroups": [],
"salePriceList": {},
"currency": {
"currencyType": null,
"symbol": "$",
"deleted": false,
"displayName": "US Dollar",
"fractionalDigits": 2,
"currencyCode": "USD",
"numericCode": "840"
},
"id": "defaultPriceGroup",
"includeAllProducts": true,
"startDate": null
},
"dateOfBirth": "1979-02-03T00:00:00.000Z",
"shippingAddress": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Syracuse",
"address2": "",
"prefix": null,
"address1": "21 Cedar Ave",
"postalCode": "13202",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-1977",
"item-id": null,
"repositoryId": "se-980031",
"faxNumber": null,
"middleName": null,
"state": "NY"
},
"firstVisitDate": null,
"middleName": null,
"lastActivity": null,
"billingAddress": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Buffalo",
"address2": "",
"prefix": null,
"address1": "451 Brooks Ave",
"postalCode": "14201",
"companyName": null,
"county": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-2150",
"item-id": null,
"repositoryId": "se-990031",
"faxNumber": null,
"middleName": null,
"state": "NY"
},
"dynamicPropertyMapDouble": {},
"derivedShippingSurchargePriceList": null,
"abandonedOrders": []
},
"order": {
"gwp": false,
"secondaryCurrencyCode": null,
"submittedDate": "2020-06-23T13:51:47.000Z",
"salesChannel": "default",
"configuratorId": null,
"uuid": "c0431f69-bb09-4d36-8d86-c75d041c6f49",
"organizationId": null,
"relationships": [
{
"paymentGroupId": "pg10413",
"amount": 80.99,
"relationshipType": "ORDERAMOUNTREMAINING",
"id": "r30390"
}
],
"exchangeRate": null,
"id": "o10411",
"state": "SUBMITTED",
"taxCalculated": true,
"combinedPriceInfos": null,
"commerceItems": [
{
"gwp": false,
"deactivationDate": null,
"returnedQuantity": 0,
"availabilityDate": null,
"billingProfileId": null,
"externalData": [],
"billingAccountId": null,
"preOrderQuantity": 0,
"assetKey": null,
"commerceItemId": "ci1000411",
"priceInfo": {
"discounted": false,
"amount": 49.99,
"secondaryCurrencyShippingSurcharge": 0,
"rawTotalPrice": 49.99,
"salePrice": 0,
"orderDiscountInfos": [],
"priceListId": "listPrices",
"itemDiscountInfos": [],
"quantityDiscounted": 0,
"amountIsFinal": false,
"onSale": false,
"shippingSurcharge": 0,
"discountable": true,
"currentPriceDetailsSorted": [
{
"secondaryCurrencyTaxAmount": 0,
"discounted": false,
"amount": 49.99,
"quantity": 1,
"configurationDiscountShare": 0,
"amountIsFinal": false,
"range": {
"lowBound": 0,
"highBound": 0,
"size": 1
},
"tax": 4,
"orderDiscountShare": 0,
"detailedUnitPrice": 49.99,
"currencyCode": "USD"
}
],
"currencyCode": "USD",
"listPrice": 49.99
},
"catalogId": null,
"externalRecurringChargeDetails": null,
"externalPriceDetails": null,
"actionCode": null,
"id": "ci1000411",
"state": "INITIAL",
"serviceId": null,
"locationInventoryInfoMap": {},
"serviceAccountId": null,
"quantity": 1,
"pointOfNoRevision": false,
"productId": "Product_21Cxi",
"parentAssetKey": null,
"externalId": null,
"originalCommerceItemId": null,
"rootAssetKey": null,
"transactionDate": null,
"catalogRefId": "Sku_21Dxy",
"customerAccountId": null,
"recurringChargePriceInfo": null,
"lineAttributes": [],
"catalogKey": null,
"productDisplayName": "Dora the Explorer - Season 1",
"shopperInput": {},
"activationDate": null,
"asset": false,
"backOrderQuantity": 0
}
],
"shippingGroups": [
{
"shippingMethod": "standardShippingMethod",
"description": "sg30411",
"submittedDate": null,
"priceInfo": {
"secondaryCurrencyTaxAmount": 0,
"discounted": false,
"shippingTax": 2,
"secondaryCurrencyShippingAmount": 0,
"amount": 25,
"rawShipping": 25,
"amountIsFinal": false,
"currencyCode": "USD"
},
"shipOnDate": null,
"actualShipDate": null,
"specialInstructions": {},
"shippingAddress": {
"country": "US",
"lastName": "Anderson",
"address3": null,
"city": "Syracuse",
"address2": null,
"prefix": null,
"address1": "21 Cedar Ave",
"companyName": null,
"jobTitle": null,
"postalCode": "13202",
"county": null,
"ownerId": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-1977",
"faxNumber": null,
"middleName": null,
"state": "NY",
"email": "kim@example.com"
},
"commerceItemRelationships": [
{
"availablePickupDate": null,
"inventoryLocationId": null,
"amount": 0,
"quantity": 1,
"pointOfNoRevision": false,
"relationshipType": "SHIPPINGQUANTITY",
"returnedQuantity": 0,
"preferredPickupDate": null,
"range": {
"lowBound": 0,
"highBound": 0,
"size": 1
},
"commerceItemExternalId": null,
"commerceItemId": "ci1000411",
"state": "INITIAL",
"id": "r30388"
}
],
"state": "INITIAL",
"id": "sg30411",
"stateDetail": null,
"trackingNumber": null,
"handlingInstructions": [],
"shippingGroupClassType": "hardgoodShippingGroup"
}
],
"freezeDate": null,
"taxExempt": false,
"profile": {
"lastName": "Anderson",
"firstName": "Kim",
"loyaltyPrograms": [],
"shippingAddress": {
"country": "US",
"lastName": "Anderson",
"types": [],
"address3": null,
"city": "Syracuse",
"address2": "",
"prefix": null,
"address1": "21 Cedar Ave",
"postalCode": "13202",
"jobTitle": null,
"companyName": null,
"county": null,
"ownerId": null,
"suffix": null,
"version": 2,
"firstName": "Kim",
"phoneNumber": "212-555-1977",
"repositoryId": "se-980031",
"faxNumber": null,
"middleName": null,
"state": "NY",
"id": "se-980031"
},
"middleName": null,
"login": "kim@example.com",
"parentOrganization": null,
"email": "kim@example.com"
},
"queuedOrderSubmitData": null,
"cartName": "o10411",
"paymentInitiatedEmailSent": false,
"payShippingInSecondaryCurrency": false,
"shippingGroupCount": 1,
"taxExemptionCode": null,
"createdByOrderId": null,
"orderAction": "order",
"submissionErrorMessages": [],
"profileId": "se-570031",
"activeQuoteOrderId": null,
"approverIds": [],
"agentId": "service",
"lastModifiedTime": 1592920307148,
"priceGroupId": "defaultPriceGroup",
"creationTime": 1592920249000,
"sourceSystem": "Cloud Commerce",
"gwpMarkers": [],
"locale": "en",
"paymentGroups": [
{
"expirationYear": "2035",
"amountAuthorized": 80.99,
"amount": 80.99,
"gatewayName": "CS-A",
"paymentProps": {
"uiIntervention": "sop"
},
"expirationMonth": "12",
"submittedDate": "2020-06-23T13:51:46.000Z",
"authorizationStatus": [
{
"authorizationDecision": "ACCEPT",
"transactionUuid": "ebb2112ff7da441d97ac67b4f9c35d90",
"amount": 80.99,
"statusProps": {
"req_card_type": "001",
"auth_cv_result": "M",
"auth_response": "100",
"req_transaction_type": "authorization,create_payment_token",
"req_locale": "en",
"req_payment_method": "card",
"decision_rmsg": "Test Review",
"auth_trans_ref_no": "77997054RWTFHZC4",
"auth_time": "2020-06-23T13:51:46.732Z",
"auth_code": "888888"
},
"transactionSuccess": true,
"errorMessage": "Request was processed successfully.",
"currency": "USD",
"reasonCode": "100",
"transactionId": "fj9o00reciqc7afedjlrohess2"
}
],
"IIN": null,
"token": "9997000108950573",
"paymentGroupClassType": "tokenizedCreditCard",
"creditCardNumber": "1111",
"paymentMethod": "tokenizedCreditCard",
"state": "AUTHORIZED",
"id": "pg10413",
"billingAddress": {
"country": "US",
"lastName": "Anderson",
"address3": null,
"city": "Syracuse",
"address2": null,
"prefix": null,
"address1": "21 Cedar Ave",
"companyName": null,
"jobTitle": null,
"postalCode": "13202",
"county": null,
"ownerId": null,
"suffix": null,
"firstName": "Kim",
"phoneNumber": "212-555-1977",
"faxNumber": null,
"middleName": null,
"state": "NY",
"email": "kim@example.com"
},
"debitStatus": [],
"currencyCode": "USD"
}
],
"payTaxInSecondaryCurrency": false,
"priceInfo": {
"secondaryCurrencyTaxAmount": 0,
"discounted": false,
"secondaryCurrencyShippingAmount": 0,
"amount": 49.99,
"secondaryCurrencyTotal": 0,
"manualAdjustmentTotal": 0,
"discountAmount": 0,
"tax": 6,
"rawSubtotal": 49.99,
"total": 80.99,
"shipping": 25,
"primaryCurrencyTotal": 49.99,
"amountIsFinal": false,
"currencyCode": "USD"
},
"submissionProgress": [],
"catalogId": null,
"totalCommerceItemCount": 1,
"externalContext": false,
"cancelReason": null,
"quoteInfo": null,
"taxPriceInfo": {
"secondaryCurrencyTaxAmount": 0,
"discounted": false,
"valueAddedTax": 0,
"amount": 6,
"countyTax": 3,
"isTaxIncluded": false,
"miscTax": 0,
"districtTax": 0,
"stateTax": 3,
"miscTaxInfo": {},
"countryTax": 0,
"cityTax": 0,
"amountIsFinal": false,
"currencyCode": "USD"
},
"lastModifiedDate": "2020-06-23T13:51:47.148Z",
"allowAlternateCurrency": false,
"approvalSystemMessages": [],
"approverMessages": [],
"paymentGroupCount": 1,
"submissionErrorCodes": [],
"recurringChargePriceInfo": null,
"organization": null,
"siteId": "siteUS"
}
}
A typical response from this webhook would be:
{
"responseCode": "8001"
}
External systems should respond with the response code 8001 when the validation is successful and an appeasement can be provided. Should the validation fail, the response code returns 8002, with a reason recorded in the reasonForValidationFailure
field.
Use the Appeasement Submit Webhook
The AppeasementSubmitWebhook
event webhook carries the required appeasement payload to external systems once the appeasement has been validated and saved. Its payload contains only the current appeasement information.
A typical request may be similar to the following:
{
"appeasement": {
"agentId": " BobAFrette",
"notes": "Customer complained that the order has arrived damaged, and asked for a
refund. Providing 15 USD.",
"orderId": "o11038",
"damagedLineItemId": "ci1235471",
"lastModifiedDate": "2020-07-08T10:34:09.698Z",
"appeasementRefunds": [
{
"refundType": "externalRefund",
"amount": 9,
"transactionNumber": "Refund Transaction Number",
"id": "100269",
"state": "INCOMPLETE",
"paymentGroupId": "pg11017",
"customerPreferredCardNumber": 0,
"refundDetails": "Refund Details",
"refundNotes": "Refund Notes",
"currencyCode": "USD",
"dateOfRefundProcess": "2017-02-08T18:30:00.000Z",
"refundSupportedTypes": true
}
],
"creationDate": "2020-07-08T10:34:09.698Z",
"profileId": "120000",
"state": "SUBMITTED",
"id": "app10438",
"originOfAppeasement": "agent",
"type": {
"displayName": "Order",
"description": "Appeasement to be applied on the order.",
"id": "order"
},
"reason": {
"readableDescription": "Item Arrived Damaged",
"id": "itemArrivedDamaged"
},
"comments": [
{
"agentId": " BobAFrette",
"comment": "Appeasement to be settled as a priority. Valued customer.",
"id": "100008",
"creationDate": "2020-07-08T10:34:09.687Z"
}
],
"submittedDate": "2020-07-08T10:34:09.688Z",
"damageDetails": "Item is Partially Damaged",
"customerType": true,
"appeasementAmount": 0,
"dateOfRequest": "2017-02-08T18:30:00.000Z"
}
}
Understand appeasement validation
By default the following validations are made when creating an order-based appeasement:
- The total appeasement amount, which includes the current appeasement refunds and the already completed appeasement refunds on the order, and the total refund amount from the already completed return request does not exceed the order total
- The refund amount for each refund type does not exceed the amount of the associated payment group
- The order on which the appeasement has been created should be in the FULFILLED state or the SUBMITTED state. The remorse period for the order should be over.
Create custom validations for appeasements
You can create custom validations for order level appeasements by setting the isOrderRequired
flag to true
. For example, you might want to create custom validations such as an Agent appeasement limit where the Agent cannot give more than a specified amount regardless of the order or profile. Or, you might want to create an order limit validation, where the Agent might not be able to give more than 15% of the order total. If you were to issue a shipping limit or a shipping total limit, the Agent could not issue anything beyond the shipping total, or a percentage of the shipping total.
Creating an appeasement total limit, which takes all the given appeasement totals from the appeasement history and sums them up, prohibits a particular profile from ever receiving an appeasement beyond this limit.
For example, if you have set the isOrderRequired
flag to false
, your system will not allow order-based appeasements. However, if you want to create a single order-based appeasement, bypassing your current setting, you would create a custom property to store the order ID. This would prevent the default orderId
from triggering the isOrderRequired
flag and allow you to create an order-based appeasement.
You could configure your system to skip order-based validations by performing the following steps:
- Create an
appeasementType
where theisOrderRequiredFlag
is set tofalse
. - Create a custom property at the appeasement level that holds the
orderId
, such asorderId2
. Then, when you create the appeasement, do not use the defaultorderId
property but the new customorderId2
field instead. - Ensure that the appeasement refund type is set to
external
, and that all of the payments are handled externally.
When you create custom properties, set the properties for which validation occurs by default to a system-allowed value:
orderId
- An order that must exist in the system.state
– The state for the given appeasement should beFULFILLED
.currencyCode
– This should match the currency of the order.paymentGroup
– When creating external refunds, it is best to use the webhook to validate the refund. When you use the webhook, you do not need to provide apaymentGroupId
value in theappeasementRefund
input.amount
– The appeasement cannot exceed the total of the order that corresponds to theorderId
.profile
– You can choose not to pass aprofileId
and use a different custom property instead that skips profile ID validation for order-based appeasements.
Validate APIs
By default, validations are performed on these fields when you create, update and submit appeasements.
Property | Description |
---|---|
reason |
The reason property indicates the reason for the appeasement. Possible reasons are:
|
state |
Appeasements can have the following states:
Note that the |
orderId |
If the appeasement type has a set isOrderRequired flag, the appeasement must have an order ID of an order in the FULLFILLED state, or a submitted order post its remorse period.
|
profileId |
The profile ID should be a registered customer.
If the appeasement type does not have an |
pymentGroupId |
This ID must be provided to identify the applicable refund for each card. |
currencyCode |
This property allows you to work with multi-currency orders. |
type |
The type property contains an order. If you have created a custom appeasement type with the Admin API, you can also provide its ID.
|
refundType |
The externalRefund is used for externally settled refunds. When using the Agent API, use the externalRefund for the refund type when invoking the validating webhook.
By default, the system updates the following refund instruments: |
amount |
All default appeasement refund objects should have non-zero amount values. |
To create additional validation, define rules/validation externally and have the appeasement request validated by a validation webhook.
Configure email
Each appeasement transaction is given a unique appeasement and authorization ID. The system also ensures that the credit is passed to downstream payment systems. Once the appeasement has been submitted and confirmed, the system triggers an email. Note that email notification occurs only when using the Agent API, and no email is triggered when using the Admin API. Emails will be issued when either the order ID, the profile ID or both are available.
If an order ID is provided and, if the order has been placed by a registered user, the email ID is picked from the profile. However, if the order has been a placed by an anonymous user, the system uses the email ID obtained from the shipping address.
Email templates contain the appeasement ID and level, the amount of the appeasement, payment mode and the payment mode identification number, any notes added, the submitted date and who the appeasement was submitted by, as well as any custom properties, order properties, profile properties and site properties that have been configured.
Perform returns with appeasements
Appeasements and returns have an impact on one another. Refund amounts are considered when generating an appeasement, and similarly, when an item is returned, the calculations for the refund amount considers all appeasement amounts that are specific to that order. For example, if there is an order with $10 and an appeasement is given for $2, a maximum of $8 can be refunded through return requests.
When the $2 has been removed from the order, the customer will not know what happened. You must add the removal to the widget to allow your customers to see the adjustments that have occurred due to the appeasements.
Displaying Appeasement adjustments
You can use the following properties to customize your template so that various details are property displayed.
Appeasement adjustment shares are captured in the appeasementRefundAdjustment
and secondaryCurrencyAppeasementRefundAdjustment
properties of the refundInfo
object. These properties are available by default in the Storefront and Agent APIs. You can configure a widget to display these properties by using the appropriate endpoints. By default in the Storefont and Agent interfaces, the refund details of a return request are also captured in the refundInfo
object in the returns view model, the return.js
file.
If you are using the default Agent return initiate refund page, the administration interface identifies any changes you have made in the appeasement adjustments. Based on these adjustments, the initiate refund button is disabled and the apply button is enabled so that the latest appeasement adjustment share details are reflected in the administration interface.
Use Storefront endpoints
When working with returns that contain appeasements, you can use the following Storefront endpoints:
Endpoint | Description |
---|---|
listReturnRequests |
When you issue a GET command to /orders/{id}/returnRequests , you get a list of return requests.
|
createReturnRequest |
When you issue a POST request, the values are populated based on the current appeasement requests and return request of the order.
|
getReturnRequest |
When you issue a GET request to /returnRequests/{id} , the values are recalculated based on the appeasements operations, such as new appeasements that are completed on the same order or the removal of an existing completed appeasement except for the completed state return requests.
|
calculateRefund |
When you issue a POST request to /returnRequests/calculateRefund , the values are populated based on the current appeasement requests and return requests of the order.
|
|
A POST request ensures that the appeasementRefundAdjustment and seoncdaryAppeasementRefundAdjustment properties are populated with values other than the default 0 value.
|
Use Admin endpoints
The appeasementRefundAdjustment
and the secondaryAppeasementRefundAdjustment
properties are added to the returns payload to capture the share of the appeasement requests. You can use the following Admin endpoints to show the property details:
Endpoint | Description | |
---|---|---|
getReturnRequest/returnRequests{id} |
This endpoint returns the available data. The values for the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment properties are not recalculated.
|
|
updateReturnRequest/returnRequests/{id} |
This endpoint will show the available data, but does not update the appeasementRefundAdjustment and secondaryRefundAdjustment properties as these properties are populated by the system.
|
Use Agent endpoints
The Agent API uses the following endpoints to work with returns:
Endpoint | Description |
---|---|
initiateReturn/returnRequests |
When you issue a POST request, this endpoint populates the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment properties to values based on the return amount. If you use the createReturnRequest and calculateRefundAmounts endpoints, the values of the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment properties are populated based on the current appeasement requests and return requests of the order
|
searchReturns/returnRequests |
When you these issue a GET request, this endpoint returns the data available; however, there is no recalculation of the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment properties.
|
getReturnRequest/returnRequests/{id} |
When you issue a GET command, the values of the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment will be recalculated based on the appeasements operations.
|
updateReturnRequest/returnRequests/{id} |
When you issue a PUT command, the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment property values will be recalculated based on the appeasements operations. This could be operations like creating new appeasements that are completed on the same order or removing an existing completed appeasement yet maintain the completed state return requests for the operation’s adjustRefundAmounts and initiateRefund totals.
|
calculateRemainingRefund /returnRequests/{id}/calculateRemainingRefund |
When you issue a POST request, the values of the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment properties is recalculated based on the appeasements operations such as new appeasements that are completed on the same order.
|
receiveReturnRequest /returnRequests/{id}/receive |
When you issue a PUT request, this endpoint returns the available data . There is no recalculation of the appeasementRefundAdjustment and secondaryAppeasementRefundAdjustment properties.
|
Note that by default, Commerce does not display the appeasementRefundAdjustment
and secondaryAppeasementRefundAdjustment
in the administration interface.
For an order appeasement type, use a refund mode that corresponds to a payment method that was used in the order. However, payments that are not settled will not be available for the internal refund process, so for these payment groups, the system assumes an externalRefund
option. Validations for other refund modes generated from an external refund are done using external refund validation webhooks.
Note that orders that have multiple appeasements can use multiple currencies. Additionally, you can perform refunds with multiple currencies within a single appeasements.
Understand refund calculations with appeasements
By default, an appeasement’s refund type corresponds to the default payment types that are available for the appeased order. Default internal refund types include:
creditCard
– This refund type includes CyberSource, Chase Credit Card andgenericCreditCard
and is the accesses using the default refund APIphysicalGiftCard
– which includesgenericGiftCard
customCurrencyPaymentGroup
– This includesloyaltyPoints
onlinePaymentGroup
– which includes PayPalstoreCredit
– which uses the Generic payment webhook for issuing the refundtokenizedCreditCard
– This includes the CyberSource payment gateway
Default refund types for external systems include:
payU Latem
instore
cash
invoice
coupon
– no refund amount is processed when using this refund type
By default, refund calculations are made on the maximum refund amount (the allowed limit based on existing refunds on the payment type), the order total and previous appeasements made on the order. When you create an external appeasement refund, the appeasement is calculated separately.
Work with External Systems
Appeasements refunds can be customized to use an external appeasement refund mode, which is then handled by an external system and then returned to the Commerce system. External appeasements can be issued using credit cards, gift cards or other methods. You can also issue non-monetary appeasements, such as coupons and vouchers. Note that multiple external appeasement modes are available, however you cannot combine monetary and non-monetary appeasements.
For orders that are placed with cash, invoices, and gift cards, appeasements must be performed using an external payment because Commerce cannot settle them internally. You can also configure external payment to allow gift vouchers or promotion codes that are not part of your order payment system. When you create an external appeasements, you need to configure the Submit Appeasement Event Webhook in the Admin API so that you will receive notification when an appeasement is successfully created.
Once appeasements are validated, they are sent to the external system through the Appeasement Submit Event webhook. You can import appeasements from an external appeasement system using the Admin API.
Update external appeasements
You must update the Commerce system whenever you generate external appeasements. Once the appeasement has been settled in the external system, the state of the appeasement and appeasement refund should be marked in the system as COMPLETED
. This identifies the appeasement amount in the total amount validation. If the external appeasement is not marked COMPLETED
, it will not be considered for subsequent returns and refunds. You can mark the appeasement with the update appeasement endpoint by issuing a PUT command in the following format:
/ccadmin/v1/appeasements/{appeasementId}