Provide Event Handlers
- 1. Initialize checkout
- 2. Shipping address update
- 3. Delivery option update
- 4. Points and Promo Codes
- 5. Complete checkout
- 6. Cancel checkout
- 6. Handling errors
[Step 3 of 8] Five event handlers can be defined and registered in the button JavaScript code. The event handlers receive cart-level details from and communicate to Amazon Pay, which will be rendered on the checkout page:
- onInitCheckout - event handler to initialize checkout (mandatory)
- onShippingAddressSelection - event handler for customer shipping address update (optional)
- onDeliveryOptionSelection - event handler for customer delivery option update (optional)
- onCompleteCheckout - event handler to complete checkout (mandatory)
- onCancel - event handler when customer abandons the checkout (mandatory)
- onMerchantManagedPaymentMethodSelection - event handler should be the authoritative source of the redeemed points and promo codes (optional)
1. Initialize checkout
The Buyer starts checkout by selecting Amazon Pay as the payment method. Amazon Pay authenticates the buyer, collects their consent and defaults to their choice of shipping address and payment method. After this onInitCheckout event handler/javascript callback function is invoked.
Amazon Pay will provide you with buyer details, based on the scopes requested. Amazon Pay expects cart information (e.g. amounts, tax, delivery options, item level details). Please find a list of supported elements in CartDetails Response. The information you share with Amazon Pay will be rendered on the Amazon Pay Checkout page.
/** Invokes when initiated checkout and authenticated **/
onInitCheckout: async function (event) {
try {
// Perform your server-side request to fetch details
const cartDetails = await fetch("/your-server/initCheckout", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify({
shippingAddress: event.shippingAddress,
scopes: event.scopes,
checkoutLanguage: event.checkoutLanguage,
}),
});
return {
totalBaseAmount: cartDetails.totalBaseAmount,
totalTaxAmount: cartDetails.totalTaxAmount,
totalShippingAmount: cartDetails.totalShippingAmount,
totalChargeAmount: cartDetails.totalChargeAmount,
totalOrderAmount: cartDetails.totalOrderAmount,
totalDiscountAmount: cartDetails.totalDiscountAmount,
lineItems: cartDetails.lineItems,
deliveryOptions: cartDetails.deliveryOptions,
checkboxes: cartDetails.checkboxes,
freeForm: cartDetails.freeForm
};
} catch (err) {
// something went wrong with your server call
console.err(err);
return {
status: "error",
reasonCode: "unknownError",
};
}
};
onInitCheckout event input
| Parameter
|
Description
|
| scopes Type: Scopes |
Details about the buyer, such as their unique identifier, name, and email that are shared based on scope requested
|
| checkoutLanguage Type: string |
Buyer selected checkout language.
|
| shippingAddress Type: Address |
Buyer selected shipping address.
|
{
"buyer": { // shared based on scope requested
"buyerId": "buyerId",
"name": "name-1",
"email": "name@amazon.com",
"phoneNumber": "800-000-0000"
},
"billingAddress": { // shared based on scope requested
"name": "Work",
"addressLine1": "440 Terry Ave",
"addressLine2": "",
"addressLine3": "",
"city": "Seattle",
"county": "King",
"district": "Seattle",
"stateOrRegion": "WA",
"postalCode": "98121",
"countryCode": "US",
"phoneNumber": "800-000-0000"
},
"shippingAddress": { // Null for PayOnly product type
"name": "Susie Smith",
"addressLine1": "10 Ditka Ave",
"addressLine2": "Suite 2500",
"addressLine3": null,
"city": "Chicago",
"county": null,
"district": null,
"stateOrRegion": "IL",
"postalCode": "60602",
"countryCode": "US",
"phoneNumber": "800-000-0000"
}
}
onInitCheckout handler output
| Attribute | Type | Description | Required | Default |
|---|---|---|---|---|
| lineItems | LineItem | Details for each item in cart | No | N/A |
| deliveryOptions | List<DeliveryOption> | Available delivery options | Yes for PayAndShip No for PayOnly |
N/A |
| totalShippingAmount | Price | Total amount for shipping | Yes | N/A |
| totalBaseAmount | Price | Total amount for items in cart | Yes | N/A |
| totalTaxAmount | Price | Total amount for tax | Yes | N/A |
| totalDiscountAmount | Price | Total sum of discounts - sum of line item discount, cart level discount and coupon code discount | No | N/A |
| totalChargeAmount | Price | Total amount for this transaction | Yes | N/A |
| totalOrderAmount | Price | Total order amount for the transaction. This field should be set when merchant wants to perform multiple authorization. | No | N/A |
| checkboxes | Checkbox (onInit response) | Checkboxes details | No | N/A |
| freeForm | FreeForm (onInit response) | Freeform details | No | N/A |
| isBuyerRecognized | Boolean | Denotes if buyer is logged in with the merchant | No | FALSE |
| addOnFeatures | List<Enum> | Set of add on features, merchant wants to enable on AmazonPay Checkout | No | Empty |
| points | MerchantPoints | Data related to merchant points | No. Yes if POINTS feature is enabled |
null |
MerchantPoints
| Attribute | Type | Description | Required | Default |
|---|---|---|---|---|
| name | String | Name of the merchant points program | Yes | N/A |
| conversionRatio | String | Conversion ratio for points to currency | Yes | N/A |
| pointsEarned | String | Points earned from this transaction | No | N/A |
| pointsAvailable | String | Total points available for redemption | Yes | N/A |
| redeemedPoints | RedeemedMerchantPoints | Details of points being redeemed | No | null |
RedeemedMerchantPoints
| Attribute | Type | Description | Required | Default |
|---|---|---|---|---|
| points | String | Points redeemed by customer | Yes | N/A |
| amount | Price | Amount equivalent to redeemed points | Yes | N/A |
MerchantPromoCodes
| Attribute | Type | Description | Required | Default |
|---|---|---|---|---|
| redeemedPromoCodes | List<RedeemedMerchantPromoCode> | List of redeemed promo codes | No | null |
RedeemedMerchantPromoCode
| Attribute | Type | Description | Required | Default | ||||
|---|---|---|---|---|---|---|---|---|
| promoCode | String | Promo code redeemed by customer | Yes | N/A | ||||
| amount | Price | Amount equivalent to redeemed points | Yes | N/A | Indicates merchant to reserve points and promo codes | Yes | FALSE |
{
"totalShippingAmount":{
"amount":"5",
"currencyCode":"USD"
},
"totalBaseAmount":{
"amount":"20",
"currencyCode":"USD"
},
"totalTaxAmount":{
"amount":"0.5",
"currencyCode":"USD"
},
"totalOrderAmount":{
"amount":"20.5",
"currencyCode":"USD"
},
"totalChargeAmount":{
"amount":"20.5",
"currencyCode":"USD"
},
"totalDiscountAmount":{
"amount":"5",
"currencyCode":"USD"
},
"isBuyerRecognized": true/false, // Default: false
"addOnFeatures": ["POINTS", "PROMO_CODE", "GIFT"],
"points": {
"name": "<name>",
"conversionRatio": "10"
"pointsEarned": "10",
"pointsAvailable":"150"
}
"lineItems":[
{
"id": "id-of-the-item",
"title":"item-title-1",
"variantTitle":"variant-title",
"quantity":"2",
"listPrice": {
"amount":"10",
"currencyCode":"USD"
},
"totalListPrice":{
"amount":"20",
"currencyCode":"USD"
}
}
],
"deliveryOptions":[{
"id":"abc_shipping-02-25.11",
"price":{
"amount":"5",
"currencyCode":"USD"
},
"shippingMethod":{
"shippingMethodName":"shipping-method-name",
"shippingMethodCode":"shipping-method-code"
},
"shippingEstimate":[{
"timeUnit":"HOUR",
"value":2
}],
"isDefault":true
}],
"checkboxes": [
{
"type" : "MERCHANT_DISCLOSURE", // required (atleast 1, atmost 4)
"attributes" : {
"termsAndConditionsUrl":"https://www.my.domain/mytandcs", // required
"privacyPolicyUrl": "https://www.my.domain/privacyIsKey" // required
}
},
{
"type" : "NEWSLETTER_SIGN_UP",
"attributes" : {
"learnMoreUrl":"https://www.my.domain/mytandcs" // optional
}
},
{
"type" : "MEMBERSHIP_SIGN_UP",
"attributes" : {
"programName":"name", // required
"learnMoreUrl":"https://www.my.domain/mytandcs" // optional
}
},
{
"type" : "SMS_DELIVERY_NOTIFICATION",
"attributes" : {
"learnMoreUrl":"https://www.my.domain/mytandcs" // optional
}
},
{
"type" : "RIGHT_OF_WITHDRAWL",
"attributes" : {
"termsAndConditionsUrl":"https://www.my.domain/mytandcs", // required
}
},
{
"type" : "MERCHANT_MULTIPLE_DISCLOSURES",
"attributes" : {
"primaryPolicyName": "name1", // required
"primaryPolicyUrl": "url1", // required
"secondaryPolicyName": "name2", // optional
"secondaryPolicyUrl": "url2", // optional
"tertiaryPolicyName": "name3", // optional
"tertiaryPolicyUrl": "url3" // optional
}
}
],
"freeForm": { // optional (if not present then exclude this feature)
"placeholderText": "Please add delivery instructions", // required
"limit": 3000 // optional
},
}
See the CartDetails type for a full definition.
Note :
- In case
isBuyerRecognizedisfalse, we will not render merchant points on UI. - If
isBuyerRecognizedistrue, but balanceMerchantPoints is null or empty then, we will not render merchant points on UI and log error on UI. - We will validate the response data before consumption. In case of invalid data provided, we will fallback to default values.
onInitCheckout handler errors
In case you can't fullfil the order based on the data supplied to you, please return an error response to Amazon Pay.
{
"status": "error",
"reasonCode": "shippingAddressInvalid"
}
| ReasonCode
|
Description
|
| shippingAddressInvalid | The supplied shipping address can't be accepted by you. The buyer will be requested to select a different address. |
| unknownError | For any other error. The buyer will see a generic error message and requested to return to your shop.
|
2. Shipping address update
When the buyer selects or changes the preferred shipping address, Amazon Pay will invoke this event handler.
/** Invokes when customer has selected different shipping address **/
onShippingAddressSelection: async function (event) {
try {
// Perform your server-side request to fetch details
const cartDetails = await fetch("/your-server/addressUpdate", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify({
shippingAddress: event.shippingAddress,
}),
});
return {
totalBaseAmount: cartDetails.totalBaseAmount,
totalTaxAmount: cartDetails.totalTaxAmount,
totalShippingAmount: cartDetails.totalShippingAmount,
totalChargeAmount: cartDetails.totalChargeAmount,
totalOrderAmount: cartDetails.totalOrderAmount,
totalDiscountAmount: cartDetails.totalDiscountAmount,
lineItems: cartDetails.lineItems,
deliveryOptions: cartDetails.deliveryOptions,
};
} catch (err) {
// something went wrong with your server call
console.err(err);
return {
status: "error",
reasonCode: "unknownError",
};
}
};
onShippingAddressSelection event input
| Parameter
|
Description
|
| shippingAddress Type: Address |
Buyer selected shipping address.
|
{
"shippingAddress": {
"name": "Susie Smith",
"addressLine1": "10 Ditka Ave",
"addressLine2": "Suite 2500",
"addressLine3": null,
"city": "Chicago",
"county": null,
"district": null,
"stateOrRegion": "IL",
"postalCode": "60602",
"countryCode": "US",
}
}
onShippingAddressSelection handler output
{
"totalShippingAmount":{
"amount":"5",
"currencyCode":"USD"
},
"totalBaseAmount":{
"amount":"20",
"currencyCode":"USD"
},
"totalTaxAmount":{
"amount":"0.5",
"currencyCode":"USD"
},
"totalOrderAmount":{
"amount":"20.5",
"currencyCode":"USD"
},
"totalChargeAmount":{
"amount":"20.5",
"currencyCode":"USD"
},
"totalDiscountAmount":{
"amount":"5",
"currencyCode":"USD"
},
"lineItems":[
{
"id": "id-of-the-item",
"title":"item-title-1",
"variantTitle":"variant-title",
"quantity":"2",
"listPrice": {
"amount":"10",
"currencyCode":"USD"
},
"totalListPrice":{
"amount":"20",
"currencyCode":"USD"
}
}
],
"deliveryOptions":[{
"id":"abc_shipping-02-25.11",
"price":{
"amount":"5",
"currencyCode":"USD"
},
"shippingMethod":{
"shippingMethodName":"shipping-method-name",
"shippingMethodCode":"shipping-method-code"
},
"shippingEstimate":[{
"timeUnit":"HOUR",
"value":2
}],
"isDefault":true
}]
}
See the CartDetails type for a full definition.
onShippingAddressSelection handler errors
In case you can't fullfil the order based on the data supplied to you, please return an error response to Amazon Pay.
{
"status": "error",
"reasonCode": "shippingAddressInvalid"
}
| ReasonCode
|
Description
|
| shippingAddressInvalid | The supplied shipping address can't be accepted by you. The buyer will be requested to select a different address. |
| unknownError | For any other error. The buyer will see a generic error message and requested to return to your shop.
|
3. Delivery option update
When the buyer selects or changes the preferred shipping option, Amazon Pay will invoke this event handler.
/** Invokes when customer has selected different shipping address **/
onDeliveryOptionSelection: async function (event) {
try {
// Perform your server-side request to fetch details
const cartDetails = await fetch("/your-server/deliveryOptionUpdate", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify({
selectedDeliveryOption: {
id: event.deliveryOptions.id,
amount: event.deliveryOptions.amount,
displayName: event.deliveryOptions.displayName,
},
}),
});
return {
totalBaseAmount: cartDetails.totalBaseAmount,
totalTaxAmount: cartDetails.totalTaxAmount,
totalShippingAmount: cartDetails.totalShippingAmount,
totalChargeAmount: cartDetails.totalChargeAmount,
totalOrderAmount: cartDetails.totalOrderAmount,
totalDiscountAmount: cartDetails.totalDiscountAmount,
lineItems: cartDetails.lineItems, // optional
deliveryOptions: cartDetails.deliveryOptions, // optional
};
} catch (err) {
// something went wrong with your server call
console.err(err);
return {
status: "error",
reasonCode: "unknownError",
};
}
};
onDeliveryOptionSelection event input
| Parameter
|
Description
|
| deliveryOptions Type: DeliveryOption (Event input) |
Buyer selected delivery option.
|
{
"deliveryOptions": {
"id": "do-2",
"displayName": "Option 2",
"amount": "5"
}
}
onDeliveryOptionSelection handler output
You can re-calculate the cart details based on the delivery option selected by the buyer. Please return anything that changed based on the delivery option selection. At a minimum the required amount fields need to be returned.
{
"totalShippingAmount":{
"amount":"5",
"currencyCode":"USD"
},
"totalBaseAmount":{
"amount":"20",
"currencyCode":"USD"
},
"totalTaxAmount":{
"amount":"0.5",
"currencyCode":"USD"
},
"totalOrderAmount":{
"amount":"20.5",
"currencyCode":"USD"
},
"totalChargeAmount":{
"amount":"20.5",
"currencyCode":"USD"
},
"totalDiscountAmount":{
"amount":"5",
"currencyCode":"USD"
}
}
See the CartDetails type for a full definition.
onDeliveryOptionSelection handler errors
In case you can't fullfil the order based on the data supplied to you, please return an error response to Amazon Pay.
{
"status": "error",
"reasonCode": "deliveryOptionInvalid"
}
| ReasonCode
|
Description
|
| deliveryOptionInvalid | The supplied delivery option can't be accepted by you. The buyer will be requested to select a different shipping option. |
| unknownError | For any other error. The buyer will see a generic error message and requested to return to your shop.
|
4. Points and Promo Codes
This event handler is used to inform merchants about the merchant points (in currency amount) and promo code selected by customers. This event handler should be the authoritative source of the redeemed points and promo codes. The values provided in the request should override the existing values at merchant side. If they are set to null, it means customer has chosen not to apply points and promo codes.
AuthorizationRequired Flag - It indicates to merchant that these amount of points and promo codes are required to be reserved for the current transaction.
onMerchantManagedPaymentMethodSelection event input
| Attribute | Type | Description | Required | Default |
|---|---|---|---|---|
| promoCode | String | Promo code redeemed by customer | No | N/A |
| points | Price | Amount equivalent to redeemed points | No | N/A |
| authorizationRequired | Boolean |
{
"promoCodes": ["<promo-code>"],
"points": {
"amount":"100", // currency amount
"currencyCode":"JPY"
},
"authorizationRequired": true/false // deafult: false
}
onMerchantManagedPaymentMethodSelection handler output
{
"totalBaseAmount":{
"amount":"20",
"currencyCode":"JPY"
},
"totalShippingAmount":{
"amount":"5",
"currencyCode":"JPY"
},
"totalTaxAmount":{
"amount":"0.5",
"currencyCode":"JPY"
},
"totalOrderAmount":{
"amount":"20.5",
"currencyCode":"JPY"
},
"totalChargeAmount":{
"amount":"20.5",
"currencyCode":"JPY"
},
"totalDiscountAmount":{
"amount":"5",
"currencyCode":"JPY"
},
"points": {
"pointsEarned": "10", // earned points could change based on redeemedPoints
"pointsAvailable":"150" // total points available without subtracting redeemedPoints
"redeemedPoints":{
"points": "100",
"amount": {
"amount":"100", // should be same as merchantPoints amount in request
"currencyCode":"JPY"
}
},
}
"promoCodes" : {
"redeemedPromoCodes": [{
"promoCode": "<promo-code>", // should be same as promo code in request
"amount":{
"amount":"10",
"currencyCode":"JPY"
}
}]
}
}
Error Response
{
status: "error", // ["error"]
reasonCode: "maxPointsBreached", // ["unknownError", ....]
}
{
status: "error",
reasonCode: "promoCodeInvalid", // ["promoCodeAlreadyUsed", "promoCodeExpired"]
message: "PC100" // the promo code which is invalid, already used or expired
}
// Note: Message attribute is required to contain promo code value to indicate
// to which promo code the error is associated with.
// In case of multiple promo codes, merchant should return error code one at a time.
- maxPointsBreached : The error code comes when provided points is greater than the balance points available with merchant (total balance points could have changed between loading Pre-order page and submitting this call).
- promoCodeInvalid : The error code will be returned when merchant does not recognize the provided promo code. AmazonPay hosted page will show error message, and let customer enter another promo code.
- promoCodeAlreadyUsed: The error code will be returned when the promo code already has been used and cannot be used further. AmazonPay hosted page will show error message, and let customer enter another promo code.
- promoCodeExpired : The error code will be returned when the promo code has expired at merchant side. AmazonPay hosted page will show error message, and let customer enter another promo code.
- buyerInvalid : The error code will be returned when merchant does not recognize the buyer (buyer logged out during checkout).
-
unknownError : The error code will be return when merchant system has issues processing this event handler. In this case Amazon Pay hosted page will show generic error message, and let customer go back to merchant website.
- Note : In case of mismatch between Amazon Pay calculated redeemedPoints and merchant provided redeemedPoints, we will fall back to generic error and let buyer enter points again.
Expected Response
- Merchant Points : If requested merchant points(in currency amount) are valid, then merchant should return equivalent merchant points in redeemedPoints field. Optionally, they could send pointsEarned and pointsAvailable if they have been changed. In case of invalid points amount, merchant should return error response.
- pointsAvailable = updated available points + redeemed points. pointsAvailable should always be the total number of available points including redeemed points as redeemed points are not yet reserved and are still available for redemption. This will become significant in case of concurrent multiple checkout sessions. pointsAvailable could be updated if buyer has redeemed points using another checkout session. Refer Appendix 1.
- Note: Merchant system are expected to return updated pointsEarned and pointsAvailable, otherwise we will use the older received values.
- Promo Code : If requested promo code is valid, then merchant should return equivalent currency amount, otherwise return the error response.
Removal of points and promo code
- Merchant Points : Merchant points could become zero or null. Currently, zero and null merchant points are conveying the same intention of not using any points. So merchant could return zero or null in response.
- If customer has removed earlier set redeemed points the we are sending zero redeemed points.
- Promo Code: In case of removal of promo code, we will send null and merchant should return null in response.
Note: Merchants need to understand these null/zero attributes as removal of these attributes, update the session at their end with these values (remove points and promo code), and return appropriate response (null/zero response).
AuthorizationRequired Flag
authorizationRequired flag is used to indicate to merchant system that given points and promo codes are used for the transaction and should be reserved at merchant side. Additionally, these points and promo codes should not be available for use in other transactions unless released during cancel or error in transaction.
- When authorizationRequired is false, merchants are required to return validated promo code and merchant points calculation in response.
- When authorizationRequired is true, merchants are required to return validated promo code and merchant points calculation in response, along with reserving the mentioned points and promo codes for the transaction at their end.
Zero Charge Orders
- ChargePermission - It will be closed right away with reason AMAZON_CLOSED.
- Charge - Merchant should not create charge for zero charge orders.
- PaymentIntent - It will always be CONFIRM.
5. Complete checkout
When the buyer clicks purchase to complete checkout, Amazon Pay will invoke this event handler. You need to take the data from the event and perform a Finalize Checkout Session API call to complete the checkout.
/** Invokes when customer has selected different shipping address **/
onCompleteCheckout: async function (event) {
try {
// Perform your server-side request to fetch details
const result = await fetch("/your-server/finalizeCheckout", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: JSON.stringify({
checkoutSessionId: event.amazonCheckoutSessionId,
billingAddress: event.billingAddress,
paymentDescriptor: event.paymentDescriptor,
checkboxes: event.checkboxes,
freeform: event.freeform
}),
});
} catch (err) {
// something went wrong with your server call
console.err(err);
return {
status: "error",
reasonCode: "unknownError",
};
}
};
onCompleteCheckout event input
As part of this callback, we share the final billingAddress and paymentDescriptor which can be used to update your database. This billing address may be different from the one shared as part of onInitCheckout callback in cases where buyer changes PI.
The input to this function is checkoutSessionId. You should take this session id and use it on your backend to call FinalizeCheckoutSession API. On the front-end, you should show a processing page / spinner. Successful response of this API merchant should render thank you page.
| Attribute | Type | Description | Required | Default |
|---|---|---|---|---|
| amazonCheckoutSessionId | String | AmazonPay's checkoutSessionId | Yes | N/A |
| billingAddress | Address | AmazonPay's billingAddress | No | N/A |
| paymentDescriptor | String | Amazon Pay-provided description for buyer-selected payment instrument Max length: 64 characters/bytes |
No | N/A |
| buyerAddtionalInfo | BuyerAddtionalInfo | Additional buyer info that collected on SPC page | Yes if merchant requested | EU only |
| checkboxes | Checkbox (onComplete input) | Checkboxes checked/unchecked by buyer | Yes if merchant requested | NA |
| freeform | String | Freeform entered by buyer | Yes if merchant requested | NA |
{
"amazonCheckoutSessionId": "d0966c90-f8f6-4835-9129-1f743cf525bc",
"billingAddress": { // shared based on scope requested
"name": "Work",
"addressLine1": "440 Terry Ave",
"addressLine2": "",
"addressLine3": "",
"city": "Seattle",
"county": "King",
"district": "Seattle",
"stateOrRegion": "WA",
"postalCode": "98121",
"countryCode": "US",
"phoneNumber": "800-000-0000"
},
"paymentDescriptor": "Visa ****1111 (Amazon Pay)",
"freeForm": "free form customer inputted text",
"checkboxes": [
{
"template": "MERCHANT_DISCLOSURE",
"isChecked": true
},
{
"template": "MERCHANT_MULTIPLE_DISCLOSURES",
"isChecked": true
}
]
}
onCompleteCheckout handler output
No output for this callback. Successful response of this API merchant should render thank you page
6. Cancel checkout
When the buyer clicks Cancel and return to merchant hyperlink, Amazon Pay will invoke this event handler. onCancel callback is used to close the amazon pay checkout popup window, buyer returns back to merchant page. If onCancel is received after successful authorization of merchant points and promo code then merchants are required to release them back to the customer account.
onCancel: function (event) {
// Takes buyer back to cart page or product details automatically
}
onCancel event input
No input required for this callback
onCancel event output
No output required for this callback
6. Handling errors
onError callback is used to communicate to merchant if any error occurred and merchant may take any action. We don't close the amazon pay window in this case. If onError is received after successful authorization of merchant points and promo code then merchants are required to release them back to the customer account.
onError: function (event) {
console.err(event);
}
onError event input
| Attribute | Type | Description |
|---|---|---|
| message | String | Error message |
onError event output
No output required for this callback

