> This page is for Afterpay Button Documentation.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.afterpay.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.afterpay.com/_mcp/server.

# Integrated Shipping

This feature improves the customer experience by embedding your shipping options directly into the Express Checkout flow. It streamlines the checkout process and can be combined with the `buyNow` flag to create a one-step checkout that immediately precedes the order confirmation page.

We recommend the Integrated Shipping flow for merchants with:

* Fewer than 5 shipping options
* Single shipping option for an entire order (i.e. no SKU level options)
* Simple tiered shipping options (e.g. standard, express, rush)
* Pickup in-store option before checkout entry

It requires `shippingOptionRequired` to be true (enabled by default) and an onShippingAddressChange callback must be defined:

**`Example with Integrated Shipping`**

```javascript Example with Integrated Shipping
const afterpayButton = document.getElementsByTagName('afterpay-button')[0];
afterpayButton.addEventListener('click',
   function (e) {
        // ...all attributes listed in step 4 above,
        afterpayButton.expressCheckout = {
          region: 'US',
          onShippingAddressChange: function (data, actions) {
           /* required for Integrated Shipping  */
           /* address in `data` */
           /* calc options, then call `actions.resolve(options)` */
         },
         onShippingOptionChange: function (data) {
           /* optional - chosen option in `data` */
         },
           onComplete: function (data) {
           /* handle success/failure of checkout */
         },
         buyNow: false,
         pickup: false,
         shippingOptionRequired: true
        }

   }, true
);
```

> **Info**
>
> Integrated Shipping is enabled by default for Express orders. To disable it, `shippingOptionRequired` must be set to false.

## Listening for Address Changes

The shipping address change callback is required:

* If you intend to update the order total based on a chosen shipping address.
* To validate that you can ship to the selected address.\
  To set up the Shipping Address Change callback, implement the onShippingAddressChange function. This function is passed two arguments: data and actions.

You, the merchant, manage how the shipping options are calculated. Javascript can calculate the options, or you can pass them to an internal API.

If shipping options are available for the given address, use the resolve action to return them to Afterpay or Clearpay (UK) - see the code example below. Similarly, use the reject action when shipping is unavailable.

### Example of retrieving shipping options via API

```js
onShippingAddressChange: function (data, actions) {
    fetch('/your-shipping-endpoint', {
      method: 'POST',
      headers: { 'content-Type': 'application/json' },
      body: JSON.stringify(data),
    }).then(function(options) {
      actions.resolve(options)
    }).catch(function(error) {
      // Parse the response and send an AfterPay rejection, e.g.:
      actions.reject(AfterPay.CONSTANTS.SHIPPING_UNSUPPORTED)
    })
  },
```

### Example of calculating shipping options in JS

```javascript
onShippingAddressChange: function (data, actions) {
    if (data.countryCode !== 'US') {
      // Reject any unsupported shipping addresses
      actions.reject(AfterPay.CONSTANTS.SHIPPING_UNSUPPORTED)
    } else {
      // Calc shipping inline
      actions.resolve([ {
        id: '1', name: 'Standard', description: '3 - 5 days',
        shippingAmount: { amount: '0.00', currency: 'USD'},
        taxAmount: { amount: '3.18', currency: 'USD'},
        orderAmount: { amount: '34.99', currency: 'USD'},
      }, {
        id: '2', name: 'Priority', description: 'Next business day',
        shippingAmount: { amount: '10.99', currency: 'USD'},
        taxAmount: { amount: '4.28', currency: 'USD'},
        orderAmount: { amount: '47.08', currency: 'USD'},
      } ])
    }
```

Afterpay calls your onShippingAddressChange function when:

* The customer first enters the Afterpay summary page
* The customer makes a change to their shipping address on the Afterpay summary page

Afterpay provides the following parameters to your onShippingAddressChange function:\
data parameter: This contains the customer’s selected address with fields:

* `suburb`, `state`, `postcode`, and `countryCode`

action parameter: This object is used to return your response to the Afterpay checkout. It consists of the following methods:

* `resolve` : Call this method to provide the shipping options applicable to the customers address. Takes an array of Shipping Option objects.
* `reject` : Call this method when you are unable to handle the request. Do not throw an error, instead call this method with a Shipping Constant as the first argument to indicate a status, e.g.:

```javascript
actions.reject(AfterPay.CONSTANTS.SHIPPING_UNSUPPORTED)
```

## Shipping Option Model

| Attribute        | Type              | Description                                                 |
| :--------------- | :---------------- | :---------------------------------------------------------- |
| `id`             | String (required) | A shipping option identifier. Max length 128                |
| `name`           | String (required) | The name of the shipping options                            |
| `shippingAmount` | Money (required)  | The shipping amount (without tax, if including `taxAmount`) |
| `taxAmount`      | Money (required)  | The tax amount                                              |
| `orderAmount`    | Money (required)  | The total amount for the order including shipping and taxes |
| `description`    | Strong            | A description for this shipping option                      |

## Shipping Constants

To indicate a number of error scenarios, actions.reject() may be invoked with a provided constant.

These are of the form `AfterPay.constants.<NAME>`, where `<NAME>` is one of:

| Constant                        | Description                                 |
| :------------------------------ | :------------------------------------------ |
| `SHIPPING_ADDRESS_UNRECOGNIZED` | Unrecognized address                        |
| `SHIPPING_ADDRESS_UNSUPPORTED`  | Recognized address, but will not ship there |
| `SERVICE_UNAVAILABLE`           | General service error.                      |

> **Info**
>
> Afterpay Express Checkout does not perform any arithmetic. It is the responsibility of your web app to calculate the correct total. Each shipping option must have a total order amount including taxes and shipping.

## Listening for Shipping Option Changes

The `onShippingOptionChange` callback allows a merchant to track the customer’s chosen shipping option as it changes. It is optional, and is called each time a customer selects a shipping option. This function is passed one argument: `data`

`data` parameter (object): This contains the customer’s selected shipping option, as provided in the response from `onShippingAddressChange`, with fields:

| ID   | Name   | Description   | Shipping Amount  | Order Amount  |
| :--- | :----- | :------------ | :--------------- | :------------ |
| `id` | `name` | `description` | `shippingAmount` | `orderAmount` |

```javascript
onShippingOptionChange: function (data) {
    console.log(data)
  },
```

## Buy Now

When the Express Checkout is complete, you may either authorize the virtual credit card provided by Afterpay or continue checkout on your review page. If you completing the order immediately, set the `buyNow` flag to true - this shows the customer a “Buy Now” button at the end of their Afterpay journey.

```javascript
const afterpayButton = document.getElementsByTagName('afterpay-button')[0];
afterpayButton.addEventListener('click',
   function (e) {
        // ...all attributes listed in step 4 above,
        afterpayButton.expressCheckout = {
          // ...
          buyNow: true,
        }
   }, true
);
```

## Configuring a pickup order

You can modify the Express Checkout experience for Click & Collect and other pickup flows by following these steps:

1. Allow your customers the ability to choose pickup options before they select Afterpay Express. This should include any decisions that may affect the cost of delivery, for instance pickup location and date.

2. If the customer has opted for pickup, provide the chosen pickup address when adding the shipping attributes.

3. When you include the `expressCheckout` object attribute:

   * Set the pickup flag to true.

   * Configure your `onShippingAddressChange` handler to return the name and description of their pickup choice. This will likely mean returning only a single option -- e.g

   ```javascript
   actions.resolve([ {
     id: 'pickup-store-123', name: 'Click & Collect',
     description: 'Available for next-day pickup',
     shippingAmount: { amount: '0.00', currency: 'USD'},
     taxAmount: { amount: '3.18', currency: 'USD'},
     orderAmount: { amount: '34.99', currency: 'USD'},
   } ])
   ```

4. You can collect additional information regarding the pickup, e.g. selecting another person to pick up the order, at your order review page. These details must not increase the order total.

> **Note**
>
> The information on this page also applies to Clearpay (UK).