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

# Klarna

> Set up Klarna and charge recurring subscriptions using merchant-initiated transactions (MIT) with a saved payment method.

Klarna is a buy now, pay later (BNPL) payment method that offers flexible payment options and supports recurring payments through merchant-initiated transactions (MIT).

## Setup

A Klarna account can be requested from the
[Klarna Business Portal](https://portal.klarna.com/products/signup/basic-info).

## Credentials

To connect a Klarna account, obtain the following credentials from the Klarna Business Portal.

* **Username:** An API username which can be generated by navigating to **Preferences** → **Settings** → **Manage Klarna API Credentials**
* **Password:** An API password which can be generated by navigating to **Preferences** → **Settings** → **Manage Klarna API Credentials**
* **Region:** The region of the Klarna account. Enter `EU` for Europe, `NA` for North America, or `OC` for Oceania

## Features

Klarna supports the following features:

* **Delayed capture** - Authorize a payment and capture it at a later time
* **Partial capture** - Capture a portion of the authorized amount
* **Partial refunds** - Refund a portion of the captured amount
* **Refunds** - Refund transactions in full
* **Void** - Cancel an authorized transaction before capture
* **Payment method tokenization** - Store Klarna payment methods for future recurring use

## Supported countries

Klarna supports transactions from buyers in the following countries:

| Country code | Country code | Country code | Country code | Country code | Country code | Country code | Country code |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| `AT`         | `AU`         | `BE`         | `CA`         | `CH`         | `DE`         | `DK`         | `ES`         |
| `FI`         | `FR`         | `GB`         | `IE`         | `IT`         | `NL`         | `NO`         | `PL`         |
| `PT`         | `SE`         | `US`         |              |              |              |              |              |

## Supported currencies

Klarna supports processing payments in the following currencies:

| Currency code | Currency code | Currency code | Currency code | Currency code | Currency code | Currency code | Currency code |
| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
| `AUD`         | `CAD`         | `CHF`         | `DKK`         | `EUR`         | `GBP`         | `NOK`         | `PLN`         |
| `SEK`         | `USD`         |               |               |               |               |               |               |

## Limitations

The following features are not supported by this connector:

* **Direct capture** - Immediate settlement is not supported; authorization must be captured separately
* **Multi-capture** - Multiple captures against a single authorization are not supported
* **Over capture** - Capturing more than the authorized amount is not supported
* **Incremental authorization** - Increasing the authorized amount is not supported
* **Partial authorization** - Accepting a partial amount when the full amount cannot be authorized is not supported
* **Zero auth** - Zero-dollar verification transactions are not supported
* **Network tokens** - Network tokenization is not supported
* **3-D Secure** - 3DS authentication is not applicable
* **Transaction sync** - Automatic transaction status synchronization is not supported
* **Settlement reporting** - Automatic settlement reporting is not supported

## Integration

For Klarna, the default integration uses a redirect to the Klarna hosted payments page. A direct integration using the Klarna JavaScript SDK or mobile SDKs is also supported.

### Redirect integration

Start by creating a new transaction with the following required fields.

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
    transactionCreate: new TransactionCreate()
    {
      Amount = 1299,
      Currency = "USD",
      Country = "US",
      PaymentMethod = new PaymentMethodRequest()
      {
        Method = "klarna",
        RedirectUrl = "https://example.com/callback",
        Country = "US",
        Currency = "USD",
      },
    }
  );
  ```

  ```go Go theme={"system"}
  amount := int64(1299)
  currency := "USD"
  country := "US"

  transactionCreate := components.TransactionCreate{
    Amount:   &amount,
    Currency: currency,
    Country:  &country,
    PaymentMethod: &components.PaymentMethodRequest{
      Method:      "klarna",
      RedirectUrl: "https://example.com/callback",
      Country:     "US",
      Currency:    "USD",
    },
  }

  transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil)
  ```

  ```java Java theme={"system"}
  CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
    .transactionCreate(TransactionCreate.builder()
      .amount(1299L)
      .currency("USD")
      .country("US")
      .paymentMethod(new PaymentMethodRequest.Builder()
        .method("klarna")
        .redirectUrl("https://example.com/callback")
        .country("US")
        .currency("USD")
        .build())
      .build())
    .call();

  Transaction transaction = transactionResponse.transaction().orElse(null);
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(
    amount: 1299,
    currency: 'USD',
    country: 'US',
    paymentMethod: new PaymentMethodRequest(
      method: 'klarna',
      redirectUrl: 'https://example.com/callback',
      country: 'US',
      currency: 'USD',
    )
  );
  $response = $client->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction: models.Transaction = client.transactions.create(
    amount=1299,
    currency="USD",
    country="US",
    payment_method={
      "method": "klarna",
      "redirect_url": "https://example.com/callback",
      "country": "US",
      "currency": "USD",
    }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
    amount: 1299,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "klarna",
      redirectUrl: "https://example.com/callback",
      country: "US",
      currency: "USD",
    },
  });
  ```
</CodeGroup>

After the transaction is created, the API response includes `payment_method.approval_url` and the `buyer_approval_pending` status.

```json theme={"system"}
{
  "type": "transaction",
  "id": "ea1efdd0-20f9-44d9-9b0b-0a3d71e9b625",
  "payment_method": {
    "type": "payment-method",
    "approval_url": "https://cdn.sandbox.spider.gr4vy.app/connectors/klarna/apm.html?token=..."
  },
  "method": "klarna"
}
```

Redirect the buyer to the `approval_url` to complete the Klarna approval flow. Once approved, the transaction moves to `authorization_succeeded`.

### Direct integration

Gr4vy supports direct integration with Klarna using the [Klarna Payments SDK](https://docs.klarna.com/klarna-payments/sdk-reference/) or mobile SDKs, allowing you to embed the payment UI directly in your app while using Gr4vy to manage the transaction lifecycle.

To initiate a direct integration, create a transaction with `integration_client` set to `web`, `ios`, or `android`. For mobile, use your app deep link for `redirect_url` (for example, `yourapp://`).

After the transaction is created, the API response includes a `session_token` which can be used to get the [session data](/reference/transactions/get-transaction-session) for that transaction.

```sh theme={"system"}
POST /transactions/:transaction_id/session?token=:session_token
```

<CodeGroup>
  ```json Web theme={"system"}
  {
    "session_data": {
      "client_token": "...",
      "purchase_country": "US",
      "purchase_currency": "USD",
      "amount": 1000
    },
    "default_completion_url": "https://api.sandbox.spider.gr4vy.app/transactions/approve/some-token",
    "integration_client": "web"
  }
  ```

  ```json iOS theme={"system"}
  {
    "session_data": {
      "client_token": "...",
      "purchase_country": "US",
      "purchase_currency": "USD",
      "amount": 1000
    },
    "default_completion_url": "https://api.sandbox.spider.gr4vy.app/transactions/approve/some-token",
    "integration_client": "ios"
  }
  ```

  ```json Android theme={"system"}
  {
    "session_data": {
      "client_token": "...",
      "purchase_country": "US",
      "purchase_currency": "USD",
      "amount": 1000
    },
    "default_completion_url": "https://api.sandbox.spider.gr4vy.app/transactions/approve/some-token",
    "integration_client": "android"
  }
  ```
</CodeGroup>

Use the `client_token` from the session data to initialize the Klarna SDK. Refer to the [Klarna SDK documentation](https://docs.klarna.com/klarna-payments/sdk-reference/) for web, iOS, and Android integration guides.

#### Complete the transaction

After the customer authorizes the payment through the Klarna SDK, Klarna returns an `authorization_token`. To finalize the transaction, send this token to Gr4vy as a query parameter on the `default_completion_url` returned in the session response.

```bash Terminal theme={"system"}
curl -X GET \
    "<default_completion_url>?authorization_token=<AUTHORIZATION_TOKEN>"
```

Once the request completes successfully, the transaction moves to `authorization_succeeded`. It can then be captured, voided, or refunded through Gr4vy.

## Subscriptions (MIT)

Klarna supports storing the buyer's payment method during the first (customer-present) payment and charging future renewals as merchant-initiated transactions (MIT) using the saved payment method, typically with no redirect.

<Note>
  Webhooks must be configured for the Klarna payment service. After the buyer approves the payment, Klarna sends an `authorization_token` via webhook which Gr4vy uses to create the reusable customer token. Without this webhook, `store: true` will not work.
</Note>

### First payment

Set `store` to `true` to save the Klarna payment method for the buyer.

<CodeGroup>
  ```csharp C# theme={"system"}
  using Gr4vy;
  using Gr4vy.Models.Components;

  // Load your private key from disk, env, or your secret manager
  var privateKey = "...";

  var sdk = new Gr4vySDK(
      id: "example",
      server: SDKConfig.Server.Sandbox,
      bearerAuthSource: Auth.WithToken(privateKey),
      merchantAccountId: "default"
  );

  var res = await sdk.Transactions.CreateAsync(transactionCreate: new TransactionCreate() {
      Amount = 5000,
      Currency = "USD",
      Country = "US",
      PaymentMethod = new PaymentMethodRequest() {
          Method = "klarna",
          RedirectUrl = "https://yourapp.com/callback",
          Country = "US",
          Currency = "USD"
      },
      Store = true,
      PaymentSource = "recurring",
      MerchantInitiated = false,
      IsSubsequentPayment = false,
  });
  // handle response
  ```

  ```go Go theme={"system"}
  package main

  import(
      "context"
      "log"
      "github.com/gr4vy/gr4vy-go"
      "github.com/gr4vy/gr4vy-go/models/components"
  )

  func main() {
      // Load your private key from disk, env, or your secret manager
      privateKey := "..."

      s := gr4vy.New(
          gr4vy.WithID("example"),
          gr4vy.WithServer(gr4vy.ServerSandbox),
          gr4vy.WithBearerAuth(gr4vy.WithToken(privateKey)),
          gr4vy.WithMerchantAccountID("default"),
      )

      amount := int64(5000)
      store := true
      merchantInitiated := false
      isSubsequentPayment := false
      res, err := s.Transactions.Create(context.Background(), &components.TransactionCreate{
          Amount: &amount,
          Currency: "USD",
          Country: "US",
          PaymentMethod: &components.PaymentMethodRequest{
              Method: "klarna",
              RedirectUrl: "https://yourapp.com/callback",
              Country: "US",
              Currency: "USD",
          },
          Store: &store,
          PaymentSource: "recurring",
          MerchantInitiated: &merchantInitiated,
          IsSubsequentPayment: &isSubsequentPayment,
      })
      if err != nil {
          log.Fatal(err)
      }

      if res.StatusCode == 201 {
          // handle response
      }
  }
  ```

  ```java Java theme={"system"}
  import com.gr4vy.Gr4vy;
  import com.gr4vy.models.components.*;
  import com.gr4vy.models.operations.*;

  public class Main {
      public static void main(String[] args) {
          // Load your private key from disk, env, or your secret manager
          String privateKey = "...";

          Gr4vy sdk = new Gr4vy.Builder()
              .id("example")
              .server(Server.SANDBOX)
              .bearerAuth(Auth.withToken(privateKey))
              .merchantAccountId("default")
              .build();

          TransactionCreate transactionCreate = new TransactionCreate.Builder()
              .amount(5000)
              .currency("USD")
              .country("US")
              .paymentMethod(new PaymentMethodRequest.Builder()
                  .method("klarna")
                  .redirectUrl("https://yourapp.com/callback")
                  .country("US")
                  .currency("USD")
                  .build())
              .store(true)
              .paymentSource("recurring")
              .merchantInitiated(false)
              .isSubsequentPayment(false)
              .build();

          try {
              CreateTransactionResponse res = sdk.transactions().create(transactionCreate);

              if (res.statusCode == 201) {
                  // handle response
              }
          } catch (Exception e) {
              // handle exception
          }
      }
  }
  ```

  ```php PHP theme={"system"}
  <?php

  require_once 'vendor/autoload.php';

  use Gr4vy;
  use Gr4vy\Auth;
  use Gr4vy\Models\Components;

  // Load your private key from disk, env, or your secret manager
  $privateKey = '...';

  $sdk = Gr4vy\SDK::builder()
      ->setId('example')
      ->setServer('sandbox')
      ->setSecuritySource(Auth::withToken($privateKey))
      ->setMerchantAccountId('default')
      ->build();

  $res = $sdk->transactions->create(new Components\TransactionCreate(
      amount: 5000,
      currency: 'USD',
      country: 'US',
      paymentMethod: new Components\PaymentMethodRequest(
          method: 'klarna',
          redirectUrl: 'https://yourapp.com/callback',
          country: 'US',
          currency: 'USD',
      ),
      store: true,
      paymentSource: 'recurring',
      merchantInitiated: false,
      isSubsequentPayment: false,
  ));

  if ($res->statusCode === 201) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  import gr4vy
  from gr4vy import auth
  from gr4vy.models import components

  # Load your private key from disk, env, or your secret manager
  private_key = "..."

  s = gr4vy.Gr4vy(
      id="example",
      server=gr4vy.SERVER_SANDBOX,
      bearer_auth=auth.with_token(private_key),
      merchant_account_id="default",
  )

  res = s.transactions.create(
      components.TransactionCreate(
          amount=5000,
          currency="USD",
          country="US",
          payment_method=components.PaymentMethodRequest(
              method="klarna",
              redirect_url="https://yourapp.com/callback",
              country="US",
              currency="USD",
          ),
          store=True,
          payment_source="recurring",
          merchant_initiated=False,
          is_subsequent_payment=False,
      ),
  )

  if res.status_code == 201:
      # handle response
      pass
  ```

  ```ts TypeScript theme={"system"}
  import { Gr4vy, withToken } from "@gr4vy/sdk";

  // Load your private key from disk, env, or your secret manager
  const privateKey = process.env.GR4VY_PRIVATE_KEY ?? "...";

  const gr4vy = new Gr4vy({
    id: "example",
    server: "sandbox",
    bearerAuth: withToken({ privateKey }),
    merchantAccountId: "default",
  });

  const res = await gr4vy.transactions.create({
    amount: 5000,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "klarna",
      redirectUrl: "https://yourapp.com/callback",
      country: "US",
      currency: "USD",
    },
    store: true,
    paymentSource: "recurring",
    merchantInitiated: false,
    isSubsequentPayment: false,
  });

  if (res.statusCode === 201) {
    // handle response
  }
  ```
</CodeGroup>

### Subsequent payment

After the payment method is saved, use the payment method ID to charge future renewals.

* Set `payment_method.method` to `id` and pass the saved payment method ID.
* Set `payment_source` to `recurring`.
* Set `merchant_initiated` and `is_subsequent_payment` to `true`.

<CodeGroup>
  ```csharp C# theme={"system"}
  using Gr4vy;
  using Gr4vy.Models.Components;

  // Load your private key from disk, env, or your secret manager
  var privateKey = "...";

  var sdk = new Gr4vySDK(
      id: "example",
      server: SDKConfig.Server.Sandbox,
      bearerAuthSource: Auth.WithToken(privateKey),
      merchantAccountId: "default"
  );

  var res = await sdk.Transactions.CreateAsync(transactionCreate: new TransactionCreate() {
      Amount = 5000,
      Currency = "USD",
      Country = "US",
      PaymentMethod = new PaymentMethodRequest() {
          Method = "id",
          Id = "c2495b14-ca95-4199-87c3-27cbfefcbe9e"
      },
      PaymentSource = "recurring",
      MerchantInitiated = true,
      IsSubsequentPayment = true,
  });
  // handle response
  ```

  ```go Go theme={"system"}
  package main

  import(
      "context"
      "log"
      "github.com/gr4vy/gr4vy-go"
      "github.com/gr4vy/gr4vy-go/models/components"
  )

  func main() {
      // Load your private key from disk, env, or your secret manager
      privateKey := "..."

      s := gr4vy.New(
          gr4vy.WithID("example"),
          gr4vy.WithServer(gr4vy.ServerSandbox),
          gr4vy.WithBearerAuth(gr4vy.WithToken(privateKey)),
          gr4vy.WithMerchantAccountID("default"),
      )

      amount := int64(5000)
      merchantInitiated := true
      isSubsequentPayment := true
      res, err := s.Transactions.Create(context.Background(), &components.TransactionCreate{
          Amount: &amount,
          Currency: "USD",
          Country: "US",
          PaymentMethod: &components.PaymentMethodRequest{
              Method: "id",
              Id: "c2495b14-ca95-4199-87c3-27cbfefcbe9e",
          },
          PaymentSource: "recurring",
          MerchantInitiated: &merchantInitiated,
          IsSubsequentPayment: &isSubsequentPayment,
      })
      if err != nil {
          log.Fatal(err)
      }

      if res.StatusCode == 201 {
          // handle response
      }
  }
  ```

  ```java Java theme={"system"}
  import com.gr4vy.Gr4vy;
  import com.gr4vy.models.components.*;
  import com.gr4vy.models.operations.*;

  public class Main {
      public static void main(String[] args) {
          // Load your private key from disk, env, or your secret manager
          String privateKey = "...";

          Gr4vy sdk = new Gr4vy.Builder()
              .id("example")
              .server(Server.SANDBOX)
              .bearerAuth(Auth.withToken(privateKey))
              .merchantAccountId("default")
              .build();

          TransactionCreate transactionCreate = new TransactionCreate.Builder()
              .amount(5000)
              .currency("USD")
              .country("US")
              .paymentMethod(new PaymentMethodRequest.Builder()
                  .method("id")
                  .id("c2495b14-ca95-4199-87c3-27cbfefcbe9e")
                  .build())
              .paymentSource("recurring")
              .merchantInitiated(true)
              .isSubsequentPayment(true)
              .build();

          try {
              CreateTransactionResponse res = sdk.transactions().create(transactionCreate);

              if (res.statusCode == 201) {
                  // handle response
              }
          } catch (Exception e) {
              // handle exception
          }
      }
  }
  ```

  ```php PHP theme={"system"}
  <?php

  require_once 'vendor/autoload.php';

  use Gr4vy;
  use Gr4vy\Auth;
  use Gr4vy\Models\Components;

  // Load your private key from disk, env, or your secret manager
  $privateKey = '...';

  $sdk = Gr4vy\SDK::builder()
      ->setId('example')
      ->setServer('sandbox')
      ->setSecuritySource(Auth::withToken($privateKey))
      ->setMerchantAccountId('default')
      ->build();

  $res = $sdk->transactions->create(new Components\TransactionCreate(
      amount: 5000,
      currency: 'USD',
      country: 'US',
      paymentMethod: new Components\PaymentMethodRequest(
          method: 'id',
          id: 'c2495b14-ca95-4199-87c3-27cbfefcbe9e',
      ),
      paymentSource: 'recurring',
      merchantInitiated: true,
      isSubsequentPayment: true,
  ));

  if ($res->statusCode === 201) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  import gr4vy
  from gr4vy import auth
  from gr4vy.models import components

  # Load your private key from disk, env, or your secret manager
  private_key = "..."

  s = gr4vy.Gr4vy(
      id="example",
      server=gr4vy.SERVER_SANDBOX,
      bearer_auth=auth.with_token(private_key),
      merchant_account_id="default",
  )

  res = s.transactions.create(
      components.TransactionCreate(
          amount=5000,
          currency="USD",
          country="US",
          payment_method=components.PaymentMethodRequest(
              method="id",
              id="c2495b14-ca95-4199-87c3-27cbfefcbe9e",
          ),
          payment_source="recurring",
          merchant_initiated=True,
          is_subsequent_payment=True,
      ),
  )

  if res.status_code == 201:
      # handle response
      pass
  ```

  ```ts TypeScript theme={"system"}
  import { Gr4vy, withToken } from "@gr4vy/sdk";

  // Load your private key from disk, env, or your secret manager
  const privateKey = process.env.GR4VY_PRIVATE_KEY ?? "...";

  const gr4vy = new Gr4vy({
    id: "example",
    server: "sandbox",
    bearerAuth: withToken({ privateKey }),
    merchantAccountId: "default",
  });

  const res = await gr4vy.transactions.create({
    amount: 5000,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "id",
      id: "c2495b14-ca95-4199-87c3-27cbfefcbe9e",
    },
    paymentSource: "recurring",
    merchantInitiated: true,
    isSubsequentPayment: true,
  });

  if (res.statusCode === 201) {
    // handle response
  }
  ```
</CodeGroup>
