Read this article for an introduction to Klarna Debit Risk 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 Klarna Debit Risk, a pioneering payment option starting with the payment option “Pay 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 Klarna Debit Risk, 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 by Bank.
With Klarna Debit Risk, Klarna offers a tailored solution for restricted segments with state-of-the art technology. Klarna Debit Risk covers the full order lifecycle including support for Order Management, including refunds. Payment status notifications will keep your systems up-to-date.
Pay 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 Klarna Debit Risk 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:
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:
In order to perform a test transaction without transferring funds with Pay by bank, follow the steps below:
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.
You can test the webhook notifications for the following payment status updates and transitions:
UNPAID
") to payment received (payment status "PAID
").UNPAID
") to payment not received (payment status "CLOSED
").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).
Country | Test case | Email address | Phone number |
---|---|---|---|
AT | 1: UNPAID -> PAID | customer+payment-paid@email.at | +4306762600801 |
AT | 2: UNPAID -> CLOSED | customer+payment-closed@email.at | +4306762600802 |
DE | 1: UNPAID -> PAID | customer+payment-paid@email.de | +491713920101 |
DE | 2: UNPAID -> CLOSED | customer+payment-closed@email.de | +491713920102 |
GB | 1: UNPAID -> PAID | customer+payment-paid@email.uk | +447555596501 |
GB | 2: UNPAID -> CLOSED | customer+payment-closed@email.uk | +447555596502 |
BE | 1: UNPAID -> PAID | customer+payment-paid@email.be | +32485213101 |
BE | 2: UNPAID -> CLOSED | customer+payment-closed@email.be | +32485213102 |
CH | 1: UNPAID -> PAID | customer+payment-paid@email.ch | +41758681001 |
CH | 2: UNPAID -> CLOSED | customer+payment-closed@email.ch | +41758681002 |
SE | 1: UNPAID -> PAID | customer+payment-paid@email.se | +46701741001 |
SE | 2: UNPAID -> CLOSED | customer+payment-closed@email.se | +46701741002 |
NL | 1: UNPAID -> PAID | customer+payment-paid@email.nl | +31632167901 |
NL | 2: UNPAID -> CLOSED | customer+payment-closed@email.nl | +31632167902 |
ES | 1: UNPAID -> PAID | customer+payment-paid@email.es | +34670369901 |
ES | 2: UNPAID -> CLOSED | customer+payment-closed@email.es | +34670369902 |
FI | 1: UNPAID -> PAID | customer+payment-paid@email.fi | +358401234901 |
FI | 2: UNPAID -> CLOSED | customer+payment-closed@email.fi | +358401234902 |
Before you proceed with the integration, review the following documentation:
From a high-level perspective, the integration process involves the following key steps:
By following these steps and referring to the provided documentation, you can seamlessly integrate Klarna Debit Risk 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.
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.
Environment | Region: EU |
---|---|
Playground |
|
Production |
|
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:
Present Klarna Debit Risk in the following way in your checkout.
Generally, it follows the instructions described in the UX Guidelines -> Presenting Klarna in the checkout.
There are minor adjustments to be aware of:
For Klarna Debit Risk 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.
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.
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.
auto_capture: true
when creating the order.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.
Klarna Debit Risk leverages a new notification system for payment status via webhooks. As mentioned earlier, once an order is created for a Pay by Bank payment (not yet captured), Klarna will inform you through a webhook about the payment status for that particular order.
Here is an overview of the different payment statuses and transitions specifically for Klarna Debit Risk.
Action | Status or status transition | Explanation |
---|---|---|
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/a | Klarna 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.
Once the order is created or the payment status changes, you receive a notification which contains the following data.
Parameter | Hierarchy | Data type | Explanation |
---|---|---|---|
Content-Type: application/json | request-headers | String | Ensure to parse the body of the notification as application/json. |
Payload-Signature: … | request-headers | String | The signature of the body to verify the request has been initiated by Klarna and not manipulated. |
event_id | request-body | String (UUID) | Unique ID for this event. |
event_type | request-body | String | The type of the event, for this notification the value is always "non_guaranteed_payment.updated". |
occurred_at | request-body | String (ISO 8601) | The timestamp (ISO 8601) when this event occurred at. |
payload | request-body | Object | The payload of this event. |
order_id | payload | String (UUID) | The order ID. Can be used for post-purchase activities. |
created_at | payload | String (ISO 8601) | The date/time when the order was created. |
purchase_currency | payload | String (ISO 4217) | The currency of the purchase. All amounts in the payload are in this currency. |
order_amount | payload | Integer | The order amount. |
payment_status | payload | String | The current payment status. Values are: UNPAID , PAID , CLOSED . |
merchant_id | payload | String | Represents the Klarna Merchant ID. |
merchant_reference1 | payload | String | Pass through field. |
merchant_reference2 | payload | String | Pass through field. |
expected_payments | payload | Object | This array contains the data of what Klarna expects to receive. Will be included with the UNPAID status already. |
payments | payload | Object | This 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_amount | expected_payments / payments | Integer | The amount to be expected and paid. It can differ between expected_payments and payments. |
debtor | expected_payments / payments | Object | Information about the debtor. The data can differ between expected_payments and payments . |
account_holder_name | debtor | String | The bank account holder name. |
iban | debtor | String | The IBAN of the bank account. |
account_number | debtor | String | The account number of the bank account. For countries without IBAN, e.g. UK. |
bank_code | debtor | String | The 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. |
bic | debtor | String | The BIC of the sender's bank. |
bank_name | debtor | String | The name of the sender's bank. |
payment_received_at | payments | String (ISO 8601) | The timestamp (ISO 8601) when the payment has been received. |
Example of a webhook notification:
For more information on webhooks, read the section How to use webhooks .
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).
In the webhook notification (described in the section above) there is information about the customer's bank account in addition to the payment status.
There might be use cases where receiving the bank account details asynchronously via a webhook notification is not sufficient.
Therefor there is an additional endpoint to query the customer bank account information synchronously after the order is created.
Here is an example of the endpoint response.
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.
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 Klarna Debit Risk 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:
To receive webhook notifications from Klarna, set up a publicly accessible HTTPS endpoint with a valid SSL certificate.
Klarna provides two publicly available environments. Refer here for more information.
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.
Environment | Region: EU |
---|---|
Playground |
|
Production |
|
Non-breaking changes are modifications made to a system or codebase that do not disrupt existing functionality. Some examples of these changes include:
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 Signaturev=1
– Signing key versionExample 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.
You can generate your signing key by any of the following 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.
To verify the signature and ensure the authenticity of the message:
`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:
For payment status updates, the event "non_guaranteed_payment.updated"
is always included.
Upon receiving webhooks, ensure their validity by performing the following steps:
event_type
, event_id
, and occurred_at
timestamp, along with relevant nested fields.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.
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.