Build the payment form with caching

Implement Payment Presentation caching for server-side integrations where you forward presentation data to Partners. This guide shows how to cache Klarna Payment Presentation variants for non-personalized flows, minimizing dependencies on third-party API calls during checkout.

As an Acquiring Partner, you can optimize checkout performance by caching Klarna Payment Presentation data. The Payment Presentation Variant API provides pre-defined presentation variants based on specific currency, locale, and intent combinations. This allows you to render Klarna payment methods without making real-time API calls on every checkout page load.

The API uses a lazy loading approach: you request a variant for a specific parameter combination when needed and cache the response for subsequent checkouts with the same parameters.

Caching Payment Presentation data delivers several benefits:

  • Reduced latency during critical checkout moments
  • Fewer dependencies on external services during payment creation
  • Improved infrastructure costs and resilience
  • Better customer experience with faster page loads

Presentation data is solely determined by transaction context (partner account, amount, currency, locale, intent) rather than customer identity.

The API is optimized for lazy loading. This means variants are not pre-fetched or loaded in bulk. Instead, the first checkout that uses a particular currency, locale, and intent combination triggers a call to the Variant API. The response is then cached so that all subsequent checkouts with the same parameters are served from cache without an API call.

Use the Payment Presentation Variant API for non-personalized checkout flows where:

  • No Customer Token is present (customer is not authenticated)
  • No Klarna Network Session Token is available (no active Klarna session)

If a Customer Token or Klarna Network Session Token is present, use the standard (non-caching) Payment Presentation integration instead. See Payment Presentation for Hosted Checkout or Payment Presentation for Server-Side Integration.

Prerequisites

Before implementing caching, ensure you have:

  • Valid Partner Account ID
  • API credentials with access to the Payment Presentation API
  • Caching infrastructure (Redis, Memcached, or similar)
  • Backend support for HTTP Cache-Control headers

How caching works

Variants concept

A presentation variant represents a set of Payment Presentation data that applies to a specific amount range within a given context.

Each variant can include:

  • Header text (e.g., "Pay with Klarna")
  • Subheader text (e.g., "Flexible payments")
  • Message parts with text and links (optional)
  • Payment button configuration
  • Icon URLs for different sizes

Cache duration

The API response includes a Cache-Control header specifying the maximum cache age:

  • TTL: currently 4 hours (14400 seconds)
  • Header format: Cache-Control: max-age=14400

You must respect this cache duration and refresh variants when the cache expires.

Amount-based variant selection

Each variant includes a ranged_payment_options array with amount-based presentation rules. Each range specifies:

  • minimum_amount: Minimum amount (in minor units, inclusive)
  • maximum_amount: Maximum amount (in minor units, exclusive)
  • payment_option: Presentation data for this range

Select the appropriate variant based on the cart/transaction amount. Different messaging can appear for different amount thresholds.

Example scenarios:

  • Amounts 0.00 - 100.00: "Flexible payments"
  • Amounts 100.00 and above: "Pay in 4, 0% interest"

Ensure your implementation refreshes the display if the cart amount changes during checkout.

Integration overview

The caching integration follows this high-level flow using a lazy loading strategy. This flow applies whether you render a hosted checkout yourself or return cached presentation data to Partners through your API:

  1. 1.
    At checkout, generate cache key from specific currency/locale/intent combination
  2. 2.
    Check cache for presentation variant matching the parameters
  3. 3.
    On cache miss: request presentation variant from Klarna API for the specific combination
  4. 4.
    Store variant in cache with TTL from Cache-Control header (currently 4 hours)
  5. 5.
    Select appropriate payment method based on transaction amount
  6. 6.
    Refresh cached data on cache expiration or cache miss
sequenceDiagram participant Checkout as Checkout Page<br/>(Hosted or Server-Side) participant AP as Acquiring Partner Backend participant C as Cache Layer participant K as Klarna Variant API Note over Checkout,AP: Customer checkout flow Checkout->>AP: Request Klarna presentation Note over Checkout,AP: amount, currency, locale, intent AP->>C: Lookup cached variants alt Cache miss AP->>K: Query Variant API K->>AP: Return variants AP->>C: Update cache else Cache hit C->>AP: Return cached variants end Note over AP: Select variant by parameters Note over AP: Select option by amount AP->>Checkout: Return Klarna presentation data

Integration steps

Step 1: Request Payment Presentation Variant

Request a presentation variant from the Payment Presentation Variant API using the endpoint below.

API endpoint
HTTP
GET /accounts/{partner_account_id}/payment/presentation/variant
Path parameters
ParameterTypeRequiredDescription
partner_account_idstringYesThe Partner Account ID for which to retrieve presentation variant
Query parameters
ParameterTypeRequiredDescription
currencystringYesISO 4217 currency code (e.g., USD, EUR, GBP)
localestringYesBCP 47 language tag (e.g., en-US, en-DE, sv-SE)
intentstringYesPrimary payment intent. Possible values: PAY, SUBSCRIBE. When multiple intents are present in a flow, specify the primary intent you want to promote.
acquiring_config[payment_account_id]stringConditionalKlarna-assigned Payment Account identifier. Required for multi-payment-account configurations. Use this parameter alone or use the combination of acquiring_config[payment_acquiring_account_id] and acquiring_config[payment_account_reference] — not both.
acquiring_config[payment_acquiring_account_id]stringConditionalAcquiring account identifier. Required for multi-payment-account configurations. Must be provided together with acquiring_config[payment_account_reference].
acquiring_config[payment_account_reference]stringConditionalUnique string reference to identify the Payment Account. Required for multi-payment-account configurations. Must be provided together with acquiring_config[payment_acquiring_account_id].

Acquiring configuration for multi-payment-account Partners

If you are an Acquiring Partner with multiple Payment Accounts, include the acquiring_config query parameter to specify which Payment Account to use. For Partners with a single Payment Account, omitting acquiring_config is allowed — Klarna automatically uses the only available Payment Account.

Provide one of the following combinations — not both:

  • Payment Account Reference: acquiring_config[payment_acquiring_account_id] + acquiring_config[payment_account_reference]
  • Payment Account ID: acquiring_config[payment_account_id]
Sample request
SHELL
curl -G https://api-global.test.klarna.com/v2/accounts/PA12345678/payment/presentation/variant \
  -H 'Authorization: Basic <API_KEY>' \
  -H 'Content-Type: application/json' \
  --data-urlencode 'currency=EUR' \
  --data-urlencode 'locale=en-DE' \
  --data-urlencode 'intent=PAY'
When to request variant

Fetch Payment Presentation Variant on demand when the requested parameter combination is not available in cache. The API accepts one specific combination of currency, locale, and intent per request.

Response handling

The response contains the following top-level fields:

FieldTypeDescription
applicable_parametersobjectParameter combination for which this variant applies
applicable_parameters.intentstringPayment intent (PAY, SUBSCRIBE)
applicable_parameters.localestringBCP 47 language tag
applicable_parameters.currencystringISO 4217 currency code
applicable_parameters.payment_account_idstringPayment Account ID (if applicable)
applicable_parameters.payment_account_referencestringPayment Account Reference (if applicable)
payment_presentation_variant_idstringUnique identifier for this variant (only present when instruction is SHOW_KLARNA)
instructionstringDisplay instruction: SHOW_KLARNA, HIDE_KLARNA
ranged_payment_optionsarrayAmount-based presentation options (only present when instruction is SHOW_KLARNA)

Always honor the instruction field from the response:

  • SHOW_KLARNA: Display Klarna as a payment option. Response includes payment_presentation_variant_id and ranged_payment_options
  • HIDE_KLARNA: Do not present Klarna, this instruction means that Klarna is not available for the combination of provided parameters. Response does NOT include payment_presentation_variant_id or ranged_payment_options

When the instruction is SHOW_KLARNA, the response includes ranged_payment_options with amount-based presentation data.

Fields
FieldTypeDescription
ranged_payment_optionsarrayArray of amount-based presentation options
ranged_payment_options[].rangeobjectAmount range definition
ranged_payment_options[].range.minimum_amountintegerMinimum amount (minor units, inclusive)
ranged_payment_options[].range.maximum_amountintegerMaximum amount (minor units, exclusive). Omitted for the last range (unbounded maximum)
ranged_payment_options[].payment_optionobjectPayment Presentation data for this range
When Klarna is available (SHOW_KLARNA)
JSON
{
  "applicable_parameters": {
    "intent": "PAY",
    "locale": "en-DE",
    "currency": "EUR",
    "payment_account_id": "PYAC_1234567890",
    "payment_account_reference": "partner_ref_001"
  },
  "payment_presentation_variant_id": "variant_id_1",
  "instruction": "SHOW_KLARNA",
  "ranged_payment_options": [
    {
When Klarna is not available (HIDE_KLARNA)

Klarna returns HIDE_KLARNA when the requested combination of currency, locale, or intent is not supported for the given Partner Account. In this case, do not display Klarna as a payment option for that parameter combination.

JSON
{
  "applicable_parameters": {
    "intent": "PAY",
    "locale": "en-DE",
    "currency": "EUR",
    "payment_account_id": "PYAC_1234567890",
    "payment_account_reference": "partner_ref_001"
  },
  "instruction": "HIDE_KLARNA"
}

Step 2: Store the Payment Presentation Variant response in cache

Cache the response with appropriate TTL extracted from the Cache-Control header.

Caching strategy

Structure cache keys based on the request parameters to ensure accurate variant retrieval and avoid cache collisions.

Build cache key from parameter values:

  1. 1.
    Concatenate parameter values (currency, locale, intent, acquiring_config if present)
  2. 2.
    Generate MD5 or SHA-256 hash for cache key component
  3. 3.
    Include all filtering parameters to avoid cache collisions

Example cache key format:

TEXT
klarna:presentation:variant:{partner_account_id}:{currency}:{locale}:{intent}:{acquiring_config_hash}

Example implementation

JAVASCRIPT
function generateCacheKey(partnerAccountId, params) {
  const parts = [
    params.currency,
    params.locale,
    params.intent,
    params.acquiring_config || ''
  ];
  const hash = md5(parts.join('|'));
  return `klarna:variant:${partnerAccountId}:${hash}`;
}

Save the response object in cache

Using a consistent key, store the response object in cache using the TTL specified in the Cache-Control header (currently 4 hours or 14400 seconds).

Parse the Cache-Control header to extract the max-age value. If the header is missing or malformed, fall back to a TTL of 4 hours (14400 seconds).

JAVASCRIPT
function parseCacheMaxAge(cacheControlHeader) {
  const match = cacheControlHeader?.match(/max-age=(\d+)/);
  return match ? parseInt(match[1]) : 14400;
}

Store the response using the parsed TTL:

JAVASCRIPT
const cacheKey = generateCacheKey(partnerAccountId, request.params);
const maxAge = parseCacheMaxAge(response.headers['cache-control']);

cache.set(cacheKey, JSON.stringify(response.body), maxAge);

Step 3: Retrieve cached variant

At checkout time, look up the cached variant for the current parameter combination. If a cached variant exists, use it to render the payment method (see Step 4). If the cache has no entry for the requested parameters, fall back to a live API call (Step 1) and store the result (Step 2).

JAVASCRIPT
function getCachedPresentation(partnerAccountId, params) {
  const cacheKey = generateCacheKey(partnerAccountId, params);
  const cached = cache.get(cacheKey);

  if (!cached) {
    return null;
  }

  return renderPaymentOption(JSON.parse(cached), params.amount);
}

Step 4: Render payment method

When a variant is available (from cache or from a fresh API response), render it based on the instruction field:

  1. 1.
    HIDE_KLARNA -- Do not display Klarna in the payment selector for this parameter combination.
  2. 2.
    SHOW_KLARNA -- Find the matching range in ranged_payment_options where the transaction amount falls between minimum_amount (inclusive) and maximum_amount (exclusive). Use the payment_option fields (header, subheader, icon, payment button, message) from that range to render Klarna in your payment selector.
JAVASCRIPT
function renderPaymentOption(variant, amount) {
  if (variant.instruction === 'HIDE_KLARNA') {
    return null;
  }

  const rangedOption = variant.ranged_payment_options.find(option => {
    const { minimum_amount, maximum_amount } = option.range;
    return amount >= minimum_amount && (maximum_amount === undefined || amount < maximum_amount);
  });

  return {
    variantId: variant.payment_presentation_variant_id,

Testing

Test your caching implementation thoroughly before production deployment.

Cache hit and miss validation

Verify that cache hits return correct presentation data:

  • Request variants for known parameter combinations
  • Confirm variants are stored in cache with correct TTL
  • Validate cache hits return expected presentation data
  • Test cache key generation produces consistent results
  • Verify parameter matching logic selects correct variants

Test cache miss scenarios:

  • Clear cache and verify fallback to Variant API
  • Simulate cache service failures
  • Confirm checkout continues without interruption
  • Verify fallback responses match cached responses

Cache refresh cycle testing

Validate cache refresh behavior:

  • Monitor cache TTL expiration and automatic refresh
  • Test manual cache refresh functionality
  • Verify refreshed data matches latest API response
  • Confirm no gaps in coverage during refresh
  • Test concurrent refresh handling

Amount-based variant selection testing

Test variant selection across amount thresholds:

  • Verify correct variant selection at minimum range boundaries
  • Test maximum range boundaries (exclusive)
  • Validate behavior when amount changes during checkout
  • Confirm messaging updates reflect current cart amount
  • Test edge cases (zero amount, very high amounts)

Multi-currency and locale testing

Validate correct variant selection for different parameter combinations:

  • Test all supported currency/locale/intent combinations
  • Verify correct mapping for Payment Account configurations
  • Test missing parameter combinations (should use fallback)
  • Validate instruction field behavior (SHOW, HIDE)
  • Confirm correct presentation data for each combination

Troubleshooting

Excessive cache growth

Problem: Cache storage grows too large with many parameter combinations or Payment Accounts

Solution: Implement two-level cache using variant IDs

Instead of storing the complete response for every parameter combination, split the storage into two cache collections. This enables deduplication when multiple parameter combinations share the same variant definitions (identified by payment_presentation_variant_id).

Storage architecture:

  1. 1.
    Store parameter-to-variant-ID mappings indexed by cache key (parameter combination)
  2. 2.
    Store variant data (ranged_payment_options) indexed by payment_presentation_variant_id
  3. 3.
    Reference variant data by ID rather than duplicating the full ranged options
  4. 4.
    Share variant definitions across multiple parameter combinations

Code example:

JAVASCRIPT
const variantDataCache = new Cache();
const mappingCache = new Cache();

function storeVariant(partnerAccountId, params, data, maxAge) {
  const cacheKey = generateCacheKey(partnerAccountId, params);

  variantDataCache.set(
    data.payment_presentation_variant_id,
    JSON.stringify({ ranged_payment_options: data.ranged_payment_options }),
    maxAge
  );

Benefits:

  • Deduplication of shared variant data across parameter combinations
  • Reduced memory footprint - variant data stored once regardless of how many parameter combinations reference it
  • Better cache efficiency for large-scale implementations with many parameter combinations

Cache staleness

Problem: Outdated presentation data displayed in checkout

Possible causes:

  • TTL not properly extracted from Cache-Control header
  • Manual cache refresh not clearing old entries
  • Cache key collision causing wrong data retrieval

Solutions:

  • Verify Cache-Control header parsing logic
  • Implement cache versioning to force refresh
  • Review cache key generation for uniqueness
  • Monitor cache entry timestamps

API failures during refresh

Problem: Cache refresh fails when calling Variant API

Possible causes:

  • Network connectivity issues
  • API credentials expired or invalid
  • Rate limiting on API requests

Solutions:

  • Implement exponential backoff for failed requests
  • Validate API credentials before refresh attempts
  • Monitor API response codes and error messages
  • Use cached data until successful refresh (graceful degradation)
  • Alert on repeated refresh failures

Next steps: Present Klarna at checkout

Once you have cached presentation variants, choose how to present Klarna at checkout:

Option 1: Return Klarna presentation data to Partners

If your Partners build their own payment selector, return the cached presentation data through your Partner-facing API so they can render Klarna themselves.

For full implementation details, see Payment Presentation Server-Side Integration.

Option 2: Render a hosted checkout

If you render the payment selector yourself, use the cached presentation data together with the Klarna Web SDK to display Klarna in your hosted checkout.

For full implementation details, see Payment Presentation for Hosted Checkout.

Related articles

Payment Presentation for Hosted Checkout integration

Payment Presentation for Server-side integration