Token charge Customer Present - Monitor the state

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 payment_token by using one or a combination of the following methods:
    • Subscribing to payment.request.state-change.* webhook events (required)
    • Reading the payment request
    • Optionally leverage available dynamic placeholders when making use of an internal return_url
  • Proactively cancel payment requests which have not resulted in successful transactions.

Monitoring the state for token charges is same as that for one-time payments.

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.The Acquiring Partner returns the Klarna Payment request data points as defined in the Handle Step-up scenario section.

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 payment_token and create a payment transaction.

EXPIRED

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

CANCELED

Payment request canceled by Acquiring Partner before authorization.Final state. No action.

DECLINED

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

State transition diagram

flowchart LR classDef default fill:#F9F8F5,color:#0B051D classDef start fill:#0B051D,stroke:#0B051D,color:#FFFFFF classDef temp fill:#FFA8CD,stroke:#0B051D classDef final fill:#BF7E9A,stroke:#0B051D classDef cond fill:#E4E3DF,stroke:#0B051D Start((Start)):::start --> Submitted1["SUBMITTED"]:::temp subgraph Submission_Handling [Submission handling] direction TB Submitted1 --> Decision1{ }:::cond Decision1 -->|Customer enters<br/>Purchase Journey| IN_PROGRESS:::temp Decision1 -->|Acquiring Partner<br/>cancels request| Cancel1[CANCELED]:::final Decision1 -->|Acquiring Partner<br/>updates request| Submitted2[SUBMITTED]:::temp Decision1 -->|"Request expired<br/>(≥ 3h)"| EXPIRED1[EXPIRED]:::final end subgraph Purchase_Journey_Outcome [Purchase journey outcome] direction TB IN_PROGRESS --> Decision2{ }:::cond Decision2 -->|Klarna accepts<br/>purchase| COMPLETED:::final Decision2 -->|Customer aborts| Submitted3[SUBMITTED]:::temp Decision2 -->|Acquiring Partner<br/>cancels request| Cancel2[CANCELED]:::final Decision2 -->|"Request expired<br/>(≥ 3h)"| EXPIRED2[EXPIRED]:::final Decision2 -->|"Customer rejected - no payment methods available<br/>"| DECLINED[DECLINED]:::final 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.

Klarna supports multiple integration methods. Acquiring Partners must implement Klarna webhook events at a minimum and may optionally combine them with other methods to enhance resilience. This approach ensures robustness, especially in cases where:

  • The customer closes the browser before returning
  • Network issues interrupt the redirect
  • Post-processing is required before informing the customer

For one-time payments, Klarna issues a payment_token that can be used to authorize the payment. The payment_token is valid for only 1 hour, so be sure to use it promptly to create the transaction.

Subscribe to webhook events (required)

Acquiring Partners can subscribe to the payment.request.state-change webhooks events using the guidelines here. Klarna will send webhook notifications whenever the payment request state is updated.

The webhook event payment.request.state-change.completed is triggered when the Payment Request reaches the state COMPLETED.

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-[...]",

Consult the API referenceAPI for a complete description of the webhook payload.

Read the payment request

The Klarna token(s) can also be retrieved through the Read Payment Request APIAPI. It will be stored in the state_context object of the payment request once in state = COMPLETED.

Sample response - State COMPLETED

JSON
{
  "payment_request_id": "krn:payment:eu1:request:10be1d49-7beb-6b24-b9dd-8c14d0528503",
  "state": "COMPLETED",
  "previous_state": "IN_PROGRESS",
  "state_context": {
    "payment_token": "krn:payment:eu1:payment-token:31b543e0-6430-64df-970c-f1ae3cd9d8b0"
  },
  "expires_at": "2025-02-26T17:25:34.534721775Z",
  "created_at": "2025-02-24T17:25:34.534721775Z",
  "updated_at": "2025-02-24T17:25:34.534721775Z",

Placeholders in the return_url

As mentioned in the "Handle step-up scenario" section, return_url is not guaranteed to be called in all cases, and frontend redirection can be affected by network issues. Therefore, use return_url strictly to enhance the customer experience (by redirecting them to the appropriate page after completion or cancellation) or as a redundancy to retrieve the payment_token in addition to using a webhook integration.

The return_url directs the customer back to the Partners website to the predefined url after a successful or abandoned authorization. By incorporating placeholders into the URL, Klarna can dynamically insert relevant transaction information, ensuring the URL contains all necessary details for processing.

This is particularly relevant whenever acquiring Partners make use of an internal return_url rather than the Partner's frontend URL when calling the Payment Authorize API.

Details about the available return_url placeholders are provided below:

PlaceholderDescription

{klarna.payment_request.payment_token}

The payment token, available when a payment request is successfully completed, and used to create a transaction.

{klarna.payment_request.id}

Klarna Payment Request identifier. Used in management of a Payment Request.

{klarna.payment_request.state}

State of the payment request - may be used as a hint.

{klarna.payment_request.payment_request_reference}

The provided reference to the payment request.

Sample request URL

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-Interoperability-Token: eyJhbGciOiJIU...' \
  -d '{
        "currency": "USD",
        "supplementary_purchase_data": { .. },
        "interoperability_data":  "<serialized-json>",
        "request_payment_transaction": {
          "amount": 11800,

Once the customer completes a payment and is redirected, the return_url will contain the payment request data points replacing the placeholders:

  • Klarna recommends that all Partners verify data received via redirect against webhook data to prevent payment_token misuse.
  • Payment tokens passed through the return_url are only valid for the account that completes the payment, ensuring protection against hijacking.

Example

HTTP
https://acquiringpartner.example/klarna-redirect?payment_token=krn:payment:eu1:payment-token:31b543e0-6430-64df-970c-f1ae3cd9d8b0&request_id=krn:payment:eu1:request:10be1d49-7beb-6b24-b9dd-8c14d0528503&state=COMPLETED&reference=acquiring-partner-reference-12345