Payment Authorization for Hosted Checkout integration

Integrate Klarna's Payment Authorize API for hosted checkout and embedded elements. This guide covers backend implementation for handling authorization results, step-up flows, and finalizing payments.

Overview

This guide is part of the Payment Authorization flow for hosted checkout and embedded elements integration path. It covers the backend implementation — what the Acquiring Partner's server does after the customer interacts with the Klarna payment form on the frontend.

Where this fits in the integration flow:

  • Payment Presentation — Your frontend presents Klarna payment methods and collects the customer's selection (previous step)
  • Authorize the payment (backend) — Your backend receives the frontend request and calls Klarna's Payment Authorize API (this step)
  • Manage payment transactions — Capture, refund, or cancel authorized payments (next step)

This guide is a continuation of the Payment Presentation guide and focuses on the server-side authorization flow.

What you'll implement:

  • A backend endpoint that receives authorization requests from your frontend
  • Integration with the authorizePaymentAPI API
  • Handling of all authorization outcomes (APPROVED, STEP_UP_REQUIRED, DECLINED)

Prerequisites

Before implementing the backend endpoint, ensure you have:

  • A working Payment Presentation implementation — your frontend can present Klarna payment methods and collect the customer's selection
  • The ability to collect payment context from the Partner (amount, currency, supplementary_purchase_data, klarna_network_session_token, klarna_network_data)
  • A Partner Account onboarded with Klarna
  • An API Key associated with your Partner Account
  • A Klarna webhook endpoint configured to receive Klarna events

Integration overview

Your backend's role: Your backend receives the authorization request from the frontend, calls Klarna's authorizePaymentAPI API, and returns the result so the frontend can proceed accordingly.

The backend authorization flow starts after the customer selects a Klarna payment method in your checkout. Your frontend triggers the initiate callback, which calls your backend. Your backend then forwards the request to Klarna and returns the result.

The integration process consists of the following key steps:

  1. 1.
    Your frontend triggers the initiate callback: The Klarna web SDK calls your configured callback when the customer initiates a payment authorization.
  2. 2.
    Your backend receives the authorization request: Accept klarna_network_session_token and payment_option_id from your frontend
  3. 3.
    Your backend calls the authorizePaymentAPI endpoint: Forward the payment context to Klarna
  4. 4.
    Your backend handles authorization results: Process STEP_UP_REQUIRED, APPROVED, or DECLINED outcomes and return the result to your frontend
  5. 5.
    Your frontend configures initiationMode: Control how the Klarna Web SDK launches the Klarna Purchase Journey for step-up
  6. 6.
    Your backend monitors step-up completion: Detect when the customer completes the Klarna Purchase Journey (for STEP_UP_REQUIRED)
  7. 7.
    Your backend finalizes the authorization: Complete the authorization after the customer finishes step-up
sequenceDiagram autonumber participant Customer participant APFrontend as Acquiring Partner (Frontend) participant APBackend as Acquiring Partner (Backend) participant KlarnaAuth as Klarna Payment Authorize API participant WebSDK as Klarna Web SDK Note over Customer,WebSDK: Payment Presentation integration (previous step) Note over Customer,APFrontend: Customer clicks Klarna payment button Customer->>APFrontend: Click payment button APFrontend->>WebSDK: initiate callback triggered WebSDK->>APFrontend: Provide klarnaNetworkSessionToken and paymentOptionId Note over APFrontend,APBackend: Step 1: Initiate callback triggered Note over APFrontend,APBackend: Step 2: Frontend calls backend APFrontend->>APBackend: POST /api/authorize-payment Note over APBackend,KlarnaAuth: Step 3: Backend calls Klarna API APBackend->>KlarnaAuth: POST /payment/authorize KlarnaAuth-->>APBackend: Authorization result Note over APBackend,APFrontend: Step 4: Handle results and return response alt result: APPROVED APBackend-->>APFrontend: Return APPROVED with successUrl APFrontend->>WebSDK: Return successUrl WebSDK->>Customer: Redirect to confirmation else result: STEP_UP_REQUIRED APBackend-->>APFrontend: Return STEP_UP_REQUIRED with paymentRequestId APFrontend->>WebSDK: Return paymentRequestId WebSDK->>Customer: Launch Klarna Purchase Journey Note over Customer,WebSDK: Customer completes authentication WebSDK->>Customer: Redirect to confirmation else result: DECLINED APBackend-->>APFrontend: Return DECLINED APFrontend->>Customer: Handle rejection (offer alternatives) end

Integration details

Step 1: Implement initiate callback

When the customer selects a Klarna payment method and clicks the Klarna payment button in your checkout, the Klarna web SDK triggers the initiate callback function configured in your Payment Presentation. This callback calls your backend authorization endpoint.

Implement the initiate callback to call your backend endpoint and handle authorization results. The frontend is responsible for:

  1. 1.
    Calling the backend authorization endpoint with the klarnaNetworkSessionToken and paymentOptionId
  2. 2.
    Handling the authorization response based on the result field
  3. 3.
    Returning the paymentRequestId to the Klarna Web SDK if step-up is required (the SDK handles launching the Klarna Purchase Journey)
  4. 4.
    Redirecting on success or displaying errors
JS
async function initiateKlarnaPayment(klarnaNetworkSessionToken, paymentOptionId) {
  try {
    // 1) Ask your backend to authorize the payment
    const response = await fetch('/api/authorize-payment', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ klarnaNetworkSessionToken, paymentOptionId })
    });

    if (!response.ok) throw new Error('Network or server error');

    // 2) Handle backend response

The following steps in this guide explain how to implement the backend endpoint that this initiate callback calls.

Step 2: Receive authorization request from frontend

Your backend endpoint receives the authorization request from the frontend after the customer clicks the Klarna payment button.

Endpoint: POST /api/authorize-payment (or your chosen path)

Input from frontend (provided by the Klarna Web SDK via the initiate callback):

ParameterTypeRequiredDescription
klarnaNetworkSessionTokenstringYesThe session token provided by the Klarna Web SDK through the initiate callback
paymentOptionIdstringYesThe payment option identifier selected by the customer, provided by the Klarna Web SDK through the initiate callback

Example frontend request:

JSON
{
  "klarnaNetworkSessionToken": "krn:network:us1:test:session-token:eyJhbGciOiJIU[...]",
  "paymentOptionId": "S0xBUk5BXzE3NzI3MjQ5MTQzMjk="
}

Step 3: Call the Payment Authorize API

Forward the complete payment context to Klarna using the Payment Authorize API. Include all payment data collected from the Partner (same as used during Payment Presentation).

The authorizePaymentAPI API is used to start the payment process on Klarna whether they are with or without customer presence.

SHELL
curl https://api-global.test.klarna.com/v2/accounts/{partner_account_id}/payment/authorize \
  -H 'Authorization: Basic <API key>' \
  -H 'Content-Type: application/json' \
  -H 'Klarna-Customer-Token: krn:partner:us1:test:identity:customer-token:ACZawkw7-2[...]' \
  -H 'Klarna-Network-Session-Token: krn:network:us1:test:session-token:eyJhbGciOiJIU[...]' \
  -d '{
        "currency": "USD",
        "supplementary_purchase_data": {
          "purchase_reference": "ORDER-12345",
          "line_items": [
            {
              "name": "Running Shoes",

The customer_token can be obtained from the Payment Tokenization flow.

Important considerations:

  • Use the same amount, currency, and supplementary_purchase_data values collected from the Partner (same as used during Payment Presentation)
  • Always configure step_up_config with HANDOVER method to allow the customer to complete authentication when needed

Step 4: Handle authorization results and return response to frontend

The authorizePaymentAPI API returns one of three possible results in the payment_transaction_response.result field. Your backend reads this field and returns the appropriate data to your frontend so it can proceed.

The result field indicates the outcome and determines your next action. It has the following possible values:

ResultDescriptionNext steps
STEP_UP_REQUIREDAdditional customer interaction is needed to complete the authorization (step-up scenario). A payment_request is created.Handle this result when Klarna requires additional customer interaction to complete authorization:
  • Return the payment_request_id to your frontend. The Klarna Web SDK launches the Klarna Purchase Journey for the customer to complete.
  • The customer (who must be present) completes the Klarna Purchase Journey.
  • Wait for step-up completion before finalizing the Payment Authorization.
  • Return URLs must be provided when calling authorizePaymentAPI to redirect the customer after they complete or stop the purchase journey.
APPROVEDThe authorization succeeded and a payment_transaction was created.The Payment Authorization is complete. Handle this result when Klarna authorizes the payment without requiring customer interaction:
  • Read and store the payment_transaction as well as klarna_network_response_data from the response if present.
  • Return the klarna_network_response_data to the Partner without modification if present.
  • Return a success response to the Partner.
  • Proceed with post-purchase operations (for example, capture or refund).
DECLINEDThe authorization was not approved and no transaction was created.Handle the rejection in your frontend (for example, offer the customer alternative payment methods):
  • Return a decline indicator to the Partner.
  • No payment_transaction is created.

Here's the high-level diagram of the Payment Authorization results and resources it produces:

Payment authorization results

The response schema is as follows:

JSON
{
  "payment_transaction_response": {
    "result": "STEP_UP_REQUIRED"
  },
  "payment_request": {
    "payment_request_id": "krn:payment:us1:request:552603c0-fe8b-4ab1-[...]",
    "payment_request_reference": "backend-request-ref-12345",
    "amount": 11800,
    "currency": "USD",
    "state": "SUBMITTED",
    "expires_at": "2025-01-02T13:00:00Z",
    "created_at": "2025-01-01T12:00:00Z",

Your backend endpoint should handle the different authorization outcomes and communicate the results to your frontend.

Here is an example showing how your frontend can retrieve the results from your backend endpoint

JS
// Example Node.js/Express endpoint
app.post('/api/authorize-payment', async (req, res) => {
  try {
    const { klarnaNetworkSessionToken, paymentOptionId } = req.body;

    // Call Klarna Payment Authorize API
    const klarnaResponse = await callKlarnaAuthorizeAPI({
      klarnaNetworkSessionToken,
      paymentOptionId,
      amount: 11800,
      currency: 'USD',
      // ... other payment context

What happens next:

When the frontend receives STEP_UP_REQUIRED with the paymentRequestId, the Klarna Web SDK automatically launches the Klarna Purchase Journey (see Step 5).

Return URLs for step-up scenario

Acquiring Partners must include return URLs in the step_up_config when calling authorizePaymentAPI to enable the step-up scenario.

These URLs, set inside the customer_interaction_config object, tell Klarna where to redirect the customer after they complete or stop the purchase journey.

return_url

If the Klarna Purchase Journey is launched in a web environment, Klarna redirects the customer to the return_url after they finish — whether they complete or stop the flow. This can be a URL managed by the Acquiring Partner (which handles redirection logic) or one collected directly from the Partner.

app_return_url

On mobile, the customer may be redirected to a third-party app (such as a bank app) or the Klarna app during the purchase journey. The app_return_url brings the customer back to the Partner's mobile app when this happens.

Partners must register a URL scheme (e.g., yourapp://klarna) or a universal link that resumes the payment flow. Klarna invokes this URL after the customer completes a native app-based step, such as biometric authentication or Klarna app login. Partners are expected to resume the mobile app in its last state without applying state changes or deep link navigations.

Interaction scenarios

The return_url and app_return_url are not mutually exclusive. Depending on the device and environment, either or both may be triggered:

ScenarioDescription
Pure web flowThe customer starts the purchase journey in a desktop browser. After completing the flow, Klarna redirects them to return_url.
App-to-app flowThe Partner's native app opens the purchase journey using a universal link. If the Klarna app is installed, the customer goes directly into it. After completion, Klarna redirects them to app_return_url.
WebView flow with app handoverThe Partner's native app starts the purchase journey in a System WebView. If the customer must authenticate via an external banking app, app_return_url returns them to the Partner's app mid-flow. They then resume in the WebView and, on completion, are redirected to return_url.

If the Acquiring Partner already collects a suitable return_url or app_return_url from the Partner, do not request a second one — this would increase the minimum integration requirements for Klarna to work.

Step 5: Handle step-up scenario

A step-up occurs when Klarna requires additional customer interaction to complete a Payment Authorization — for example, when the customer needs to log in, authenticate, or select a payment method.

When step-up is triggered, authorizePaymentAPI returns a STEP_UP_REQUIRED result along with a Payment Request containing the payment_request_id which is required for the Klarna Web SDK to launch the Klarna Purchase Journey.

Configure initiationMode

The Klarna web SDK launches the purchase journey through the initiate function on the Klarna Payment button. The function returns a promise that resolves to an object containing the paymentRequestId:

JAVASCRIPT
const buttonConfig = {
  initiate: () => {
    // Call to Payment Authorize API returns STEP_UP_REQUIRED
    return { paymentRequestId: "krn:payment:us1:request:552603c0-fe8b-4ab1-[...]" };
  },
  initiationMode: "DEVICE_BEST", // "DEVICE_BEST" (default) | "ON_PAGE" | "REDIRECT"
};

// Render and mount the button with the assigned configuration
paymentPresentation.paymentButton
  .component(buttonConfig)
  .mount("#klarna-button-container");

The initiationMode parameter controls how the Klarna Purchase Journey is launched when your backend returns STEP_UP_REQUIRED. Configure this in your frontend payment button.

initiationModeDescription
DEVICE_BESTAutomatically selects the best way to launch the Klarna Purchase Journey depending on the device - this is the default and recommended value: *Mobile: Always redirect *Desktop: pop-up if possible, fallback to redirect
  • Native webview: Always redirect Note: for this initiationMode, a return_url is required in the customer_interaction_config object when calling the Payment Authorize API.
ON_PAGEThe Klarna Purchase Journey is triggered on the same page. The customer never leaves the page. The Klarna Purchase Journey opens in a pop-up if possible and fallback to fullscreen iframe if necessary.
REDIRECTThe customer will be redirected to the Klarna Purchase Journey. Note: for this initiationMode, a return_url is required in the customer_interaction_config object when calling the Payment Authorize API.

When does this matter? The initiationMode parameter only affects the customer experience when your backend returns STEP_UP_REQUIRED. If your backend returns APPROVED, the customer proceeds directly to the confirmation page without launching the Klarna Purchase Journey.

For complete frontend implementation details, see the Payment Presentation guide.

Launching the Klarna Purchase Journey

The purchase journey allows the customer to authenticate with Klarna (via login, one-time passwords, etc.), choose a payment method, and accept the payment.

Phone collection in the Klarna purchase journey

Handle customer return after Klarna's purchase journey

Klarna redirects the customer to the return_url in customer_interaction_config, except when a pop-up experience is used and the customer stops the flow.

On completion, Klarna issues a klarna_network_session_token to the Acquiring Partner to finalize the payment.

Web SDK events

Acquiring Partners can register event handlers on the KlarnaPayment SDK interface to track purchase journey stages:

Event handlerPurpose
on("complete", callback)Triggered when the customer accepts the purchase. During a redirect flow, the handler fires once the success page loads. Pending updates are triggered even if the handler is registered after the page loads, removing the need for polling.
on("abort", callback)Triggered when the customer stops the Klarna purchase journey.
on("error", callback)Triggered when an error occurs during the Payment Request lifecycle. When defined, all errors are emitted to this handler instead of being thrown.

Event handlers provide access to the following paymentRequest properties:

PropertyDefinition
paymentRequestIdUnique identifier of the Payment Request.
stateCurrent state of the Payment Request.
previousStatePrevious state of the Payment Request.
stateReasonThe reason the Payment Request is in its current state.
stateContextState-specific context. The klarna_network_session_token is stored here when the Payment Request reaches the COMPLETED state.
JAVASCRIPT
klarna.Payment.on("complete", (paymentRequest) => {
  console.log("Payment request completed");
  // By default, Klarna will redirect to the submitted return_url upon completion.
  // Return false if you want to prevent the redirection to the success page.
  return true
});

Use Web SDK events to enhance the customer experience — for example, displaying clear error messages when a purchase is stopped, or disabling page interactions while payment authorization is in progress.

Never use SDK events to trigger Payment Authorization. Always rely on Klarna webhooks to receive the klarna_network_session_token and finalize the payment after the customer approves the purchase.

Step 6: Monitor step-up completion (for STEP_UP_REQUIRED)

When the authorizePaymentAPI API returns STEP_UP_REQUIRED, the customer needs to complete the Klarna Purchase Journey before you can finalize the authorization. Your backend monitors for step-up completion by the customer to know when to proceed.

Once the customer completes the step-up, Klarna issues a new klarna_network_session_token that you'll need for the finalization call in Step 7.

The klarna_network_session_token is valid for only 1 hour, so be sure to use it promptly.

Method 1: Subscribe to Klarna 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:test:HGBY07TR",
    "recipient_account_id": "krn:partner:global:account:test:LWT2XJSE",
    "product_instance_id": "krn:partner:product:payment:ad71bc48-8a07-4919-[...]",
    "webhook_id": "krn:partner:global:notification:webhook:120e5b7e-abcd-4def-[...]",
    "live": false

Method 2: Read the Payment Request (optional/fallback)

As an alternative method, retrieve the Klarna token(s) by calling the readPaymentRequestAPI API.

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:us1:request:552603c0-fe8b-4ab1-[...]",
  "state": "COMPLETED",
  "previous_state": "IN_PROGRESS",
  "state_context": {
    "klarna_network_session_token": "krn:network:us1:test:session-token:eyJhbGciOiJIU..."
  },
  "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": "backend-request-ref-12345",
  "amount": 11800,

Step 7: Finalize the authorization (after step-up completion)

After receiving the klarna_network_session_token from webhook or polling, finalize the authorization by calling the Payment Authorize API again with the new token.

Finalization request

Call authorizePaymentAPI using:

  • The newly obtained klarna_network_session_token in the Klarna-Network-Session-Token request header
  • The same payment context (amount, currency, supplementary_purchase_data, klarna_network_data) used in the initial authorization
  • The same payment_transaction_reference to link the requests

Example finalization request:

SHELL
curl https://api-global.test.klarna.com/v2/accounts/{partner_account_id}/payment/authorize \
  -H 'Authorization: Basic <API key>' \
  -H 'Content-Type: application/json' \
  -H 'Klarna-Network-Session-Token: krn:network:us1:test:session-token:eyJhbGciOiJIU...' \
  -d '{
        "currency": "USD",
        "supplementary_purchase_data": { ... },
        "klarna_network_data": "{\"content_type\":\"vnd.klarna.network-data.v1+json\",\"content\":{\"operation\":\"payment_request\",\"request\":{\"supplementary_purchase_data\":{...}}}",
        "request_payment_transaction": {
          "amount": 11800,
          "payment_option_id": "S0xBUk5BXzE3NzI3MjQ5MTQzMjk=",
          "payment_transaction_reference": "backend-transaction-ref-12345"

If the klarna_network_session_token has expired (1-hour validity) or the payment context doesn't match the initial authorization, the finalization call returns DECLINED.

Expected finalization response

When finalization succeeds, Klarna returns APPROVED with the payment transaction:

JSON
{
  "payment_transaction_response": {
    "result": "APPROVED",
    "payment_transaction": {
      "payment_transaction_id": "krn:payment:us1:transaction:791bbb7b-813a-[...]",
      "amount": 11800,
      "currency": "USD",
      "payment_pricing": {...},
      "payment_funding": {
        "type": "GUARANTEED",
        "state": "FUNDED"
      }

Step 8: Return authorization outcomes to the Partner

Map the Klarna authorization result to the Partner-facing API response:

  • klarna_network_response_data

Requirements

  • Treat this value as an opaque string; do not validate or infer its structure.
  • Use exact parameter name klarna_network_response_data in the Partner-facing API to ensure Partners can easily identify and use the parameter
  • All returned data MUST be forwarded without modification. Below is an example of how Acquiring Partners can return the Klarna Network Response Data parameter in their Partner-facing APIs.
JSON
{
  "checkout_id": "cs_27234RBQD9NAKD032BN",
  "amount": 17800,
  "status": "completed",
  "currency": "USD",
  "additional_data": {
    "klarna_network_response_data": "{\"content_type\":\"vnd.klarna.network-data.v1+json\",\"content\":{\"operation\":\"payment_request\",\"response\":{\"result\":\"APPROVED\",\"payment_transaction\":{\"payment_transaction_id\":\"krn:payment:us1:transaction:791bbb7b-813a-[...]\"}}}}"
  }
}

Next steps

After implementing the backend authorization endpoint, complete your integration:

Related articles

API & SDK references

API