> **Description:** Complete API reference with endpoints, webhooks, payment flows, and data structures for implementing the full checkout experience.

> **Deprecated:** This page documents a deprecated API. It is preserved for existing integrations. Do not recommend it for new integrations.

# Checkout API guide

**Important update**

Vipps MobilePay has entered into an agreement to sell the Checkout solution to [Kustom](https://www.kustom.co/).

As part of this transition, *Vipps MobilePay Checkout* will become *Kustom Checkout*. This means the Checkout product you ordered will be delivered and developed by Kustom going forward.
If you have questions, you can check our [FAQ](https://vippsmobilepay.com/en-NO/vippsmobilepay-kustom).

The Checkout API provides an all-in-one solution for receiving payment for goods and services online using our trusted technology and brand.
It combines several Vipps MobilePay products, including [Login](https://developer.vippsmobilepay.com/docs/APIs/login-api/README.md), [ePayment](https://developer.vippsmobilepay.com/docs/APIs/epayment-api/README.md), [Recurring](https://developer.vippsmobilepay.com/docs/APIs/recurring-api/README.md) and [Order Management](https://developer.vippsmobilepay.com/docs/APIs/order-management-api/README.md) allowing a frictionless integration for merchants.

API version: 3.0.0.

**Please note:** There are some differences between the test and production environments. Read more about the [test environment](https://developer.vippsmobilepay.com/docs/knowledge-base/test-environment.md) and its limitations.

**Please note:** Always use the most recent API version when integrating with Checkout. All endpoints are described in detail in our [API Reference](https://developer.vippsmobilepay.com/redocusaurus/checkout-swagger-id.yaml).

## Checkout features

### Checkout API

Checkout works around the concept of a *session*, with a time to live of one hour. The API exposes endpoints for the merchant to interact with a session. These include:

- session initiation
- session status

#### Session types

A Checkout session supports both *one-time-payments* and *subscriptions* by setting the `type` property to `PAYMENT` or `SUBSCRIPTION` respectively at session initiation. A session in subscription mode may also include an optional *one-time-payment*, also referred to as *initial charge*.

### Checkout frontend

Once a session is created, you have two options for displaying it: either embedded in an iFrame on your website (*regular Checkout*) or as a full-page redirect to our hosted checkout page (*CheckoutDirect*). The choice depends on your use case.

#### Frontend SDK

We provide a frontend SDK to make opening the session on the merchant easy
(the SDK is
[explained in detail](#step-2-displaying-the-session)
later in this guide).

It is **strongly** recommended to use the frontend SDK to make sure you get the latest improvements and bug fixes.

### Shipping

In most situations, a merchant wants to send goods to a customer using a shipping provider. Consult [the shipping guide](https://developer.vippsmobilepay.com/docs/APIs/checkout-api/checkout-how-it-works-shipping.md) and the [API spec](https://developer.vippsmobilepay.com/redocusaurus/checkout-swagger-id.yaml) for a detailed description of which shipping providers and features Checkout supports.

### Checkout direct - hosted checkout

With *Checkout Direct* you can implement a checkout flow directly from a product page without going through a shopping cart. *Checkout Direct* decouples you from needing to embed an iFrame and lets us handle everything on our secure servers before returning the customer to your shop after a payment is finished. To use *Checkout Direct* , follow the [System integration guidelines](#system-integration-guidelines) and make sure you pick [Option 2](https://developer.vippsmobilepay.com/docs/APIs/checkout-api/checkout-api-guide.md#step-2-displaying-the-session) under [Step 2: Displaying the session to the user](#step-2-displaying-the-session).

**Please note:** CheckoutDirect redirects users to a full-page checkout on our servers. If you want to embed checkout within your website, use the regular Checkout method (Option 1) instead.

### Checkout Elements

You can adjust the fields and values present in the Checkout by setting the `configuration.elements` property in the
[`Create a Checkout session`][create-checkout-session-endpoint] endpoint.
For example, you might have a purchasing flow where you don't require an address because you're not sending physical goods,
or you don't need the customers to identify themselves because they are already logged into your system. Then, you can disable the
contact details panel by changing the `configuration.elements`.

The `Elements` mode is optionally set by the `configuration.elements` property at session initiation, and defaults to `Full`.

If you need the address from a user, you can enable this by using *Elements* `PaymentAndContactInfo`, resulting in the following personal details form and payment form.

Screenshot: Two-step contact and payment flow (Vipps or MobilePay): the first screen shows a 'My information' form with a Fetch button and manual fields for name, mobile number, and email; the second screen shows the pre-filled contact details alongside payment method options (app or card) and a Complete purchase button.

If you don't need the contact details for a customer, you can disable it by using Elements `PaymentOnly`, resulting in the following session:

Screenshot: Checkout payment screen (Vipps or MobilePay) showing only the payment section with no address or contact form -- the app is selected by default and a card option with Visa and Mastercard logos is listed below, with a Complete purchase button.

### Prefill customer data

We believe that simplicity is key to providing the best user experience. With `prefillCustomer`, you can easily send in any information you have about your customer, making filling out forms in the Checkout a breeze.
All fields in `prefillCustomer` are optional. We will prefill the form with whatever information you send and let your customers fill in the rest if any information is missing.

To further streamline the payment process, we've implemented a feature that automatically forwards the phone number to our [landing page](https://developer.vippsmobilepay.com/docs/knowledge-base/landing-page.md).
This removes the hassle of having to fill in the phone number multiple times and makes it even easier for your customers to pay.

Even if your Checkout is set up with `PaymentOnly`, you can still send in your customer's phone number to make the payment process smoother.

### Custom consent

Sometimes you need to ask your customers for permission for certain actions, such as subscribing to technical updates. That's where our "custom consent" feature comes in handy!

When you enable "custom consent", a checkbox with a message appears at the bottom of the checkout page. Your customers can choose to check this box if they want to give their consent. You can make the checkbox optional or required, depending on your needs.

The message displayed next to the checkbox can contain up to one link, formatted in Markdown like this: `[linkText](https://example.com)`. This allows you to direct customers to additional information or resources related to the consent request.

Screenshot: Checkout payment screen (Vipps or MobilePay) with the app selected and a card option, a Complete purchase button, and below the button a custom consent checkbox with a linked label for optional newsletter subscription.

### Order details

Checkout supports providing order details to the user in the Vipps or MobilePay app. This can be useful in many cases, and is sometimes mandatory [as described below](#order-details-and-content-monitoring).

To enable Checkout to provide order details, the `orderSummary` property in the session initiation request must be set.
Detailed information is available in the OpenAPI spec [session initiation endpoint][create-checkout-session-endpoint].

Order details are a combination of a list of *OrderLines* and a *BottomLine*. An *OrderLine* is a description of each item present in the order. The *BottomLine* contains information regarding the order as a whole.
It is possible to specify shipping costs in one or more *OrderLines* in the session initiation.
If shipping is handled in Checkout and is not free, an order line with the shipping cost will be automatically added, **even if** shipping costs are specified in the session initiation.

If set up properly in the `OrderSummary` property in the session initiation, the order details will be created when payment is initiated (by sending it to Order Management API), and will be visible in the customer's app when the payment is successfully completed.
Further details regarding order details in the [Order Management API](https://developer.vippsmobilepay.com/docs/APIs/order-management-api/order-management-api-guide.md#order-details)

#### Show order summary

In addition to automatically creating [order details](https://developer.vippsmobilepay.com/docs/APIs/order-management-api/order-management-api-guide.md#order-details), setting up the `OrderSummary` property as described above enables the use of `showOrderSummary: true` inside `configuration` in the session initiation. This will display a simplified order summary, similar to the receipt, on top of the Checkout window. Use this feature if you would like to show what the user is paying for during the checkout. We show a simpler summary than the receipt using a subset of the properties inside `OrderSummary`. For example, tax calculations are shown in the receipt, but not in the order summary. The following properties are honored: `id`, `name`, `discount`, `giftcard`, `totalAmount`, `productUrl`, `isReturn`, `isShipping`, `currency`, `giftCardAmount`, `quantity`.

Screenshot: Order summary panel labeled 'My items' with a table showing item name, quantity, and price columns -- including regular items, a discounted item with a Discount badge, a returned item with a Returned badge, shipping, and a gift card credit with a Gift card badge, followed by a total row.

#### Order details and content monitoring

We offer [Content monitoring](https://developer.vippsmobilepay.com/docs/APIs/order-management-api/order-management-api-guide.md#content-monitoring) as a way for merchants to deal with the regulatory demands of content monitoring.
For some merchants, we can utilize the merchant's webpage for content monitoring, continuously verifying that the actual products being sold coincide with the expected products.
If you, as a merchant, don't have a permanent website that can be utilized for content monitoring, for example you don't have a user facing website or the website is ephemeral/short-lived, then you must utilize Content monitoring.
In order to comply with content monitoring, all transactions must be posted to the Order Management order details functionality described in this section.

### Recurring payments

Screenshot: Checkout subscription screen with a 'Pay now' section for an initial charge, a 'Payment agreement' section showing a campaign period, the price after the campaign ends, and a billing frequency of every week until cancelled, followed by pre-filled contact details and a Vipps/MobilePay payment option.

Initiation of recurring payments can be done through Checkout, so you can retrieve the customer and shipping information in a simple manner.
All operations after the initial agreement are done as described in
the [Vipps MobilePay Recurring API guide](https://developer.vippsmobilepay.com/docs/APIs/recurring-api/recurring-api-guide.md).

When initiating a Checkout session, use the `InitiateSubscriptionSessionRequest` schema in the request body of the
[Create a Checkout session](https://developer.vippsmobilepay.com/redocusaurus/checkout-swagger-id.yaml) request.

If you are on WooCommerce, you can offer recurring payments for Checkout through the
[recurring plugin for WooCommerce](https://developer.vippsmobilepay.com/docs/plugins-ext/recurring-woocommerce/README.md) plugin.

If you offer both recurring and single payments, we recommend using our
[Recurring checkout](https://developer.vippsmobilepay.com/docs/plugins-ext/recurring-woocommerce/README.md) alongside our [standard checkout plugin](https://developer.vippsmobilepay.com/docs/plugins-ext/woocommerce/README.md).

We only offer static shipping options at the moment.

### External payment methods

**INFO**

External payment methods are now supported in all markets.

External payment methods allow merchants to add means of payment that are currently not available natively within Checkout. When a customer selects this method for payment, they are redirected to an external URL as supplied by the merchant.

#### Compliance

In order for your payment method to be compliant, you need to have an agreement in place with the specified external payment provider (E.g. Klarna).

#### Allowed external payment methods

Below follows a list of allowed external payment methods.

| Payment method |
| -------------- |
| Klarna         |
| SveaCheckout   |

#### Flow and Implementation

When you [initiate a session](#step-1-initiating-a-session), you have the option of specifying a list of external payment methods, these consist of a key `paymentMethod` identifying the payment method (one of the [allowed external payment methods](#allowed-external-payment-methods)), and a string `redirectUrl`. These external payment methods are then added to the list of available payment methods that the customer can choose from. Should a customer select one of the supplied external payment methods, they will be redirected to the supplied `redirectUrl`.

> **Note**: You are responsible for the subsequent steps in the checkout flow once a customer has selected this method of payment. This includes the confirmation page, order creation and so forth. As this flow is external to the Checkout context, Vipps MobilePay will not take responsibility for any of the required integration steps towards the external payment provider, nor any complications that could occur with the orders paid using this functionality

### Extended payment capture deadlines

Special rules apply for payments made with Checkout: All payments started in Checkout can be captured up to 180 days after reservation, regardless of country or payment app.

We guarantee successful capture within 14 days after the reservation.

We cannot guarantee successful captures from 15 to 180 days after reservation, so there is a chance of a failed capture,
for example in the case of insufficient funds, expired cards, or similar issues.
See: [Card payment deadlines may vary](https://developer.vippsmobilepay.com/docs/knowledge-base/reserve-and-capture.md#credit-card-payment-deadlines-may-vary).

## System integration guidelines

Be sure to always use the most updated version of the API when integrating.

### Flow diagram

The standard flow for a Checkout consists of

1. Initiating a session
2. Displaying the session to the user
3. Handling the result of the session

```mermaid
sequenceDiagram
  autonumber
  actor User
  participant LandingPage as Payment landing page
  participant App as Vipps or MobilePay app
  participant Merchant
  participant Frontend as Checkout (iFrame)
  participant API as Checkout API

  User->>Merchant: Start shopping session, proceed to checkout
  Merchant->>API: Start checkout session
  API-->>Merchant: Response containing token identifying the session
  Merchant->>Frontend: Initialize frontend SDK to open session in iFrame
  Merchant->>API: Start polling on session
  Frontend->>User: Display session
  User->>Frontend: Fill out checkout form fields. Proceed to payment
  Frontend->>API: Initiate payment
  API-->>Frontend: Payment URL

  alt If mobile device
    Frontend->>App: Switch to Vipps or MobilePay app
  else If desktop device
    Frontend->>LandingPage: Redirect to payment landing page
    LandingPage->>App: Receive push for payment
  end
  App->>User: Display payment info
  User->>App: Complete payment

  alt If mobile device
    App->>Merchant: Redirect to merchant app
  else If desktop device
    LandingPage->>Merchant: Redirect to merchant defined return URL
  end

  API-->>Merchant: Receive polling result on session
  API->>Merchant: Receive callback/webhook result on session
```

  User starts a shopping session and proceeds to checkout on the Merchant site.
  Merchant calls the Checkout API to start a checkout session.
  Checkout API returns a token identifying the session to Merchant.
  Merchant initializes the frontend SDK to open the session in an iFrame.
  Merchant starts polling the Checkout API for session status.
  Checkout iFrame displays the session to the User.
  User fills out the checkout form fields and proceeds to payment.
  Checkout iFrame initiates the payment via the Checkout API.
  Checkout API returns a payment URL to the iFrame.
  On mobile: the iFrame switches the user to the Vipps or MobilePay app directly. On desktop: the iFrame redirects to the payment landing page, which sends a push notification to the app.
  App displays payment info to the User.
  User completes the payment in the app.
  On mobile: app redirects the user back to the Merchant app. On desktop: the landing page redirects the user to the Merchant's return URL.
  Merchant receives the polling result and callback/webhook result on the session from the Checkout API.

### Step 1: Initiating a session

The merchant backend calls the [session initiation endpoint][create-checkout-session-endpoint]:

[`POST:/checkout/v3/session`][create-checkout-session-endpoint]

Provide headers described in [HTTP headers](https://developer.vippsmobilepay.com/docs/knowledge-base/http-headers.md).

All fields of the request body are described in our [API Reference][create-checkout-session-endpoint].

The response object consists of a `token` and a `checkoutFrontendUrl`, which are used in the next step

#### Configuration for use inside a native mobile application

Checkout can be used in an iOS or Android app to pay for goods and services. The Checkout frontend may then be opened directly inside a web view, instead of as an iFrame inside a merchant website.

In this situation, the merchant must provide a `returnUrl` to direct the user back to an application.
The frontend application will automatically try to detect if the user is on a mobile device.
If so, it will do an "app switch" into the Vipps  or MobilePay  app, and then back to your application upon completion.

We recommend that you use `WEB_REDIRECT` and implement universal links (starting with `https`), as they contain built-in logic to handle both desktop and mobile flow. They are more secure than the deep link flow and provide a better user experience.

Please see [General info: App flow recommendations](https://developer.vippsmobilepay.com/docs/knowledge-base/app-flow.md) for more details.

#### Configuration of external payment methods

To enable this feature, you need to populate the `externalPaymentMethods` field in the `configuration` property on session initiation request. Subsequently, you need to undertake integration work towards the payment provider. This may include both backend and frontend work (e.g., order confirmation pages).

Example:

```json
{
  "externalPaymentMethods": [
    {
      "paymentMethod": "Klarna", // Required
      "redirectUrl": "https://..." // Required: HTTPS
    }
  ]
}
```

We also suggest polling the session to extract the customer information and the selected shipment method that can be used to, for example, populate fields in the external payment method provider, or to fulfill the subsequent steps.

### Step 2: Displaying the session

Load the frontend SDK in the `<head>` section of the merchant website.

```html
<head>
  <script src="https://checkout.vipps.no/vippsCheckoutSDK.js"></script>
</head>
```

**SDK initialization restriction**

The Checkout SDK must be initiated from the top-level parent document and cannot be initiated from within an iframe. This is because the SDK takes control over navigation to handle the payment flow properly.

The most common flow includes embedding Checkout on the merchant website, typically as the step succeeding a shopping cart view. This is the standard method using the `VippsCheckout` SDK function.

*Option 1: iFrame* and *Option 2: Checkout Direct* can also work in combination on your site.

The frontend SDK exposes a global function called `VippsCheckout`. Initialize this with the following parameters:

| Parameter             | Description                                                                                                 | Optional |
| --------------------- | ----------------------------------------------------------------------------------------------------------- | -------- |
| `checkoutFrontendUrl` | Specifies where to load the iFrame content from. Comes from session creation response                       | No       |
| `iFrameContainerId`   | The ID of the HTML element to contain the Checkout iFrame                                                   | No       |
| `token`               | Token identifying the session. Comes from session creation response.                                        | No       |
| `language`            | Can be set to `nb`, `dk`, `fi`, or `en`. This is optional and will default to 'en' English if not specified | Yes      |
| `on`                  | Listen to events from Checkout. See [SDK events](#frontend-sdk-events) for more details.                    | Yes      |

Example merchant website using Checkout frontend SDK to embed an iFrame with the session in plain html/js.

```html
<html>
  <head>
    <title>Merchant website</title>
    <script src="https://checkout.vipps.no/vippsCheckoutSDK.js"></script>
  </head>
  <body>
    <button type="button" id="checkout-button">Checkout with Vipps</button>
    <section id="vipps-checkout-frame-container">

    </section>
    <script>
      document
        .getElementById("checkout-button")
        .addEventListener("click", function () {
          // Relay an initiate session request to Checkout API through the merchant's backend
          fetch("<MERCHANT BACKEND CREATE SESSION URL>", {
            method: "POST",
          })
            .then((response) => response.json())
            .then((data) => {
              var vippsCheckout = VippsCheckout({
                checkoutFrontendUrl: data.checkoutFrontendUrl,
                iFrameContainerId: "vipps-checkout-frame-container",
                language: "nb",
                token: data.token,
              });
            })
            .catch((error) => {
              // Handle at least these two types of errors here:
              // 1. Fetch to create session endpoint failed
              // 2. Checkout frontend SDK not loaded resulting in VippsCheckout not being defined
            });
        });
    </script>
  </body>
</html>
```

**Please note:** Never leak the merchant credentials to the frontend. A Checkout session should always be created by the merchant backend

**Please note:** The Checkout frontend **is not** supposed to be open in its own browser window/tab. The only exception to this is when using Checkout inside a web view in a native mobile application.

#### Sticky Checkout session

The frontend SDK provides an alternative way to display the session, using a query parameter in the URL. This makes the session "sticky", meaning that the same session will open after a page refresh.

If the query parameter `token` is present and the token attribute in the argument object to `VippsCheckout` **is not** defined, the frontend SDK will load the iFrame with the token from the query parameter.

The SDK provides a helper method that will redirect the user to the current page with the `token` query parameter added to the URL.

**Please note:** Make sure to initialize `VippsCheckout` outside any user dependent execution blocks (like event handlers) to make sure that the iFrame is loaded every time a user lands on the page.

```javascript
// Globally defined
var vippsCheckout = VippsCheckout({
  checkoutFrontendUrl: data.checkoutFrontendUrl,
  iFrameContainerId: "checkout-iframe-container",
});

// Attach to checkout button
fetch("<MERCHANT BACKEND CREATE SESSION URL>", { method: "POST" })
  .then((response) => response.json())
  .then((data) => {
    vippsCheckout.redirectToCurrentPageWithToken(data.token);
  });
```

#### Frontend SDK events

You can listen to changes in Checkout by supplying callbacks to the `on` option in the frontend SDK.
Each key in the map supplied to `on` corresponds to an event and accepts a callback function with a `data` parameter as a value.

Available events:

| Parameter                      | Description                                                                                             | Type                                                                                                                                            |
| ------------------------------ | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `shipping_option_selected`     | Is triggered when the user selects a shipping option or `undefined` when shipping option is deselected. | `ShippingOption` &#124; `undefined`                                                                                                             |
| `total_amount_changed`         | Is triggered when the total amount changes (for example, when a shipping option is selected).           | `Money`                                                                                                                                         |
| `session_status_changed`       | Is triggered upon changes in session status (for example, when payment is started).                     | `SessionStarted` &#124; `PaymentInitiated` &#124; `PaymentSuccessful` &#124; `PaymentFailed` &#124; `SessionTerminated` &#124; `SessionExpired` |
| `shipping_address_changed`     | Is triggered when a new "delivered to" address is submitted or `undefined` when removed.                | `Address` &#124; `undefined`                                                                                                                    |
| `customer_information_changed` | Is triggered when new customer information is submitted or `undefined` when removed.                    | `Address` &#124; `undefined`                                                                                                                    |

##### Type definition

###### `ShippingOption`

| Parameter     | Type                             | Description                                                                  |
| ------------- | -------------------------------- | ---------------------------------------------------------------------------- |
| `id`          | `string`                         | The merchant's shipping option identification.                                |
| `brand`       | `string`                         | The name of the brand of the option (for example, "Posten" or "PostNord").   |
| `description` | `description` &#124; `undefined` | The description of the shipping option.                                      |
| `product`     | `string`                         | The brand specific product (for example, "Servicepakke" or "Home delivery"). |
| `price`       | `Money`                          | The price of the shipping option.                                            |

###### `Money`

| Parameter                | Type     | Description                                                                                                 |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------- |
| `fractionalDenomination` | `number` | Value in minor units. For Norwegian kroner (NOK) that means 1 kr = 100 øre. Example: 499 kr = 49900 øre. |
| `currency`               | `string` | Three letter ISO-4217 currency code.                                                                        |

###### `Address`

| Parameter   | Type     |
| ----------- | -------- |
| `address`   | `string` |
| `city`      | `string` |
| `country`   | `string` |
| `email`     | `string` |
| `firstName` | `string` |
| `lastName`  | `string` |
| `phone`     | `string` |
| `zip`       | `string` |

##### Example

```javascript
window.VippsCheckout = {
  checkoutFrontendUrl: data.checkoutFrontendUrl,
  iFrameContainerId: "vipps-checkout-frame-container",
  language: "nb",
  token: data.token,
  on: {
    shipping_option_selected: function (data) {
      // Do something when the shipping option is selected
    },
    total_amount_changed: function (data) {
      // Do something when the total amount changed
    },
    session_status_changed: function (data) {
      // Do something when status changed
    },
    shipping_address_changed: function (data) {
      // Do something when shipping address changed
    },
    customer_information_changed: function (data) {
      // Do something when customer information changed
    },
  },
};
```

CheckoutDirect redirects users to a checkout page hosted on our secure servers. The user leaves your website during checkout and returns after payment is completed.

**When to use CheckoutDirect:**

- You don't have your own web shop
- You want Vipps MobilePay to handle the entire checkout UI

**When to use regular Checkout (Option 1):**

- You want to embed checkout within your website
- You have a standard e-commerce flow

Use cases for CheckoutDirect include (but are not limited to)

- Checkout of a single item, essentially skipping the shopping cart.
- Lack of own web shop. If the merchant does not have their own web solution the Checkout can be hosted by Vipps MobilePay instead

To check out a single item directly attach a click event handler to a button close to the product, preferably the [Vipps MobilePay button](https://developer.vippsmobilepay.com/docs/knowledge-base/buttons.md) that comes predefined with the Vipps/MobilePay look-and-feel.

The frontend SDK exposes a global function called `VippsCheckoutDirect`. The click handler should call the function with the following parameters

| Parameter             | Description                                                                                                  | Optional |
| --------------------- | ------------------------------------------------------------------------------------------------------------ | -------- |
| `checkoutFrontendUrl` | Specifies where to load the iFrame content from. Comes from session creation response                        | No       |
| `token`               | Token identifying the session. Comes from session creation response.                                         | No       |
| `language`            | Can be set to `nb`, `en`, `fi`, or `dk`. This is optional and will default to `en` English, if not specified | Yes      |

```html
<html>
  <head>
    <title>Merchant website</title>
    <script
      async
      type="text/javascript"
      src="https://checkout.vipps.no/vippsCheckoutSDK.js"
    ></script>
    <script
      async
      type="text/javascript"
      src="https://checkout.vipps.no/checkout-button/v1/vipps-checkout-button.js"
    ></script>
  </head>
  <body>
    <vipps-mobilepay-button id="checkout-button"></vipps-mobilepay-button>
    <script>
      document
        .getElementById("checkout-button")
        .addEventListener("click", function () {
          // Relay an initiate session request to Checkout API through the merchant's backend
          fetch("<MERCHANT BACKEND CREATE SESSION URL>", {
            method: "POST",
          })
            .then((response) => response.json())
            .then((data) => {
              VippsCheckoutDirect({
                checkoutFrontendUrl: data.checkoutFrontendUrl,
                language: "nb",
                token: data.token,
              });
            })
            .catch((error) => {
              // Handle at least these two types of errors here:
              // 1. Fetch to create session endpoint failed
              // 2. Checkout frontend SDK not loaded resulting in VippsCheckoutDirect not being defined
            });
        });
    </script>
  </body>
</html>
```

**Please note:** Never leak the merchant credentials to the frontend. A Checkout session should always be created by the merchant backend

### Step 2a: Update the session

Updates to a Checkout session are allowed before the user proceeds to payment. Possible use cases may be upselling (adding products to an order after the user has proceeded to checkout), updating the order details with gift cards or similar, or updating the available shipping options to accomplish free-shipping use cases.

Properties of a session that may be updated.

1. Payment details
2. Order
3. Logistics options

In order to update the Checkout, it must be "locked" through the web SDK. The web SDK exposes functions for locking and unlocking a Checkout, both returning a promise indicating when the operation is done.

```javascript
// See step for information about when to initialize the SDK. The result may also be stored on the window object for easier access to lock and unlock functions.
const checkout = VippsCheckout({
  checkoutFrontendUrl: data.checkoutFrontendUrl,
  iFrameContainerId: "vipps-checkout-frame-container",
  language: "nb",
  token: data.token,
});

await checkout.lock();

// Use the update session (PATCH) endpoint for updating the Checkout from your backend. Do not attempt to update the session directly from the frontend as client credentials towards Vipps API should not be exposed to the users client/browser.

await checkout.unlock();
```

### Step 3: Handling the result of the session

After the user has completed the checkout process, the merchant will be notified with transaction details through *callback* and *polling*, as described below.

**Please note:** It is highly recommended implementing polling in addition to callback. We **don't** guarantee delivery of the callback.

**Please note:** If external payment methods are enabled and the user selects this option for payment, the merchant **will not** be notified.

#### Callback handling

The callback will be sent to a
[callback endpoint (click on the "Callbacks" tab)][create-checkout-session-endpoint]
implemented by the merchant.

`POST:{merchantInfo.callbackUrl}`

The `callbackAuthorizationToken`, provided by the merchant at session initiation, will be attached as the `Authorization` header. Use this to authorize the caller.

The callback is fired when the `sessionState` property changes to a terminal state (i.e., `PaymentTerminated`, `PaymentSuccessful`, or `PaymentInitiationFailed`). This means that the callback is sent at most once per session (with exponential backoff retry in case the response isn't successful).
We recommend using a combination of both a callback and polling to get the most recent state for a session.

Every callback must be answered with a `HTTP 2XX response`. In the eventuality that any other response is sent, we will retry with an exponential backoff until `2XX` is received again. The callback will be retried a maximum of 3 times.
Please keep in mind that we **don't** guarantee delivery of the callback, so it is highly recommended implementing polling in addition to callback.

It is critical that the endpoint receiving the callback is robust. It should also be able to receive any additional data not specified in the minimum example, so that it can be backwards compatible in accordance with our integration guidelines.

#### Session polling

Checkout exposes a [polling endpoint][retrieve-sessioninfo-endpoint].

The complete URL for polling is returned from the
[session creation endpoint][create-checkout-session-endpoint]
as `pollingUrl`.

#### Payment details

The `sessionState` property of the callback/polling response gives information about the state of the payment. Values `PaymentSuccessful`, `PaymentTerminated`, and `SessionExpired` are terminal states. Stop polling when receiving one of these states. The callback will only be sent once the session is in a terminal state.

The `paymentDetails` property gives additional information about the transaction. The shape of the object differs based on `paymentMethod`.

Example callback/polling response for payment method `Wallet` (Vipps/MobilePay) and `Card`:

```json
{
    ...
    sessionState: "PaymentSuccessful",
    paymentMethod: "Wallet",
    paymentDetails: {
        type: "wallet", // or "card"
        state: "AUTHORISED",
        amount: {
            value: 1234,
            currency: "NOK"
        }
    },
    ...
}
```

Additional details for `Wallet` and `Card` transactions can be retrieved from the underlying [GET:payment endpoint][get-payment-endpoint] (session with type: PAYMENT) or [GET:charge endpoint](https://developer.vippsmobilepay.com/docs/APIs/recurring-api/recurring-api-guide.md#charges) (session with type: SUBSCRIPTION) that Checkout uses under the hood.

#### Subscription details

If the Checkout Session was initialized with `type: SUBSCRIPTION` the `subscriptionDetails` property of the callback/polling response gives information about the state of the agreement.

```json
{
    ...
    sessionState: "PaymentSuccessful",
    paymentMethod: "Wallet",
    subscriptionDetails: {
        agreementId: "agr_123456",
        state: "ACTIVE"
    }
    ...
}
```

The `agreementId` property is the reference to the *recurring agreement*, and may be used towards the Recurring API to make changes to the agreement.

### Step 3a: Transaction operations

Depending on the payment method additional actions must be taken after a successful payment.

For payment methods `Wallet`/`Card` the amount will be *reserved* on the customer account until you *capture* it to complete the payment. Capture must be done in accordance with the terms and conditions you have with the user. Our recommendation is that this is not performed until the goods or services have been delivered. For more details, see [capture regulations](https://developer.vippsmobilepay.com/docs/knowledge-base/reserve-and-capture.md#capture-regulations).

See the [ePayment API payment operations (if Checkout Session is type: PAYMENT)](https://developer.vippsmobilepay.com/docs/APIs/epayment-api/api-guide/operations/README.md) or [Recurring API charge operations (if Checkout Session is type: SUBSCRIPTION)](https://developer.vippsmobilepay.com/docs/APIs/recurring-api/recurring-api-guide.md#charges) for more information on how to perform capture/cancel/refund on a payment. The merchant credentials and the `reference` are cross compatible between Checkout and ePayment/Recurring APIs. The property referred to as `reference` in Checkout is synonymous with `chargeId` when doing charge/payment operations to Recurring.

**Please note:** That the [eCom API](https://developer.vippsmobilepay.com/docs/APIs/ecom-api/README.md) is deprecated and should not be used, as it lacks full support for card transactions.

**Please note:** Checkout only supports sales units that are set up with type *reserve capture* (as opposed to *direct capture*). Read more about [capture](https://developer.vippsmobilepay.com/docs/knowledge-base/reserve-and-capture.md).

[create-checkout-session-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/checkout-swagger-id.yaml
[retrieve-sessioninfo-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/checkout-swagger-id.yaml
[create-payment-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml
[get-payment-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml
[get-payment-event-log-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml
[cancel-payment-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml
[capture-payment-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml
[refund-payment-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml
[force-approve-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml

> **Full site overview:** For every page in this documentation, read [https://developer.vippsmobilepay.com/llms.txt](https://developer.vippsmobilepay.com/llms.txt).
