---
title: Provide Event Handlers
url: amazon-pay-buy-now-checkout/provide-event-handlers.html
---

**[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)

* TOC
{:toc}
{::options toc_levels="3" /}

---

### 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](../amazon-pay-api-v2/buy-now-checkout.html#type-cartdetails). The information you share with Amazon Pay will be rendered on the Amazon Pay Checkout page.

```JavaScript
/** 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,
    };
  } catch (err) {
    // something went wrong with your server call
    console.err(err);
    return {
      status: "error",
      reasonCode: "unknownError",
    };
  }
};
```

#### onInitCheckout event input

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>Parameter
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>scopes<br><br>Type: <a href="../amazon-pay-api-v2/buy-now-checkout.md#type-scopes">Scopes</a>
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Details about the buyer, such as their unique identifier, name, and email that are shared based on scope requested
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>checkoutLanguage<br><br>Type: string
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Buyer selected checkout language.
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>shippingAddress<br><br>Type: <a href="../amazon-pay-api-v2/buyer.md#type-address">Address</a>
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Buyer selected shipping address.
                <br /></td>
        </tr>
    </tbody>
</table>

```JSON
{
    "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

```JSON
{
    "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](../amazon-pay-api-v2/buy-now-checkout.html#type-cartdetails) type for a full definition.

#### 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.

```JSON
{
    "status": "error",
    "reasonCode": "shippingAddressInvalid"
}
```

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>ReasonCode
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>shippingAddressInvalid</td>
            <td style='text-align: left;vertical-align: top;'>The supplied shipping address can't be accepted by you. The buyer will be requested to select a different address.</td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>unknownError</td>
            <td style='text-align: left;vertical-align: top;'>For any other error. The buyer will see a generic error message and requested to return to your shop.
                <br /></td>
        </tr>
    </tbody>
</table>

---

### 2. Shipping address update

When the buyer selects or changes the preferred shipping address, Amazon Pay will invoke this event handler.

```JavaScript
/** 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

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>Parameter
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>shippingAddress<br><br>Type: <a href="../amazon-pay-api-v2/buyer.md#type-address">Address</a>
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Buyer selected shipping address.
                <br /></td>
        </tr>
    </tbody>
</table>

```JSON
{
    "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

```JSON
{
    "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](../amazon-pay-api-v2/buy-now-checkout.html#type-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.

```JSON
{
    "status": "error",
    "reasonCode": "shippingAddressInvalid"
}
```

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>ReasonCode
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>shippingAddressInvalid</td>
            <td style='text-align: left;vertical-align: top;'>The supplied shipping address can't be accepted by you. The buyer will be requested to select a different address.</td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>unknownError</td>
            <td style='text-align: left;vertical-align: top;'>For any other error. The buyer will see a generic error message and requested to return to your shop.
                <br /></td>
        </tr>
    </tbody>
</table>

---

### 3. Delivery option update

When the buyer selects or changes the preferred shipping option, Amazon Pay will invoke this event handler.

```JavaScript
/** 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

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>Parameter
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>deliveryOptions<br><br>Type: <a href="../amazon-pay-api-v2/buy-now-checkout.md#type-deliveryoption-event-input">DeliveryOption (Event input)</a>
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Buyer selected delivery option.
                <br /></td>
        </tr>
    </tbody>
</table>

```JSON
{
    "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.

```JSON
{
    "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](../amazon-pay-api-v2/buy-now-checkout.html#type-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.

```JSON
{
    "status": "error", 
    "reasonCode": "deliveryOptionInvalid"
}
```

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>ReasonCode
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>deliveryOptionInvalid</td>
            <td style='text-align: left;vertical-align: top;'>The supplied delivery option can't be accepted by you. The buyer will be requested to select a different shipping option.</td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>unknownError</td>
            <td style='text-align: left;vertical-align: top;'>For any other error. The buyer will see a generic error message and requested to return to your shop.
                <br /></td>
        </tr>
    </tbody>
</table>

---

### 4. 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](../amazon-pay-api-v2/checkout-session.html#finalize-checkout-session) API call to complete the checkout.

```JavaScript
/** 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,
      }),
    });
  } catch (err) {
    // something went wrong with your server call
    console.err(err);
    return {
      status: "error",
      reasonCode: "unknownError",
    };
  }
};
```

#### onCompleteCheckout event input

<table width="100%" border="1">
    <tbody>
        <tr >
            <td style='vertical-align: top; font-weight: bold ; width: 35%' class='bold'>Parameter
                <br /></td>
            <td style='vertical-align: top; font-weight: bold; width: 65%' class='bold'>Description
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>amazonCheckoutSessionId<br><br>Type: string
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>AmazonPay's checkoutSessionId
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>billingAddress<br><br>Type: <a href="../amazon-pay-api-v2/buyer.md#type-address">Address</a>
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Buyer selected billing address
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>paymentDescriptor<br><br>Type: string
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Amazon Pay-provided description for buyer-selected payment instrument
                <br /></td>
        </tr>
        <tr>
            <td style='vertical-align: top;'>buyerAdditionalInfo<br><br>Type: <a href="../amazon-pay-api-v2/buy-now-checkout.md#type-buyeraddtionalinfo">BuyerAdditionalInfo</a>
                <br /></td>
            <td style='text-align: left;vertical-align: top;'>Additional buyer info collected on the Buy Now page (EU only)
                <br /></td>
        </tr>
    </tbody>
</table>

```JSON
{
    "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": "Amazon Pay Visa (1111)"
}
```

#### onCompleteCheckout handler output

No output required for this callback. Redirect the buyer to your confirmation page, when the `Finalize Checkout Session` API was successful.

### 5. 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.
 
```JSON
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.
 
```JSON
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