Paytrail
Build checkout form with Klarna WebSDK

Integrate Klarna’s Web SDK to deliver a seamless, optimized checkout experience on your site. Initialize the SDK, present Klarna in the payment selector, and finalize the flow with Klarna’s payment button.

Prerequisites recap

Before you integrate, check that you meet the following prerequisites:

  1. Ensure that you have Klarna enabled with Paytrail.
  2. Confirm you have access to the Klarna Portal.
  3. Inside Klarna Portal:
    1. Confirm that you have generated a client identifier with your domain URL allowlisted.
    2. Confirm that you have generated an API key.
  4. Confirm that you have registered webhooks for payment.request.state-change.completed events following Webhooks guidelines.
  5. Add Terms and Conditions for Web SDK.

Subscribing to webhooks in the Klarna Portal will be available in a future release.

Integration overview

Here's an overview of all the steps to display Klarna and initiate payments via the WebSDK:

  1. Present Klarna as a payment option in the payment form.
  2. Customer clicks the Klarna payment button in your checkout.
  3. You create a server-side payment request to Klarna and share available interoperability data points.
  4. If customer interaction is required, Klarna returns a payment_request_id.
    1. The payment_request_id is used to initiate the purchase flow with Klarna’s WebSDK.
    2. The Klarna purchase journey is launched.
    3. The customer completes the Klarna purchase journey.
  5. Klarna returns an interoperability_token via webhook.
  6. You create an authorization request with Paytrail and share the required interoperability data points.
  7. Paytrail responds with an approval and order completion.
  8. Customer is redirected to your confirmation page.
sequenceDiagram participant C as Customer participant P as Partner participant K as Klarna participant AP as Paytrail C->>P: Visit checkout page P->>K: Initialize Klarna SDK P->>K: Request presentation instructions K->>P: Return assets and instructions P->>P: Render payment selector C->>P: Select Klarna payment method P->>P: Update Klarna presentation<br>Show Klarna payment button C->>P: Click Klarna payment button Note over P,AP: Handle the "Pay with Klarna" button click C->>P: Click Klarna payment button P->>K: POST /v2/payment/requests Note over P,K: Share interoperability data points alt Customer interaction required K->>P: Return payment request id P->>K: Return payment request id<br>to Klarna SDK K->>C: Start Klarna purchase journey C->>K: Complete Klarna purchase journey end K->>P: Payment request completed event via webhook Note over K,P: interoperability_token P->>AP: Authorize payment Note over P,AP: Share interoperability data points AP->>P: Respond with approval Note over P,AP: Order completed P->>C: Redirect to confirmation page

Integration details

Present Klarna in the payment form

Presenting Klarna in the payment form involves retrieving the visual assets, localized text, and display instructions required to correctly render Klarna as a payment option and display the payment button. This dynamic presentation ensures a consistent customer experience, accurate localization, and optimized conversion performance, while adapting seamlessly to different checkout states.

​On a high level, the process involves:

  1. Initialize Klarna Web SDK in your checkout experience.
  2. Request Klarna’s payment presentation for the current payment context.
  3. Render Klarna payment option(s) dynamically in the payment form according to the instructions.
  4. Allow the customer to select and deselect a Klarna payment option.
  5. Display the Klarna button and start the payment process when clicked.

​The expected outcomes are as follows:

Initial presentationWhen Klarna is selected

Klarna's payment presentation best practice

To ensure the best user experience and optimal conversion rates when presenting Klarna as a payment option, please apply the following recommendations:

  • Display Klarna descriptor dynamically alongside other payment options in your payment form.
  • Embed Klarna’s UI elements directly in your frontend for a consistent and responsive design.

The next sections in this guideline will walk through how this can be achieved using Klarna Web SDK.

Initialize the Klarna Web SDK

The Klarna Web SDK (klarna.mjs) follows the JavaScript module approach and should be included in places where you need to have a reference to the SDK such as while rendering any components or initiating a payment flow. Here are the initialization parameters:

ParameterPresenceDescription

clientId

requiredA credential used to identify the Partner, which can be obtained from the Klarna Portal. To ensure the credential functions properly, make sure to register all domains where the Web SDK will be used.

products

optionalAn array used to specify which products should be loaded to optimize performance by limiting the amount of data downloaded. If the PAYMENT product is included, only the Klarna.Payment package will be loaded. If the products array is omitted, all available packages will be loaded by default.

locale

optionalLanguage and region code (e.g., en-US). If omitted, Klarna may default based on the customer’s browser settings.

sdkToken

optionalThe short-lived token exchanged from the klarna_network_session_token. Enables restoring the customer's session state securely on the client.

For the full API specifications, refer to Klarna Web SDK.
SDK initialization sample

JAVASCRIPT
<script type="module">
  const { KlarnaSDK } = await import("https://js.klarna.com/web-sdk/v2/klarna.mjs")

  const Klarna = await KlarnaSDK({ 
    clientId: "[client-id]",
    products: ["PAYMENT"],
    locale: "en-US", // optional
  })

  // Klarna SDK ready to be utilized
  // Klarna.Payment.button().mount('#payment_container')
</script>

If the domain is not registered, subsequent method calls will result in an error.

Do
Don't
  • Don’t include the Web SDK in a bundle or host it yourself.
  • Don't load the Web SDK inside an iframe.
  • Don't omit products.
  • Don't use the Web SDK without disclosing tracking technologies.

Klarna payment presentation request

Klarna payment presentation provides all the visual assets, localized texts, and instructions needed to correctly display Klarna in your checkout form.

Use the initialized SDK instance to call the Klarna.Payment.presentation() method.

Basic checkout context parameters must be provided:

ParameterPresenceDescription

amount

conditionalThe transaction amount in minor units following ISO 4217 exponents (e.g., $118.00 = 11800, ¥1400 = 1400). This field is required if any of the intents include PAY, SUBSCRIBE, or DONATE; otherwise, it is optional.

currency

requiredThree-letter ISO 4217 currency code (e.g., USD, EUR).

locale

optionalLocale code to localize texts and formats (e.g., en-US, de-DE). If you don’t set this, it will automatically use the value chosen when you first set up the Web SDK. If that’s not available, it will use your browser’s settings instead.

intents

optionalSpecify the intent of the checkout flow: PAY, SUBSCRIBE, SIGNUP, SIGNIN, DONATE, ADD_TO_WALLET.
If omitted, intents defaults to ["PAY"].

For the full API specifications, refer to Klarna Web SDK.

Performance optimization

It is important to ensure that Klarna is displayed at roughly the same time as other payment methods, with an acceptable delay of less than 100 ms. To achieve this, begin initializing the Klarna Web SDK and invoke the payment presentation method concurrently while loading the list of all enabled payment methods from your server.

Sample code

JAVASCRIPT
const paymentPresentation = await klarna.Payment.presentation({
  amount: 11800,
  currency: "USD",
  locale: "en-US",
  intents: ["PAY"] 
});

Klarna payment presentation response

The PaymentPresentation interface provides the full Klarna branding package and instructions tailored to the customer's purchase:

AttributePresencePurpose

instruction

requiredSpecifies how Klarna as a payment option(s) should be displayed (e.g., whether to show, preselect, or display as show-only). Adhering to these payment presentation instructions ensures customers have the best possible experience and optimizes conversion rates.

paymentOption

optionalDefines the default payment option applicable to all purchase types. This object includes the visual elements required to represent Klarna during checkout.

The paymentOption object structure is as follows:

AttributePresencePurpose

paymentOptionId

requiredThe identifier of the payment option. The value is required to be sent to the Payment Authorize API or the Payment Request API when initiating the payment.

icon


required
Klarna badge/logo suitable for checkout forms.

header


required
The main descriptor that introduces Klarna in the payment form. The value will be dynamically adjusted based on the locale provided.

subheader

requiredThe descriptor subheader which must be loaded inline below the main descriptor header. Short and enriched descriptive texts. Provides transparency on available options like installments, pay later, etc.

message

optionalEnriched tailored description with link.

badge

optionalBadge used for saved options or promotions.

terms

optionalDefines terms/disclosures potentially with links.

paymentButton

requiredPayment button that starts the Klarna purchase journey.

For the full API specifications, refer to Klarna Web SDK.

Follow Klarna payment presentation instruction

This section describes how to apply Klarna’s payment presentation instructions, which define how Klarna should appear in your checkout. Following these instructions ensures a consistent experience across payment states and is required for features like Klarna Express Checkout and Sign in with Klarna.

The instruction attribute has the following values:

InstructionDescription

SHOW_KLARNA

Show Klarna alongside other payment methods.

PRESELECT_KLARNA

Show Klarna pre-selected but still alongside others. This is returned when using the customer_token issued from the Sign in with Klarna feature or the tokenization flow.

SHOW_ONLY_KLARNA

Show Klarna as the only payment method. This is returned when the customer has finished the first step of Klarna Express Checkout multistep.

For the full API specifications, refer to Klarna Web SDK.

Skip this section if you don't use any Conversion Boost features from Klarna such as Klarna Express Checkout, Sign-in with Klarna, Klarna Messaging or Klarna Prequalification.

Here are example outcomes illustrating how Klarna should be displayed for each instruction:

Show KlarnaPreselect KlarnaShow only Klarna

The presentation instructions are derived from possible customer purchase journeys described in the How to present Klarna article.
Sample code:

JAVASCRIPT
function renderKlarna(paymentPresentation) {
  if (!paymentPresentation) return;

  const root = qs("#klarna-payment-method");
  if (!root) {
    console.error("Missing #klarna-payment-method container.");
    return;
  }

  root.innerHTML = `<div id="klarna-option-default" class="klarna-option default" style="display:none;">

</div>

Mount Klarna payment option components

Once an instance of PaymentPresentation is created, the Klarna payment option(s) must be rendered dynamically in the payment selector according to Klarna’s presentation guidelines. The following diagram displays different visual components and how they are rendered in different selection states:

  1. Icon
  2. Badge
  3. Header
  4. Subheader
  5. Message
  6. Terms
  7. Button

Mount the Klarna payment option components within your designated Klarna payment method container to render them dynamically in the payment form. Ensure that all components—including those not immediately visible—are mounted during initialization, and manage their visibility through your own logic or UI controls.

JAVASCRIPT
function renderKlarnaOption(containerId, option) {
  const container = qs(`#${containerId}`);
  if (!container) {
    console.error(`Missing #${containerId} container.`);
    return;
  }

  const ids = {
    icon:    `${containerId}-icon`,
    header:  `${containerId}-header`,
    subhdr:  `${containerId}-subheader`,
    badge:   `${containerId}-badge`,

Handle Klarna payment option selection and deselection

When a Klarna payment option is selected/deselected, ensure the additional visual components are shown/hidden properly.

JS
/**
 * Toggle the Klarna payment option selected state.
 * Use for both SDK preselection (PRESELECT_KLARNA) and user interactions.
 */
function toggleKlarnaPaymentOptionSelection(containerId, isSelected) {
  const container = qs(`#${containerId}`);
  if (!container) {
    console.error(`Missing container #${containerId}.`);
    return;
  }

  const display = isSelected ? "block" : "none";

Handle Klarna payment button styling and initiate callback

The payment presentation instance allows you to mount the prebuilt button component. The Klarna Payment Button is context-aware and dynamically adapts to your configuration.

Klarna payment button variants

Choose the theme and shape of the payment button to best fit into your online store in a way that complements your brand and encourages user engagement. More details on the button styling can be found here.

Configure Klarna payment button

The paymentButton.component() can be configured with the following set of parameters:

ParameterDescription

id

Sets a custom DOM ID on the rendered button. Useful for testing or styling.

shape

Defines the button’s shape. Possible values are:default, pill, rect

theme

Sets the visual theme of the button. Possible values are: default, light, dark, outlined

locale

Sets the language and region (e.g., en-US). If you don’t set this, it will automatically use the value chosen when you first set up the Web SDK. If that’s not available, it will use your browser’s settings instead.

disabled

Disables the button when set to true. Useful during form validation or async operations.

loading

Forces the button into a loading state. Useful when awaiting async setup or validation.

intents

Sets the purpose of the payment. Used to personalize the button and flow if not set when creating the PaymentPresentation instance.

initiate

Function that returns a Promise resolving to either a PaymentRequestData, a paymentRequestId, or a returnUrl. This will be handled differently depending on the integration path.

initiationMode

Defines how Klarna launches the purchase journey.

For the full API specifications, refer to Klarna Web SDK.

Sample code

JAVASCRIPT
option
  .paymentButton
  .component({
    id: "klarna-payment-button",  // optional test hook
    shape: "pill",                // "default" | "pill" | "rect"
    theme: "default",             // "default" | "light" | "dark" | "outlined"
    intents: ["PAY"],
    initiationMode: "DEVICE_BEST", // "DEVICE_BEST" | "ON_PAGE" | "REDIRECT"
    initiate: (klarnaNetworkSesionToken, paymentOptionId) => initiateKlarnaPayment(klarnaNetworkSesionToken, paymentOptionId)
  })
  .mount(`#${containerId}-payment-button`);

The button will automatically handle customer interaction and trigger the Klarna purchase flow via the initiate function.

Handle the payment button click

Initiate the purchase journey

In order to launch the purchase flow, you need to implement the initiate callback on the Klarna payment button interface. The initiate callback is triggered when the customer clicks on the Klarna payment button, upon which, the payment request data such as amount and currency must be submitted to Klarna server.

ParameterPresence

currency

required
Currency in ISO 4217 format.
Supported currencies: AUD, EUR, CAD, CZK, DKK, HUF, MXN, NZD, NOK, PLN, RON, SEK, CHF, GBP, USD.

amount

required
Total amount of a one-off purchase, including tax and any available discounts. The value should be in non-negative minor units. Eg: 25 Dollars should be 2500. This is the amount that Klarna will charge the customer for a one-off purchase. Should not include any amounts for subscriptions.

supplementaryPurchaseData

optional
Additional details about the transaction can help reduce the risk of fraud and enhance transparency.
  • purchase_reference

  • customer

  • shipping

  • line_items

  • customer.customer_accounts

    / customer.customer_device
  • travel_reservations

  • lodging_reservations

  • insurances

  • vouchers

  • event_reservation

  • ondemand_service

  • subscription

  • in_store_service

  • marketplace_seller_details

For the full API specifications, refer to the API referenceKlarna Icon.

Create Klarna payment request on the server side and initiate the purchase flow using Klarna Web SDK

Create a payment request on the server side is the recommended approach to create the payment request, then share the payment request ID as response to the initiate callback.

Client code

JAVASCRIPT
const klarnaPaymentButton = klarna.Payment.button({
  initiate: async () => {
    const resp = await fetch('/create-klarna-payment-request', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ /* Your data here */ })
    });
    const data = await resp.json();
    return { paymentRequestId: data.paymentRequestId };
  }
});

For the full API specifications, refer to Klarna Web SDK.

Server code

JAVASCRIPT
// Server.js
// Simplified backend example for creating a Klarna payment request

const axios = require('axios');

// Klarna credentials and base URL (replace with your keys and consider loading from environment variables)
const KLARNA_API_KEY = 'YOUR_API_KEY';
const KLARNA_BASE_URL = 'https://global-api.klarna.com'; // According to docs

// Function to create a Klarna payment request
async function createKlarnaPaymentRequest(data) {
  const url = `${KLARNA_BASE_URL}/v2/payment/requests`;

For the full API specifications, refer to the API referenceKlarna Icon.

Create a new payment request on every button click instead of reusing payment requests.

Monitor payment status

This guide outlines how to monitor the Klarna Payment Request as part of the step up scenario. On a high level:

  • Understand payment request lifecycle in order to handle COMPLETED, CANCELED, DECLINED and EXPIRED states properly.
  • Monitor and retrieve the klarna_network_session_token and/or customer_token by using one or a combination of the following methods:
    • Subscribing to payment.request.state-change.* webhook events (required)
    • Reading the payment request

Payment request lifecycle

During the checkout process, the Payment Request will transition to various states. Find below an overview of the possible payment request states together with a transition diagram:

StateDescriptionNext action

SUBMITTED

Initial state. Payment requests can be updated until the customer enters Klarna Journey.Handle step-up scenario.

IN_PROGRESS

The customer is actively in Klarna’s purchase journey.Listen for state changes via webhook.

COMPLETED

Customer completed the flow, pending final authorization.Retrieve klarna_network_session_token and create a payment transaction.

EXPIRED

Payment request expired (t≥3h).Final state. No action.

CANCELED

Payment request canceled by the integrator before authorization.Final state. No action.

DECLINED

Payment request has been declined during authorization.Final state. No action.

<u>State transition diagram</u>

flowchart LR Start((Start)):::teritiaryEntity --> SUBMITTED1[<b>SUBMITTED</b>]:::secondaryEntity %% -------------------------------------------------- %% Submission Handling %% -------------------------------------------------- subgraph Submission_Handling [<b>Submission handling</b>] direction TB SUBMITTED1 --> Decision1{ }:::teritiaryEntity Decision1 -->|Customer enters<br/>Purchase Journey| IN_PROGRESS[<b>IN_PROGRESS</b>]:::secondaryEntity Decision1 -->|Acquiring Partner<br/>cancels request| CANCELED1[<b>CANCELED</b>]:::primaryEntity Decision1 -->|Acquiring Partner<br/>updates request| SUBMITTED2[<b>SUBMITTED</b>]:::secondaryEntity Decision1 -->|"Request expired<br/>(≥ 3h)"| EXPIRED1[<b>EXPIRED</b>]:::primaryEntity end %% -------------------------------------------------- %% Purchase Journey Outcome %% -------------------------------------------------- subgraph Purchase_Journey_Outcome [<b>Purchase journey outcome</b>] direction TB IN_PROGRESS --> Decision2{ }:::teritiaryEntity Decision2 -->|Klarna accepts<br/>purchase| COMPLETED[<b>COMPLETED</b>]:::primaryEntity Decision2 -->|Customer aborts| SUBMITTED3[<b>SUBMITTED</b>]:::secondaryEntity Decision2 -->|Acquiring Partner<br/>cancels request| CANCELED2[<b>CANCELED</b>]:::primaryEntity Decision2 -->|"Request expired<br/>(≥ 3h)"| EXPIRED2[<b>EXPIRED</b>]:::primaryEntity Decision2 -->|"Customer rejected - no payment methods available"| DECLINED[<b>DECLINED</b>]:::primaryEntity end

A Payment Request remains open for 3 hours. Klarna recommends Partners proactively cancel Payment Requests which have not resulted in successful transactions, especially if your Payment Request timeout is less than 3 hours.

Monitor and retrieve interoperability_token

To retrieve the required token(s), Klarna provides multiple integration methods. Subscribing to Klarna webhook events is required and may be combined with additional methods to improve resilience.

Using webhooks ensures reliable completion handling, particularly when the customer closes the browser before returning, network interruptions occur during redirects, or post-processing is required before notifying the customer.

The klarna_network_session_token is issued by Klarna after the customer approves the purchase. Use this token to finalize the authorization and create the corresponding Klarna payment transaction.

The klarna_network_session_token is valid for only 1 hour and must be used within this time frame to finalize the authorization.

Method: Subscribe to webhook events (required)

Subscribe to the payment.request.state-change.completed webhook event using the guidelines provided here. Klarna sends this event when the Payment Request reaches the COMPLETED state.

This event indicates that the customer has finished the step-up interaction and that the Acquiring Partner can proceed with finalizing the authorization.

Sample payload

JSON
{
  "metadata": {
    "event_type": "payment.request.state-change.completed",
    "event_id": "d9f9b1a0-5b1a-4b0e-9b0a-9e9b1a0d5b1a",
    "event_version": "v2",
    "occurred_at": "2024-01-01T12:00:00Z",
    "correlation_id": "2d1557e8-17c3-466c-924a-bbc3e91c2a02",
    "subject_account_id": "krn:partner:global:account:live:HGBY07TR",
    "recipient_account_id": "krn:partner:global:account:live:LWT2XJSE",
    "product_instance_id": "krn:partner:product:payment:ad71bc48-8a07-4919-[...]",
    "webhook_id": "krn:partner:global:notification:webhook:120e5b7e-abcd-4def-[...]",
    "live": false

Consult the API referenceKlarna Icon for a complete description of the webhook payload.

Method: Read the payment request

As an alternative method, retrieve the Klarna token(s) by calling the Read Payment Request APIKlarna Icon.

Once the Payment Request reaches the COMPLETED state, the token(s) are available in the state_context object of the Payment Request.

Sample payload

JSON
{
  "payment_request_id": "krn:payment:eu1:request:10be1d49-7beb-6b24-b9dd-8c14d0528503",
  "state": "COMPLETED",
  "previous_state": "IN_PROGRESS",
  "state_context": {
    "klarna_network_session_token":"krn:network:eu1:live:session-token:[...]"
  },
  "expires_at": "2025-02-26T17:25:34.534721775Z",
  "created_at": "2025-02-24T17:25:34.534721775Z",
  "updated_at": "2025-02-24T17:25:34.534721775Z",
  "payment_request_reference": "request-reference-1234",
  "amount": 11836,

Authorize the payment

Make sure to add the interoperability_token received via the webhook and the purchase details within the call to Paytrail. If everything is implemented correctly, Klarna will approve the payment transaction.

BASH
curl -X POST https://api.acquiring-partner.com/payment \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1000,
    "currency": "USD",
    "payment_methods": {
      "klarna": {
        "klarna_interoperability_token": ""
      }
    }
  }'

In rare cases where there's discrepancy between the amount and purchase details submitted in the original payment request and the information submitted to Paytrail, Klarna may reject and ask the customer to approve the purchase again.