> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paynext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Klarna

> Accept Klarna payments through PayNext.

Klarna is a buy-now-pay-later wallet. Customers are redirected to Klarna, choose a payment option there (pay in full, pay later, installments, or financing), and return to your checkout. Klarna pays you the full amount up front and collects from the customer itself.

In PayNext, Klarna is available through Stripe. It supports one-time payments and subscriptions, with separate authorize and capture (like Amazon Pay).

## Payment Method Details

| | |
| :- | :- |
| **Customer locations** | Depends on the Stripe account country ([Klarna availability](https://docs.stripe.com/payments/klarna)) |
| **Supported currencies** | Depends on the Stripe account country ([Klarna availability](https://docs.stripe.com/payments/klarna)) |
| **Recurrent payments** | ✓ (country limits apply — see [Country limits](#country-limits)) |
| **Manual capture support** | ✓ |
| **Refunds** | ✓ |
| **Supported processors** | Stripe |

## Prerequisites

1. Connect and activate the [Stripe integration](https://docs.paynext.com/integrations/processors/stripe.md) in PayNext and add the **Publishable Key** to it (see [Notes](#notes))
2. Enable Klarna in your Stripe Dashboard under **Settings → Payment methods** (the Stripe capability `klarna_payments` must be active on the account that serves the customer)
3. Turn on Klarna in your PayNext checkout configuration and list the customer currencies it applies to

> [!WARNING]
>
> Klarna is shown at checkout when the customer's country is allowed by the [country limits](#country-limits) and the plan's currency matches the customer currencies of your Klarna checkout configuration. PayNext does not ask your Stripe account. If you list a currency that Stripe does not support for Klarna, starting the payment returns an error.

## Country limits

PayNext applies extra country rules on top of Stripe account availability, keyed on the customer's country:

| Customer country | Allowed Klarna usage |
| :- | :- |
| Australia | One-off only |
| Poland | One-off only (no Klarna subscriptions) |
| Norway | One-off, or a subscription billed every 3 months or less often (every 61 days or less often when billed in days, or yearly). Weekly, monthly, and every-2-months plans are excluded. |
| Other countries | One-off and subscriptions, subject to Stripe/Klarna availability |

The same country rules decide whether Klarna is offered at checkout and whether a subscription can be reactivated. Reactivation does not require the Klarna checkout configuration to list currencies. A condition on customer currencies still has to match the plan's currency, according to its match type. Reactivation is allowed when any condition in your Klarna configuration matches. Reactivation checks the country only when it takes a payment. Klarna is not returned in checkout configuration for a plan that breaks the country rules.

## How it works

### One-time payments

The customer selects Klarna, is redirected to Klarna to pick a payment option and approve, then returns to your site. A one-off does not save a reusable instrument for subscriptions (`setup_future_usage` is not sent).

### Subscriptions (initial payment)

For a subscription, the first payment is customer-present: Klarna redirects the customer, the authorization can reach `AUTHORIZED`, and a separate capture moves the payment to `SETTLED`. That first approval also sets up the saved Klarna instrument for later renewals.

### Recurring charges

After the instrument is saved, renewals are charged off-session against the stored Klarna payment method. If Stripe accepts the charge, the payment can be `AUTHORIZED` (a separate capture then settles it, see [Authorize and capture](#authorize-and-capture)), `SETTLING` (Stripe completes it with a later event), or `SETTLED`. PayNext prefers the Stripe account that created the instrument and, if it can't find that account, uses the processor from your workflow.

### Paid trials

Klarna can't pay a free trial: starting a Klarna payment for a plan whose price today is zero returns HTTP 400 with the message `Klarna requires a positive plan price`.

On a paid-trial subscription's first customer-present payment, PayNext charges the trial price (what the customer pays today). Klarna's confirmation page shows the renewal price and the next billing date for later charges. That first-payment discount presentation applies only while the customer is present. Off-session renewals charge without that trial discount. On an existing subscription—for example a prorated charge or a plan change through checkout—Klarna does not present the charge as a trial-style discount; a checkout plan change uses the target plan's renewal price for what Klarna shows as the upcoming amount.

### Payments completed without the customer returning

A Klarna payment can finish even if the customer never returns to your site after approving on Klarna. When Stripe reports the approval, PayNext creates the customer, the payment, and, for a subscription plan, the subscription.

* PayNext creates a new customer for the attempt unless it finds one to reuse: the customer of an existing subscription, or a customer already saved in the checkout session. It never matches a customer by email.
* The customer's name stays empty. The country comes from the checkout session, or from the payment's Stripe metadata when the session has none. If neither has a valid country, the customer's country stays empty.
* The payment is `PENDING`, then moves to `AUTHORIZED` and `SETTLED` as Stripe reports each step.
* If you have a published workflow for Klarna, Workflow Runs lists one run for the payment (see [Workflows](#workflows)).

A checkout session stays valid for 24 hours. After that, a create request for the same Klarna payment returns HTTP 400 with code `klarna_session_expired`. PayNext can still process a late Stripe notification from the details stored with the payment at Stripe. If those details are incomplete, PayNext acknowledges the notification and creates nothing.

If the customer starts Klarna again in a checkout session whose payment is already `AUTHORIZED`, `SETTLING`, `SETTLED`, or `REFUNDED`, the request returns HTTP 409 (`payment already completed for this client session`) and PayNext creates nothing new at Stripe.

## Authorize and capture

Klarna supports manual capture. With a published workflow, a completed customer approval leaves the payment in `AUTHORIZED` until the workflow captures it (after a Delay step, if you add one). Without a published workflow, PayNext captures a customer-present payment right away when Stripe reports it. Capture settles the payment to `SETTLED` for the full authorized amount—partial capture is not supported. When Stripe reports the charge as still processing, the payment is `SETTLING` first and becomes `SETTLED` with a later Stripe event.

You can void an `AUTHORIZED` payment before capture: a refund request on an uncaptured authorization cancels the hold. The payment becomes `CANCELLED` and no money is returned (refunded amount stays `0`). The payment's timeline shows one `Cancelled` entry, whether you voided the payment or Stripe cancelled it. If the payment started a subscription, PayNext cancels the subscription when Stripe delivers the cancellation event for the voided authorization, not at the moment of your request (see [Webhooks](#webhooks)).

If an authorization is not captured within **28 days**, Klarna cancels it through Stripe. PayNext runs no timer of its own: when Stripe notifies it, PayNext reports the payment as `CANCELLED` and cancels the subscription the payment started (see [Webhooks](#webhooks)).

## Workflows

When Stripe reports that the customer approved a Klarna payment, PayNext follows your published payment-created workflow for Klarna. Without one, PayNext captures a customer-present payment reported this way immediately.

| Step | What happens |
| :- | :- |
| Authorize | Passes to the next step. It does not authorize again. |
| Delay | The payment stays `AUTHORIZED` and PayNext captures it after the delay (days, hours, or minutes). |
| Capture | Captures the full authorized amount. |
| Condition | Follows the first matching branch. The payment is not captured and stays `AUTHORIZED` if no branch matches or if the workflow has a condition and the customer can't be found. Some conditions read metadata that Stripe's notification may not carry, or the current plan, status, or failed attempts of a subscription the payment doesn't have yet. PayNext can't evaluate them, so it follows every branch. If all branches capture at the same time and one of them has no conditions, the payment is captured. If none captures, the payment follows the first branch: a Decline there blocks it, a Stop leaves it `AUTHORIZED`. Otherwise it is not captured and stays `AUTHORIZED`. If every branch has conditions, that counts as one more branch that doesn't capture. |
| Decline | Which path reaches Decline first decides the result. If Stripe's approval notification reaches PayNext first, Decline cancels the authorization at Stripe and sets the payment to `BLOCKED`. If the authorization can't be cancelled, the payment stays `AUTHORIZED`. If the customer's return reaches the Decline step first, Decline only sets the payment to `BLOCKED`: the authorization is not cancelled at Stripe, the subscription is not cancelled, and the hold stays until Stripe cancels it. For a renewal, Decline sets the payment to `BLOCKED` and counts as a failed attempt in dunning: an active or trial subscription becomes `past_due`, and it is cancelled if this was the last attempt. The hold stays until Stripe cancels it. |
| Stop | The payment is not captured and stays `AUTHORIZED`. |
| Split | For a payment that Stripe reports: continues when all branches lead to the same step. Otherwise the payment is not captured and stays `AUTHORIZED`. For a customer who returns to your site, Split picks one branch by weight. |

A payment that stays `AUTHORIZED` keeps its hold until Stripe cancels it. You can't save a workflow that Klarna triggers with an Authorize and capture step.

For a payment PayNext created from the Stripe notification, Workflow Runs shows one run for the payment. A delayed capture shows as `waiting`. PayNext does not calculate tax for a payment that Stripe has already settled.

## If the customer doesn't complete payment

If the customer abandons the Klarna redirect (closes the tab or never returns), the payment becomes `INCOMPLETE` when Stripe reports that the attempt expired. This applies to customer-present payments. No charge is taken, and an abandoned Klarna redirect does not open dunning.

If the customer tries Klarna again in the same checkout session after an attempt ended `INCOMPLETE`, `DECLINED`, or `FAILED`, PayNext creates a new payment with a new payment ID and a new PaymentIntent at Stripe, and cancels the previous PaymentIntent if Stripe still shows it as unpaid. If Stripe already shows the previous attempt as paid or authorized, PayNext returns that payment instead of creating a new one. The first payment keeps its own status.

## Plan changes

Merchant-API plan changes (for example `PATCH /subscriptions` with a plan id, without a customer-present checkout) and the **Change subscription** workflow step are refused for subscriptions billed with Klarna, including a change to the plan the subscription is already on. The API returns HTTP 400 with code `klarna_plan_change_requires_checkout`, and the workflow step fails with an error that starts with `klarna_plan_change_requires_checkout`. Neither changes the plan. Metadata sent in the same `PATCH` request is saved even when the plan change is refused, and a request that sends only metadata isn't affected. The check is skipped for a subscription that has no payment in status `AUTHORIZED`, `SETTLING`, `SETTLED`, or `REFUNDED`. Otherwise it looks at the payment method of the latest such payment, including a deleted Klarna method. A subscription that started on Klarna but whose latest such payment used another method is not blocked.

To change the plan on a Klarna subscription, run a customer-present plan change through checkout so the customer re-authorizes on Klarna. See [Change Subscription Plan](https://docs.paynext.com/guides/use-cases/change-subscription-plan.md).

## Change the payment method

The customer changes the payment method through a customer-present checkout that charges the existing subscription. There is no separate flow that only switches the method, and Klarna doesn't accept a zero-amount checkout. To switch from a card to Klarna, the customer must also pass the country limits and your Klarna checkout configuration.

Renewals are charged on the customer's payment method that most recently completed a successful payment, across all of the customer's payments, not only this subscription's.

## Reactivation

PayNext charges for a reactivation only when the subscription is cancelled and its paid period has ended. If the paid period is still running, or the subscription is only scheduled for cancellation, reactivation creates no payment and does not check the payment method.

When a reactivation takes a payment, PayNext charges the customer's most recently used payment method (or, if none has paid, the most recently added one). If that method is Klarna and is deleted, closed, invalid, inactive, or suspended, the API returns an error with code `payment_method_inactive_or_deleted` before it creates a payment. Other method types are not checked.

When that method is Klarna, the reactivation is also refused with code `klarna_reactivation_ineligible` when Klarna isn't eligible for the customer's country and the plan, or when no condition in your Klarna checkout configuration matches. Eligibility follows the [country limits](#country-limits) and your configuration, without the requirement to list currencies.

## If the customer revokes the mandate

A customer can remove or deactivate the saved Klarna payment method in the Klarna app. PayNext receives that from Stripe (`mandate.updated`) and sets the payment method `status` to `deleted`. A mandate of type `single_use` is ignored.

A revoked payment method can't be charged: an attempt on it is aborted and recorded as `INCOMPLETE` with `decline_code` `payment_method_disabled`. If the customer has no other usable payment method, PayNext pauses dunning for all of the customer's `past_due` subscriptions, and each stays `past_due` for 14 days before it is cancelled with reason `dead_instrument`. If the customer has another usable method, dunning continues and PayNext doesn't cancel for this reason. The 14 days start at the revocation for a subscription that is already `past_due`, and at the first failed renewal otherwise. A subscription that isn't `past_due` is unchanged until its next renewal fails. See [Dead payment methods](https://docs.paynext.com/guides/use-cases/recover-subscriptions.md#dead-payment-methods).

Each change is reported by [`customer.payment_method.updated`](https://docs.paynext.com/webhooks/introduction/event-types#payment-method-events).

## Webhooks

For Klarna payment and subscription advances, merchants receive:

* **v1:** `payment.created`, `payment.updated` (on each status change), and `subscription.created` when the subscription becomes active
* **v2** (sent only when v2 webhooks are enabled): `payment_v2.created`, `payment_v2.authorized`, `payment_v2.settling`, `payment_v2.settled`, `payment_v2.cancelled`, and `subscription_v2.created`

Each of those events fires once for the matching transition. See [Event Types](https://docs.paynext.com/webhooks/introduction/event-types.md).

For a payment PayNext creates from the Stripe notification, you receive `payment.created` once, then one `payment.updated` for each status the payment reaches: `AUTHORIZED`, `SETTLING` (when Stripe reports the charge as still processing), and `SETTLED`. A subscription becomes active when the payment is authorized or when it settles, so `subscription.created` is not tied to one payment status.

When a workflow decline blocks a payment because Stripe's approval notification reached PayNext first, no `payment.updated` for `BLOCKED` is sent, so the last update you receive for the payment shows `AUTHORIZED`. When the customer's return reaches the Decline step first, or for a renewal, PayNext sends `payment.updated` with status `BLOCKED` (`payment_v2.blocked` for v2). A payment that ends `CANCELLED` sends `payment.updated`.

### Subscription cancelled with a voided payment

When an `AUTHORIZED` payment is cancelled, PayNext also cancels the subscription that payment started. This happens when you void the payment, and when Stripe cancels the hold (including when it expires). PayNext cancels the subscription with reason `workflow_action`. PayNext cancels the subscription only when all of these hold:

* The payment is customer-present (not a renewal) and was authorized but not captured.
* The subscription is active or in a trial.
* The subscription has no other payment in status `AUTHORIZED`, `SETTLING`, `SETTLED`, or `REFUNDED`.

Otherwise the subscription stays as it is.

## Refunds

What a refund request does depends on the payment status:

* `AUTHORIZED`: PayNext voids the hold. No money is returned. See [Authorize and capture](#authorize-and-capture).
* `SETTLED` or `SETTLING`: PayNext refunds the full amount through Stripe.
* `DECLINED`, `FAILED`, or a `BLOCKED` payment that never held funds: the API refuses the request with HTTP 400.

Partial refunds are not supported: a request with an `amount` returns HTTP 400 (even if it equals the full payment amount), or HTTP 409 if the payment is already fully refunded. A request for a `CANCELLED` payment, or for an `AUTHORIZED` payment whose void is already in progress, returns HTTP 200 and changes nothing, whatever it contains. Repeating a full refund request (without `amount`) also returns HTTP 200 and changes nothing when the payment already has a refund in status `PENDING`, `DECLINED`, `SETTLING`, or `SETTLED`. A refund that `FAILED` is sent to Stripe again. HTTP 409 is also returned when the payment is already fully refunded and has no refund record, or when another operation on the payment is in progress. Stripe's response can settle the refund immediately (`SETTLED`), decline it (`DECLINED`), or leave it `SETTLING`; a `SETTLING` refund completes when Stripe reports the result. See [Stripe Klarna docs](https://docs.stripe.com/payments/klarna) for Klarna's refund window at the processor.

## Testing

**1. Configure sandbox credentials**

Use Stripe Test mode credentials in your PayNext integration and make sure Klarna is enabled for that account (`klarna_payments` active).

**2. Configure return URL**

Ensure your return URL is configured when rendering the PayNext SDK. Klarna redirects the customer off-site and back to your site.

**3. Make a test payment**

Start a Klarna payment via PayNext checkout using a currency and customer country supported by your Stripe account. For subscriptions, use a plan that passes the [country limits](#country-limits).

**4. Complete approval on Klarna**

Approve the payment on the Klarna page and return to your site. Confirm the payment reaches `AUTHORIZED` or `SETTLED` as configured.

**5. Verify capture and incomplete paths**

For manual capture, add a Delay step before Capture in your Klarna workflow and confirm the payment stays `AUTHORIZED` during the delay and reaches `SETTLED` after it. Start another payment and abandon the redirect; confirm the payment becomes `INCOMPLETE` and no dunning opens.

## Notes

* PayNext keeps its own internal Klarna fields out of the payment metadata in API responses and webhooks. For a payment made with a saved Klarna method on a one-off plan with the customer present, PayNext stores your return URL in `klarna_return_url`, and it stays visible in payment metadata. PayNext overwrites a metadata key with that name.
* Klarna options shown on Klarna's page (pay later, installments, financing) depend on country, amount, and whether the charge is one-off or recurring — PayNext does not pre-select or restrict which option Klarna shows.
* The Klarna page language follows the locale known to checkout (mapped to Klarna's preferred locale). When none is known, PayNext uses the language from the `Accept-Language` header of the request that starts the payment, and `en-US` if nothing maps.
* Add the Publishable Key to the Stripe integration. The checkout receives it for Klarna when it is set.
* Do not use merchant-API plan change for Klarna subscriptions; use customer-present checkout instead.

> [!NOTE]
>
> Stripe and Klarna also limit which payment options appear. For subscriptions, Pay later is available only for customers in Germany, Sweden, and the United States. You cannot force or hide a specific Klarna option from PayNext. Poland does not support Klarna subscriptions, and Norway has further subscription-interval limits on Klarna's side. See [Stripe Klarna limitations](https://docs.stripe.com/payments/klarna#limitations-to-availability). PayNext's own [country limits](#country-limits) above still apply on top of that.

> [!NOTE]
>
> If the customer pays with Apple Pay on Klarna's page, Klarna handles that wallet. For PayNext and Stripe the charge is a normal Klarna payment (category `pay_now`): authorization, capture, and off-session renewals work the same way, and you do not need extra live setup in Stripe for Apple Pay on Klarna. Klarna may not offer Apple Pay in sandbox. You cannot hide Apple Pay for the account from the Stripe Dashboard alone.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.