Klarna Docs - Pay Now Standalone integration guide

Pay Now Standalone integration guide

Read this article for an introduction to Pay now standalone and how you can integrate it.

At Klarna, we're dedicated to providing customized solutions for every business scenario. That's why we're excited to introduce Pay Now Standalone, a pioneering payment option starting with the payment method “Pay Now by Bank” designed exclusively for partners from restricted segments such as Gaming, Gambling and Crypto (see Klarna Ethical instructions for more information on restricted segments). By offering this specialized product, we ensure that partners from restricted segments can access a reliable and efficient bank transfer solution.

Customers will be able to enjoy the familiar and seamless payment experience they're accustomed to with Klarna. Once their Klarna account and identity is verified, they have the freedom to choose their favorite way to pay. With Pay Now Standalone, instead of selecting from the various Klarna payment options available under the categories of Pay Now, Pay Later, or Pay over Time, customers skip the payment selection step and proceed directly with Pay Now by Bank.

With Pay Now Standalone, Klarna offers a tailored solution for restricted segments with state-of-the art technology. Pay Now Standalone covers the full order lifecycle including support for Order Management, including refunds. Payment status notifications will keep your systems up-to-date.

Pay Now by Bank isn't a new service. In fact, it has been available for many years across all of Klarna's payment products, such as Klarna payments and Klarna checkout. The key differentiators of Pay Now Standalone include a modified settlement process and the introduction of a new notification system through a webhook to keep you informed about the payment status.

From an integration perspective, this means you have to integrate with Klarna payments API for the payment processing and the Order management API to support post-purchase functionalities.

It's especially important to understand when and how you create and capture an order:

  • Orders: Only created orders initiate payment status notifications.
  • Captures: Only captured orders initiate payouts of settlements.

If you offer mobile apps, Klarna's Mobile SDK is the recommended and official method to integrate Klarna's products into your mobile app. 

This is particularly crucial when incorporating the payment method Bank Transfer, as it ensures a seamless experience for customers. They will be smoothly redirected back to your app after confirming the bank transfer within their banking app, which is commonly referred to as app2app redirects.

Read more about Klarna's Mobile SDK.

To facilitate testing the integration with your product, Klarna offers a dedicated playground environment. To ensure a smoooth testing process, please follow the steps below and carefully review the provided information to adequately prepare for your integration work.

Following the Testing Klarna products chapter in our documentation:

  1. Create a new test account.
  2. Get API credentials for the playground environment through the Merchant portal. In the navigation pane, go to Payment Settings > Klarna API Credentials.
  3. Share just the Username, for example, PKXXXXX, with your Klarna contact. We'll make a few configuration changes necessary for Pay Now Standalone and will inform you once done so you can continue testing.
  4. Use sample data to test your integration.
    After you went through the documentation and have integrated Pay Now Standalone, familiarize yourself with the test cases, the testing procedure, and the sample customer data.
  5. Test payment status updates through webhooks.
  6. Go live. Once you've completed the go-live checklist and Klarna signed off on your integration, you're ready to go live.

Test transaction

In order to perform a test transaction without transferring funds with Pay by bank, follow the steps below:

  1. Go through the Klarna user account by selecting a combination of a random phone number and an email matching the required patterns.
  2. Select the Demo Bank on the Bank selection screen.
  3. Select the bank login Demo Bank PSD2.
  4. Enter random data for Username and Password on the Testbank Sign in screen.
  5. Select My salary account on the account selection screen.
  6. Enter random data for the one-time password (OTP) process during the payment process simulation later on.

The steps above are country-specific and can slightly differ between markets. Make sure to always select Demo Bank and enter random data for the bank sign-in and authorization step (OTP), but never use real bank data for testing purposes.

Test webhooks

You can test the webhook notifications for the following payment status updates and transitions:

  • Test case 1: Payment received.
    Order created (payment status "UNPAID") to payment received (payment status "PAID").
    It can take up to a minute until you receive the notification.
  • Test case 2: Payment not received.
    Order created (payment status "UNPAID") to payment not received (payment status "CLOSED").
    It can take up to 10 minutes until you receive the notification.

You can test webhooks by using specific sample customer data.

Important note: Due to a limitation in the playground environment, please ensure to create an order within 5 minutes time after you've received an authorization token, otherwise no UNPAID-webhook will be sent to your payment-status endpoint. For the production environment, the token is valid for 60 minutes (see Get authorization).

CountryTest caseEmail addressPhone number
AT1: UNPAID -> PAIDcustomer+payment-paid@email.at+4306762600801
AT2: UNPAID -> CLOSEDcustomer+payment-closed@email.at+4306762600802
DE1: UNPAID -> PAIDcustomer+payment-paid@email.de+491713920101
DE2: UNPAID -> CLOSEDcustomer+payment-closed@email.de+491713920102
GB1: UNPAID -> PAIDcustomer+payment-paid@email.uk+447555596501
GB2: UNPAID -> CLOSEDcustomer+payment-closed@email.uk+447555596502

Before you proceed with the integration, review the following documentation:

From a high-level perspective, the integration process involves the following key steps:

  1. Initiate a payment.
  2. Check out.
  3. Create an order.
  4. Post-purchase activities (Order management) such as receiving payment status notifications, capturing orders or performing refunds.

By following these steps and referring to the provided documentation, you can seamlessly integrate Pay Now Standalone into your platform.

When a customer wishes to pay with Klarna, you need to start a payment session by sending a POST request to the {apiURL}/payments/v1/sessions endpoint. In this request, include the (shopping) cart details and indicate the intent of the payment.

Settings specific for Pay Now Standalone

  • For Pay Now by Bank, set intent: buy .
  • Mandatory usage of the merchant_urls.authorization to get the authorization_token through a server-side Authorization callback.

IP addresses for the authorization callback

The authorization callback will use the following source IP addresses when connecting to your configured endpoint. This is important if the target systems have firewall rules that restrict the IP addresses allowed to connect.

EnvironmentRegion: EU
Playground
  • 34.242.203.160
  • 34.242.19.4
Production
  • 52.17.117.56
  • 52.17.176.198

Read all the details on Step 1: initiate a payment and Create a new payment session (API specification).

During the checkout process, your customers will be able to view Klarna as a payment option, choose it, and proceed with the purchase. To enable these customer interactions, you need to perform two main actions:

  • Display Klarna as a payment method in the checkout.
  • Get authorization for the purchase.

Step 2.1: Display Klarna as a payment method in the checkout

Present Pay Now Standalone in the following way in your checkout.

  • Payment method descriptor: Pay with Klarna
  • Include the Klarna badge next to the descriptor.

Pay Now Standalone in the checkout.

Settings specific for Pay Now Standalone

For Pay Now Standalone integrated inline, there is no need to display the Klarna widget. However, you can use the response parameters for name and asset_urls  in payment_method_categories to dynamically display the descriptor and badge.

Step 2.2: Get authorization

In this step, you provide all the necessary customer details for Klarna to assess and decide whether to accept the purchase. This helps minimize the risk of payment defaults.

Settings specific for Pay Now Standalone

For comprehensive information, please review Step 2: Check out, and remember to handle the server-side Authorization callback mentioned earlier.

Once Klarna authorises the purchase, use the authorisation token to create an order and complete the one-time payment.

Once the order is created, you will receive the first payment status notification.

Ensure to save the order ID because it is required for all post-purchase activities like captures.

Settings specific for Pay Now Standalone

  • If your Klarna contract allows automatic capture of the order once an order is created, set auto_capture: true when creating the order.
  • There is no pending fraud status for Pay Now Standalone.

Read all details on Step 3: Create an order for one-time payments.

When your customers choose Klarna as the payment method and their orders are created, Order Management comes into play for further order processing. This solution enables various post-purchase operations like captures and refunds.

Settings specific for Pay Now Standalone

  • No specific settings in operations, except the Payment status notifications and Settlements which are described below. You can read more about Order management and the Order management API.

Step 4.1: Payment status notifications via webhooks

Pay Now Standalone leverages a new notification system for payment status via webhooks. As mentioned earlier, once an order is created for a Pay Now by Bank payment (not yet captured), Klarna will inform you through a webhook about the payment status for that particular order.

Payment status and transitions

Here is an overview of the different payment statuses and transitions specifically for Pay Now Standalone.

ActionStatus or status transitionExplanation
Order created and the payment has not been received by Klarna (yet)."UNPAID"When the order is created and the money has not yet been received, an unpaid notification is sent.
Payment has been received by Klarna."UNPAID" -> "PAID"After the money has been received by Klarna, regardless of if the order is captured already or not.
Klarna doesn't receive a payment after X days (payment default)."UNPAID" -> "CLOSED"A payment is treated as "CLOSED" after a specific period of time X (where X is dynamically determined but its maximum is 10 business/working days).After the "payment_status" of the order has been set to "CLOSED", the order will be either automatically canceled, if not yet captured, or refunded if already captured.
Klarna receives a payment for an order that has been set to "CLOSED" already.n/aKlarna automatically refunds the payment to the customer, no communication or notification towards the partner.

See the swimlane diagram for more information on the Payment status notification flows.

Payment status notifications.

Payload for Payment status notifications

Once the order is created or the payment status changes, you receive a notification which contains the following data.

ParameterHierarchyData typeExplanation
Content-Type: application/jsonrequest-headersStringEnsure to parse the body of the notification as application/json.
Payload-Signature: …request-headersStringThe signature of the body to verify the request has been initiated by Klarna and not manipulated.
event_idrequest-bodyString (UUID)Unique ID for this event.
event_typerequest-bodyStringThe type of the event, for this notification the value is always "non_guaranteed_payment.updated".
occurred_atrequest-bodyString (ISO 8601)The timestamp (ISO 8601) when this event occurred at.
payloadrequest-bodyObjectThe payload of this event.
order_idpayloadString (UUID)The order ID. Can be used for post-purchase activities.
created_atpayloadString (ISO 8601)The date/time when the order was created.
purchase_currencypayloadString (ISO 4217)The currency of the purchase. All amounts in the payload are in this currency.
order_amountpayloadIntegerThe order amount.
payment_statuspayloadStringThe current payment status. Values are: UNPAID, PAID, CLOSED.
merchant_idpayloadStringRepresents the Klarna Merchant ID.
merchant_reference1payloadStringPass through field.
merchant_reference2payloadStringPass through field.
expected_paymentspayloadObjectThis array contains the data of what Klarna expects to receive. Will be included with the UNPAID status already.
paymentspayloadObjectThis array contains data of what Klarna actually received on funds from this order. Will be included with the PAID status for the first time.
payment_amountexpected_payments / paymentsIntegerThe amount to be expected and paid. It can differ between expected_payments and payments.
debtorexpected_payments / paymentsObjectInformation about the debtor. The data can differ between expected_payments and payments.
account_holder_namedebtorStringThe bank account holder name.
ibandebtorStringThe IBAN of the bank account.
account_numberdebtorStringThe account number of the bank account. For countries without IBAN, e.g. UK.
bank_codedebtorStringThe bank code of the bank account. For countries without IBAN, e.g. UK.
Note: The values are from type String and can contain numbers and/or letters, e.g. "ABNA", the bank code for ABN Amro in the Netherlands.
bicdebtorStringThe BIC of the sender's bank.
bank_namedebtorStringThe name of the sender's bank.
payment_received_atpaymentsString (ISO 8601)The timestamp (ISO 8601) when the payment has been received.

Example of a webhook notification:

JSON
{
  "event_type": "non_guaranteed_payment.updated",
  "event_id": "ab1d1d7c-238d-4bd0-8a6f-c6e5da4283d6",
  "occurred_at": "2024-03-08T21:12:00.940Z",
  "payload": {
    "merchant_id": "KXXXXXX",
    "order_id": "23590864-4d7a-4a43-b923-d463a2c2a59e",
    "order_amount": 7000,
    "purchase_currency": "EUR",
    "created_at": "2024-03-07T16:41:46.000Z",

Example of a payment status notification for Bank Transfer.

Note for Testing: Due to a limitation in the playground environment, please ensure to create an order within 5 minutes time after you've received an authorization token, otherwise no UNPAID-webhook will be sent to your payment-status endpoint. For the production environment, the token is valid for 60 minutes (see Get authorization).

For more information on webhooks, read the section How to use webhooks .

Step 4.2: Settlement reports

Settlement reports provide a detailed breakdown of all payments made by Klarna to you, facilitating the reconciliation of your accounts. Each Settlement Report includes a unique payment reference, which corresponds to the entry on your bank account statement. Settlement Reports are available in CSV, PDF or JSON format and can be accessed in three different ways - using Klarna’s Merchant Portal, the Settlements API or by Klarna-SFTP.

Specific settings for Pay Now Standalone
  • In the event of an order being captured but experiencing a payment default, it will result in a RETURN (type) for the order, and the corresponding amount will be deducted from the next settlement or payout.
  • Each RETURN from a payment default will additionally contain the text "non_guarantee_reversal" in the settlement report field merchant_refund_reference (you may need to add this field to your settlement report configuration in your Klarna Partner Portal).

For complete information, please refer to the details on Settlement reports and Settlements API.

Note that Pay Now Standalone follows a non-guaranteed settlement flow, Klarna doesn't handle disputes. Therefore, it is your responsibility to manage any dunning, including disputes.

Soon, configuring webhooks will be possible through the Webhook Notifications page in Merchant Portal Settings. In the meantime, and if you're a Distribution Partner wanting to use webhooks, please contact your Solutions & Delivery lead who will assist you with the integration process.

To integrate webhooks, follow these steps: 

  1. Create an HTTPS URL (endpoint) for receiving webhooks on your server
  2. Generate a signing key
  3. Choose the events you want to listen to
  4. Verify and respond to received webhooks with a 2xx HTTP status if they are valid.

To receive webhook notifications from Klarna, set up a publicly accessible HTTPS endpoint with a valid SSL certificate.

  • You can create a single endpoint to receive multiple event types or set up individual endpoints for each event type.
  • If you're subscribing to events based in the EU, the server receiving the events must be physically located in the EU.

Environments

Klarna provides two publicly available environments. Refer here for more information.

  • Playground.
  • Production.

IP addresses for the webhook

Depending on your network and security requirements, you might need to add our network to your firewall's allowlist to receive webhook events from us. To help your integration operate securely, it must also verify that it’s communicating with Klarna through one of our listed IP addresses.

EnvironmentRegion: EU
Playground
  • 63.33.163.93
  • 63.34.140.6
  • 63.34.72.238
Production
  • 52.18.109.75
  • 63.32.138.153
  • 63.32.201.200

Non-breaking changes

Non-breaking changes are modifications made to a system or codebase that do not disrupt existing functionality. Some examples of these changes include:

  1. Addition of HTTP headers 
  2. Addition of optional or read-only fields/properties
  3. Re-ordering of fields in the JSON
  4. Addition of new values to an enum if there is a default defined

To verify the authenticity of notifications sent by Klarna and prevent tampering by third parties, Klarna signs the HTTP messages using a signing key generated by you. The signature is set as the `Payload-Signature` header, which is computed as the HMAC-SHA512 over the message body and the signing key.

The `Payload-Signature` header conforms to RFC 8941 – Structured Field Values for HTTP and contains 3 fields:

  • ts=1663750989096 – Timestamp (milliseconds)
  • sig=c4031d6fdc01e66542079… – HMAC Signature
  • v=1 – Signing key version

Example of a Payload-Signature: ts=1663750989096,sig=c4031d6fdc01e66542079b0608a3886788e1cb4e7c7201de4f1fbeedf4193491e2fffe2178a04387534bd168d902751e0546bf2ffb11628e9e5f1aa5cdfc8c3a,v=1

Note that the Klarna-Signature header present in the HTTP message contains only the signature value. This header is deprecated and shouldn’t be used.

How to generate and set your signing key 

You can generate your signing key by any of the following commands:

Generate your signing key by any of the these commands.

You can set and update your signing key through the Merchant Portal. Simply access the appropriate settings to manage this key.

If you're a Distribution Partner, please get in touch with your Solutions & Delivery lead, who will generate a signing key for you.

Verifying signatures

To verify the signature and ensure the authenticity of the message:

  1. Compute the signature by applying the HMAC-SHA512 algorithm over the HTTP message body and using your generated signing key.
  2. Parse the `Payload-Signature` header and compare the `sig` field to the computed signature's hexadecimal digest.

If the values match, you can be confident that the request originated from Klarna, and you can proceed to accept the message for further processing. However, if the values do not match, reject the message and respond with an HTTP 400 Bad Request status.

You can follow the following steps to properly validate a received notification:

Validate your notification.

For payment status updates, the event "non_guaranteed_payment.updated" is always included.

Upon receiving webhooks, ensure their validity by performing the following steps:

  1. Check the Object: Klarna sends event data within the POST request body. Each event contains an event_type, event_id, and occurred_at timestamp, along with relevant nested fields.
  2. Send a 2xx Response: After confirming the webhook's authenticity, respond with an HTTP status code in the 2xx range if both the message and signatures are valid. If any issue arises, respond with a 403 status code. If you do not receive a message, you can provide additional data for debugging purposes using an error object/description in the response.

Retry strategy 

To acknowledge receipt of a notification, your endpoint must respond with either an HTTP 200, 201, 202, or 204 status code. Any other status code indicates that the notification couldn't be processed. In such cases, Klarna will attempt to resend the notification at increasing intervals. If the initial payment status webhook fails with a non-200 error or timeout, it will be retried 15 times with an exponential backoff strategy for approx 2 days, starting with a few seconds between the retries, going to minutes, hours, and ending with half a day and one day between the last two re-tries. It is crucial to respond immediately upon receiving the notification, before proceeding with any resource-intensive server-side tasks.

The current retry strategy is not exclusive to the payment status notification and applies to all Klarna services, such as disputes and order management, that utilize our webhook platform.

Idempotent delivery

Occasionally, the same event may be delivered multiple times. Your endpoint should be idempotent, meaning it handles duplicates without affecting data integrity.

Each notification contains an event_id field, which is a unique identifier (UUIDv4). You can use this ID to identify and dismiss duplicate messages if you have already received and processed them.

If you have any further questions, please don't hesitate to contact your designated Klarna representative.