Save a customer's Klarna payment method from the backend using the canonical Payment Request, Klarna Purchase Journey, token issuance flow. Step-by-step server-side implementation for Partners, with sample requests and responses for tokenization only and tokenization combined with an initial payment.
Use this guide to save a customer's Klarna payment method from the backend without embedding the Klarna Web SDK in the checkout. Partners create a Payment Request that asks Klarna to issue a customer_token, redirect the customer to the Klarna Purchase Journey to collect consent, then either store the issued token (tokenization only) or finalize an initial Payment Transaction (tokenization combined with authorization).
This page is the tokenization counterpart of Authorize a customer-initiated payment (server-side). It uses the same createPaymentRequest, redirect, webhook, authorizePayment pattern, with one extra parameter (request_customer_token) that tells Klarna to issue a token alongside (or instead of) a Payment Transaction.
A backend that creates a Payment Request with request_customer_token and stores the resulting payment_request_id.
A redirect step from the checkout to the Klarna Purchase Journey.
A webhook handler that processes payment.request.state-change.completed and extracts either the customer_token (tokenization only) or the klarna_network_session_token (tokenization combined with authorization).
For combined flows, a backend step that finalizes the Payment Transaction with authorizePayment.
Secure storage of the issued customer_token, ready to be reused on subsequent authorizations.
When Klarna is embedded in the checkout via the Klarna Web SDK, follow Tokenization for hosted checkout pages and embedded elements instead. The SDK orchestrates the same underlying API calls, but launches the Klarna Purchase Journey in a popup or modal rather than via a full-page redirect.
The flow is the canonical Partner Payment Request flow, with two branches that diverge after the customer completes the Klarna Purchase Journey:
The Partner's backend calls createPaymentRequest with request_customer_token (and, for the combined flow, an amount) plus customer_interaction_config.method = HANDOVER.
Klarna responds with a payment_request_id and a payment_request_url.
Redirect the customer's browser to the payment_request_url.
The customer authenticates with Klarna and approves the tokenization (and the initial payment, when one was requested) in the Klarna Purchase Journey.
Klarna sends a payment.request.state-change.completed webhook.
Branch on the scenario:
Tokenization only: The webhook payload (and the Payment Request's state_context.klarna_customer.customer_token) carry the issued customer_token. Tokenization is complete: store the token securely and confirm the outcome to the customer. No further API call is needed.
Tokenization combined with authorization: The webhook payload carries a klarna_network_session_token. Call authorizePayment with the Klarna Network Session Token in the Klarna-Network-Session-Token header to create the initial Payment Transaction. The response includes both customer_token_response (the issued token) and payment_transaction_response (the payment outcome).
sequenceDiagram
autonumber
participant C as Customer
participant P as Partner
participant K as Klarna
C->>P: Initiate tokenization (subscription signup, save card, free trial)
P->>K: createPaymentRequest (request_customer_token, customer_interaction_config=HANDOVER)
K->>P: payment_request_id, payment_request_url, state=SUBMITTED
P->>C: Redirect to payment_request_url
C->>K: Authenticate and approve tokenization in the Purchase Journey
K->>C: Redirect to return_url
K-->>P: Webhook payment.request.state-change.completed (state=COMPLETED)
alt Tokenization only
Note over K,P: Payload carries customer_token in klarna_customer
P->>P: Store customer_token securely
P->>C: Confirm tokenization success
else Tokenization combined with authorization
Note over K,P: Payload carries klarna_network_session_token
P->>K: authorizePayment with Klarna-Network-Session-Token header
alt APPROVED
K->>P: customer_token_response + payment_transaction_response (APPROVED)
P->>P: Store customer_token and payment_transaction_id
P->>C: Show success page
else DECLINED
K->>P: customer_token_response + payment_transaction_response (DECLINED)
Note over P: Token may still be issued, inspect customer_token_response
P->>C: Show alternative payment page
end
end
From the Partner's backend, call createPaymentRequest with the tokenization context and a customer_interaction_config describing how Klarna should hand the customer over to the Klarna Purchase Journey. For server-rendered checkouts, set method = HANDOVER and provide a return_url (and optionally an app_return_url for native apps).
The request structure depends on whether the payment method is being saved alone, or saved together with an initial payment.
Use this shape to save a payment method without an immediate charge (for example, a free trial, wallet linking, or "save card for later"). Include request_customer_token and omitrequest_payment_transaction and amount.
Include at minimum:
Parameter
Required
Description
currency
Yes
Currency in ISO 4217 format. The token's currency context for future transactions.
request_customer_token.scopes
Yes
Token scope. Use payment:customer_not_present for subscription / scheduled billing, payment:customer_present for on-demand / one-click. See token scopes.
request_customer_token.customer_token_reference
Recommended
The Partner's own reference for the token, used for reconciliation and to link the token to a customer record.
customer_interaction_config.method
Yes
Set to HANDOVER for the redirect-based server-side flow. The customer must always provide consent for tokenization, so HANDOVER is mandatory here.
customer_interaction_config.return_url
Yes
URL on the Partner's domain where Klarna redirects the customer after the Klarna Purchase Journey.
customer_interaction_config.app_return_url
Recommended (mobile)
App scheme or universal link that returns the customer to the Partner's native app after a mid-flow handover to a third-party app (such as a bank app or the Klarna app). Not a substitute for return_url.
payment_request_reference
Recommended
The Partner's own reference for the Payment Request, used for reconciliation.
supplementary_purchase_data
Recommended
Additional context describing the tokenization use case. Significantly improves underwriting and powers customer communication. See supplementary purchase data.
supplementary_purchase_data.subscriptions
Conditional
Required when the token will be used for subscription authorizations (scope payment:customer_not_present). Include subscription reference, billing plans, and free-trial status.
supplementary_purchase_data.ondemand_service
Conditional
Required when the token will be used for on-demand authorizations (scope payment:customer_present). Describes the service the token will be used for.
supplementary_purchase_data.customer
Recommended
Customer context (name, email, address). Used by Klarna to simplify sign-up and for fraud assessment.
acquiring_config
Conditional
Routes the Payment Request to a specific Payment Account or Payment Acquiring Account. Required when the Partner's Klarna setup includes more than one account. See Payment Request resource.
Optionally set customer_interaction_config.interaction_expiry to override the default 3-hour Payment Request lifetime. See Custom Payment Request expiry.
Token scope selection is critical
The token scope must match the intended re-authorization pattern:
payment:customer_present is for on-demand re-authorizations where the customer is present.
payment:customer_not_present is for unattended scheduled authorizations.
Klarna issues exactly one scope per token, and it cannot be changed later. See the token scopes guidance for help choosing.
Redirect the customer to the payment_request_url returned in Step 1. The Klarna Purchase Journey lets the customer authenticate with Klarna (login, one-time passcode, biometrics), confirm tokenization consent, and (for combined flows) approve the initial payment.
On completion, Klarna redirects the customer back to the return_url (or app_return_url on mobile) provided in customer_interaction_config. For tokenization-only flows, the issued customer_token is delivered via the webhook (Step 3). For combined flows, Klarna also issues a klarna_network_session_token used to finalize the Payment Transaction in Step 4.
The return_url and app_return_url set inside customer_interaction_config tell Klarna where to send the customer after they complete or stop the Klarna Purchase Journey.
When 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.
On mobile, the customer may be redirected to a third-party app (such as a bank app) or the Klarna app during the Klarna Purchase Journey. The app_return_url brings the customer back to the Partner's mobile app when this happens.
Register a URL scheme (for example, yourapp://klarna) or a universal link that resumes the tokenization flow. Klarna invokes this URL after the customer completes a native app-based step, such as biometric authentication or Klarna app login. Resume the mobile app in its last state without applying state changes or deep link navigations.
The return_url and app_return_url are not mutually exclusive. Depending on the device and environment, either or both may be triggered:
Scenario
Description
Pure web flow
The customer starts the Klarna Purchase Journey in a desktop browser. After completing the flow, Klarna redirects them to return_url.
App-to-app flow
The Partner's native app opens the Klarna Purchase Journey using a universal link. When the Klarna app is installed, the customer goes directly into it. After completion, Klarna redirects them to app_return_url.
WebView flow with app handover
The Partner's native app starts the Klarna Purchase Journey in a System WebView. When 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.
Once the customer approves tokenization in the Klarna Purchase Journey, Klarna transitions the Payment Request to COMPLETED and notifies the Partner via webhook. The payload differs by scenario.
Klarna provides two methods to retrieve the tokenization outcome. Subscribing to the webhook event is required and may be combined with reading the Payment Request as a fallback for resilience.
Klarna sends this event when the Payment Request reaches the COMPLETED state, indicating that the customer has approved tokenization. Subscribe via the Webhooks registration guide.
The webhook payload carries the issued customer_token directly under klarna_customer. Tokenization is complete at this point. No further API call is needed. Store the token securely and confirm the outcome to the customer.
As a fallback (for example, when the webhook is delayed or the handler missed it), call readPaymentRequest. Once the Payment Request reaches the COMPLETED state, both the customer_token and (for combined flows) the klarna_network_session_token are available in state_context.
Tokenization-only flow: complete. When only a token was requested (no amount), tokenization is complete now. Skip Step 4 and go straight to Step 5: Store the customer token.
This step applies only to the Tokenization combined with authorization flow. Tokenization itself is already complete at the end of Step 3. What remains is to create the initial Payment Transaction using the Klarna Network Session Token.
Call authorizePayment with the klarna_network_session_token in the Klarna-Network-Session-Token request header. Klarna creates the Payment Transaction and confirms the issued customer_token in the same response.
The customer's selected payment method is carried by the Klarna Network Session Token, so payment_option_id is not required. Use the same currency, amount, and supplementary_purchase_data sent on the Payment Request. Significant differences may cause Klarna to require re-confirmation.
Because the customer just completed the Klarna Purchase Journey, Klarna may still ask for a step-up at authorization. Include step_up_config to make recovery possible; without it, borderline cases return DECLINED instead of STEP_UP_REQUIRED.
Include at minimum:
Parameter
Required
Description
Klarna-Network-Session-Token (header)
Yes
The Klarna Network Session Token received in Step 3.
The Partner's own reference for the Payment Transaction, used for reconciliation.
request_customer_token.scopes
Yes
Same scope requested on the Payment Request. Required so Klarna confirms the token under the same scope.
request_customer_token.customer_token_reference
Recommended
Same reference used on the Payment Request.
supplementary_purchase_data
Recommended
Same supplementary data sent on the Payment Request.
step_up_config
Recommended
Opts in to the STEP_UP_REQUIRED outcome so the customer can complete a step-up Klarna Purchase Journey when Klarna's risk signals require additional interaction. Set customer_interaction_config.method = HANDOVER and provide a return_url (and optionally app_return_url for native apps). Without it, borderline cases return DECLINED.
acquiring_config
Conditional
Routes the Payment Transaction to a specific Payment Account or Payment Acquiring Account, and optionally requests the settlement currency. Use the same routing fields set on the Payment Request.
When the klarna_network_session_token has expired (1-hour validity) or the payment context differs significantly from the original Payment Request, the call returns DECLINED. The customer_token may still be issued, so always inspect customer_token_response independently of the payment result.
Klarna returns response objects matching what was requested: a customer_token_response for the token, and a payment_transaction_response for the initial payment. The two are independent. A DECLINED payment does not automatically mean the token was not issued.
Result (payment_transaction_response.result)
Description
Next steps
APPROVED
The initial Payment Authorization succeeded and a payment_transaction was created. The customer_token is returned in customer_token_response and is ready for future use.
Store the customer_token securely (Step 5), persist the payment_transaction_id, and confirm the outcome to the customer.
STEP_UP_REQUIRED
Returned only when step_up_config was included on the request. Klarna's risk signals require additional customer interaction before approval. The response includes a new Payment Request with customer_interaction details.
Launch the Klarna Purchase Journey using the new Payment Request, wait for the next payment.request.state-change.completed webhook to deliver a new Klarna Network Session Token, then call authorizePayment again with that token to finalize. The same Customer Token context is preserved across the retry.
DECLINED
The initial Payment Authorization failed. No payment_transaction is created. The customer_token may still be returned in customer_token_response and remain valid for future use. Inspect customer_token_response.result to be sure.
Show the customer a decline / alternative payment page. When the token was issued, decide whether to retain it (typical for subscription onboarding where the next billing attempt can succeed) or discard it based on business logic.
Once a customer_token is available (whether from the Step 3 webhook for tokenization only, or the Step 4 response for the combined flow), persist it securely. The customer_token is a sensitive credential that allows authorizations on behalf of the customer until it expires or is revoked.
Practice
Description
Store securely
Persist customer_token values in encrypted storage. Restrict access to the systems that issue authorizations.
Associate with the customer
Link each token to the relevant customer record, including the issuing scope and the issuance timestamp. Use customer_token_reference to keep the Partner's reference and the Klarna-issued token in sync.
Track scope and intent
Record the token's scope (payment:customer_present or payment:customer_not_present) and the business intent (subscription, wallet, on-demand) so the right token is picked at authorization time.
Honor lifecycle events
When a customer cancels their subscription or removes their saved payment method, stop using the token and delete it or mark it as inactive.
Do not expose tokens
Never return raw customer_token values to a frontend, mobile clients, or third parties. Reference them by an internal identifier instead.
Once stored, the customer_token is what Partners reuse on subsequent authorizations. Both authorization patterns start with authorizePayment and bypass the upfront Payment Request, because the stored token already represents the customer's consent. The difference is whether step_up_config is included to opt in to step-up:
Customer-present authorizations (on-demand, one-click): use scope payment:customer_present. Call authorizePayment directly with the Klarna-Customer-Token header, currency, request_payment_transaction.amount, supplementary_purchase_data, and step_up_config with customer_interaction_config.method = HANDOVER and a return_url. When Klarna's risk signals require additional customer interaction, the response is STEP_UP_REQUIRED with a new Payment Request. Launch the Klarna Purchase Journey using it, then call authorizePayment again with the new Klarna Network Session Token. Without step_up_config, Klarna returns DECLINED on borderline cases instead of allowing recovery.
Customer-not-present authorizations (subscriptions, scheduled billing): use scope payment:customer_not_present. Call authorizePayment directly with the Klarna-Customer-Token header, currency, request_payment_transaction.amount, and supplementary_purchase_data. Do not include step_up_config. There is no customer available to complete a step-up Klarna Purchase Journey. Klarna returns APPROVED or DECLINED only.