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:

amount

paymentGroupId

currencyCode

refundType

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 createReason endpoint in the Admin API. Default reasons include:

orderArrivedLate

orderArrivedDamaged

itemArrivedLate

itemArrivedDamaged

didNotLikeItem

goodwillGesture

productComplaint

refundType

This property, which is in appeasementRefund, identifies the type of refund to issue. The supported refund types are:

creditCard – This refund type is used for Chase Credit Card.

customCurrencyGroup – This refund type is used for loyalty.

externalRefund – This refund type is used for invoice, cash, payUlantam, coupons and instorePaymentMethod.

onlinePaymentGroup – This refund type includes PayPal.

physicalGiftCard – This refund type is used for gift cards.

storeCredit – This issues a store credit.

tokenizedCreditCard – This refund type is used for CyberSource payments.

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 to external. If the comment is added using the Agent API, the agentId 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 the isOrderRequiredFlag is set to false.
  • Create a custom property at the appeasement level that holds the orderId, such as orderId2. Then, when you create the appeasement, do not use the default orderId property but the new custom orderId2 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 be FULFILLED.
  • 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 a paymentGroupId value in the appeasementRefund input.
  • amount – The appeasement cannot exceed the total of the order that corresponds to the orderId.
  • profile – You can choose not to pass a profileId 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:

orderArrivedLate

orderArriveDamaged

itemArrivedLate

itemArrivedDamaged

didNotLikeItem

incorrectItem

goodwillGesture

productComplaint

state Appeasements can have the following states:

INCOMPLETE – An appeasement remains in this state until submitted.

SUBMITTED – An appeasement reaches this state once its validation is successful.

COMPLETE – An appeasement is marked COMPLETE by an external system once all of the refunds are settled.

Note that the state property can only be sent with the Admin API.

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 isOrderRequired flag set, the profileId is mandatory in the Agent API.

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:

creditCard

storeCredit

tokenizedCreditCard

onlinePaymentGroup

physicalGiftCard

customCurrencyPaymentGroup

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.

initiateReturn and

validateReturns

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 and genericCreditCard and is the accesses using the default refund API
  • physicalGiftCard – which includes genericGiftCard
  • customCurrencyPaymentGroup – This includes loyaltyPoints
  • onlinePaymentGroup – which includes PayPal
  • storeCredit – which uses the Generic payment webhook for issuing the refund
  • tokenizedCreditCard – 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}