> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dintero.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Shipping address callback

> Update the shipping options in Dintero Checkout when the customer changes their shipping address, using either a backend callback endpoint or the Web SDK onAddressCallback function.

Updating the shipping options presented to the end customer when they add or change their shipping address in the checkout can be implemented either via a **backend callback endpoint** or via a **frontend callback function** when using the [Dintero Web SDK].

## Updating shipping options via backend callback endpoint

> [!NOTE]
>
> If you use the \[Dintero Web SDK] and provide an `onAddressCallback` function, the checkout does not call `express.shipping_address_callback_url`. See [Updating shipping options via frontend callback function](#updating-shipping-options-via-frontend-callback-function).

When there are changes in the shipping address in the checkout, a callback is sent from Dintero's services to the endpoint that you have specified in `session.express.shipping_address_callback_url` with an updated order including the new address.

The webshop should update the webshop state/order with the new shipping address, and return a list of available [shipping options](/docs/checkout/shipping-options.md) for the given shipping address.

Link to [the API specification for the callback endpoint](/api-reference/example-session-callbacks/example_shipping_address_callback_url.md). Note that the request body is what *Dintero* will post to your endpoint and the response is what *your endpoint* returns back to Dintero.

If the checkout is embedded, the [Dintero Web SDK] will call **onSession** whenever the session is updated, with the
event **SessionUpdated**.

### Compatibility with "one click" Apple Pay and Google Pay

In order to support one click express payments via Apple Pay and Google Pay your endpoint must support returning shipping options when the `session.order.shipping_address` in the request body from Dintero’s systems contains only `country` and `postal_code`.

## Troubleshooting the backend callback

### If correction item is added to the order

If the implementation has problems with items of the type correction, you might have problems with the shipping address
callback.

```json title="Item with correction" theme={null}
{
  "id": "correction-mc7nt6LjqgCejGGLNHpFMq",
  "amount": -10000,
  "line_id": "correction-mc7nt6LjqgCejGGLNHpFMq",
  "quantity": 1,
  "description": "Correction"
}
```

This can happen when handling the callback and responding with an updated order with the wrong `order.amount`.

To solve this, make sure that `order.amount` contains the amount from the shipping option which is currently chosen.

#### Example

If the callback contains the following:

```json theme={null}
{
  "order": {
    "items": [
      {
        "id": "item-1",
        "line_id": "item-1",
        "amount": 10000,
        "vat": 25,
        "vat_amount": 2000,
        "quantity": 1
      }
    ],
    "amount": 20000,
    "vat_amount": 4000,
    "currency": "NOK",
    "shipping_option": {
      "id": "shipping",
      "line_id": "shipping",
      "amount": 10000,
      "vat": 25,
      "vat_amount": 2000
    }
  }
}
```

then, if the order is not changed, the response needs to contain the `10000` from the
request `order.shipping_option.amount`:

```json theme={null}
{
  "order": {
    "items": [
      {
        "id": "item-1",
        "line_id": "item-1",
        "amount": 10000,
        "quantity": 1,
        "vat": 25,
        "vat_amount": 2000
      }
    ],
    "amount": 20000,
    "vat_amount": 4000,
    "currency": "NOK"
  }
}
```

If the tax of the item has changed from 25% to 20% you should still provide the same amount from the callback payload.
If the shipping option price has changed, we will adjust the total price of the whole order when we choose the shipping
option from the new list of shipping options.

```json theme={null}
{
  "order": {
    "items": [
      {
        "id": "item-1",
        "line_id": "item-1",
        "amount": 9600,
        "quantity": 1,
        "vat": 20,
        "vat_amount": 1600
      }
    ],
    "amount": 19600,
    "vat_amount": 3600,
    "currency": "NOK"
  }
}
```

> [!TIP]
>
> The use-cases for when the order changes when the address is changed are:
>
> * The new address is in another country or state, and the tax is different for the new location
> * Other, less probable ones (e.g. if the customer is from a certain location, they have to buy a specific item)
>
> If these use cases don't apply to you, it's best to respond to the callback with just the new shipping options.

## Updating shipping options via frontend callback function

This only applies when the checkout is embedded and the embedding site is using the [Dintero Web SDK]. It is not available when the checkout is opened with `redirect()`. In pop-out mode the embedding page handles the callback, not the pop-out window.

If the `onAddressCallback` function is provided, the checkout will not perform the machine to machine address update callback defined in the session at `express.shipping_address_callback_url`. Instead the SDK runtime has to handle the address update flow.

The `onAddressCallback` function is invoked when an end user submits their address details (the shipping and billing addresses) in an embedded Checkout Express session. The callback function is invoked with an updated session that is not yet persisted in the Dintero backend. The checkout will be locked and payment will be paused until the provided callback function is called, or `checkout.submitAddressCallbackResult` is called with the result.

The function receives an event with the event `type`, the updated `session`, and the `callback` used to return the result.

When `onAddressCallback` is invoked you will have to perform a **server-to-server** [session update](/api-reference/session/checkout_session_put.md) with shipping options or other details that have changed. Once the session has been updated you need to call the provided callback function with a result.

When the session has been updated successfully, return a successful result:

```js theme={null}
{
    success: true
}
```

If the session update failed, return the result with an error message:

```js theme={null}
{
   success: false,
   error: "<reason for session update failure>"
}
```

```js theme={null}
onAddressCallback: function(event, checkout, callback) {
     // Perform a server-to-server session update
     getShippingOptionsForAddressAndUpdateSession(event.session).then(() => {
        callback({
            success: true,
        });
     }).catch((err) => {
        callback({
            success: false,
            error: toErrorMessage(err),
        });
     });
},
```

> [!NOTE]
>
> When implementing the `onAddressCallback`, there is no need to manually lock the session and refresh it as described in [Updating a checkout session](/docs/checkout/updating-session.md). The checkout will automatically lock the payment and refresh the session when the `callback` function is used to return a result.

If your `onAddressCallback` function throws, the SDK returns `{ success: false, error: "Address callback runtime error" }` on your behalf so the checkout is not left waiting.

See also the [onAddressCallback section](https://github.com/Dintero/Dintero.Checkout.Web.SDK#handling-checkout-express-address-updates-using-the-onaddresscallback) in the [Dintero Web SDK] documentation.

[Dintero Web SDK]: https://github.com/Dintero/Dintero.Checkout.Web.SDK


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.