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:
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:
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.
Before implementing caching, ensure you have:
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:
The API response includes a Cache-Control header specifying the maximum cache age:
Cache-Control: max-age=14400You must respect this cache duration and refresh variants when the cache expires.
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 rangeSelect the appropriate variant based on the cart/transaction amount. Different messaging can appear for different amount thresholds.
Example scenarios:
Ensure your implementation refreshes the display if the cart amount changes during checkout.
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:
Request a presentation variant from the Payment Presentation Variant API using the endpoint below.
GET /accounts/{partner_account_id}/payment/presentation/variant| Parameter | Type | Required | Description |
|---|---|---|---|
partner_account_id | string | Yes | The Partner Account ID for which to retrieve presentation variant |
| Parameter | Type | Required | Description |
|---|---|---|---|
currency | string | Yes | ISO 4217 currency code (e.g., USD, EUR, GBP) |
locale | string | Yes | BCP 47 language tag (e.g., en-US, en-DE, sv-SE) |
intent | string | Yes | Primary 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] | string | Conditional | Klarna-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] | string | Conditional | Acquiring account identifier. Required for multi-payment-account configurations. Must be provided together with acquiring_config[payment_account_reference]. |
acquiring_config[payment_account_reference] | string | Conditional | Unique 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:
acquiring_config[payment_acquiring_account_id] + acquiring_config[payment_account_reference]acquiring_config[payment_account_id]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'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.
The response contains the following top-level fields:
| Field | Type | Description |
|---|---|---|
applicable_parameters | object | Parameter combination for which this variant applies |
applicable_parameters.intent | string | Payment intent (PAY, SUBSCRIBE) |
applicable_parameters.locale | string | BCP 47 language tag |
applicable_parameters.currency | string | ISO 4217 currency code |
applicable_parameters.payment_account_id | string | Payment Account ID (if applicable) |
applicable_parameters.payment_account_reference | string | Payment Account Reference (if applicable) |
payment_presentation_variant_id | string | Unique identifier for this variant (only present when instruction is SHOW_KLARNA) |
instruction | string | Display instruction: SHOW_KLARNA, HIDE_KLARNA |
ranged_payment_options | array | Amount-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_optionsHIDE_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_optionsWhen the instruction is SHOW_KLARNA, the response includes ranged_payment_options with amount-based presentation data.
| Field | Type | Description |
|---|---|---|
ranged_payment_options | array | Array of amount-based presentation options |
ranged_payment_options[].range | object | Amount range definition |
ranged_payment_options[].range.minimum_amount | integer | Minimum amount (minor units, inclusive) |
ranged_payment_options[].range.maximum_amount | integer | Maximum amount (minor units, exclusive). Omitted for the last range (unbounded maximum) |
ranged_payment_options[].payment_option | object | Payment Presentation data for this range |
{
"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": [
{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.
{
"applicable_parameters": {
"intent": "PAY",
"locale": "en-DE",
"currency": "EUR",
"payment_account_id": "PYAC_1234567890",
"payment_account_reference": "partner_ref_001"
},
"instruction": "HIDE_KLARNA"
}Cache the response with appropriate TTL extracted from the Cache-Control header.
Structure cache keys based on the request parameters to ensure accurate variant retrieval and avoid cache collisions.
Build cache key from parameter values:
Example cache key format:
klarna:presentation:variant:{partner_account_id}:{currency}:{locale}:{intent}:{acquiring_config_hash}Example implementation
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).
function parseCacheMaxAge(cacheControlHeader) {
const match = cacheControlHeader?.match(/max-age=(\d+)/);
return match ? parseInt(match[1]) : 14400;
}Store the response using the parsed TTL:
const cacheKey = generateCacheKey(partnerAccountId, request.params);
const maxAge = parseCacheMaxAge(response.headers['cache-control']);
cache.set(cacheKey, JSON.stringify(response.body), maxAge);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).
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);
}When a variant is available (from cache or from a fresh API response), render it based on the instruction field:
HIDE_KLARNA -- Do not display Klarna in the payment selector for this parameter combination.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.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,Test your caching implementation thoroughly before production deployment.
Verify that cache hits return correct presentation data:
Test cache miss scenarios:
Validate cache refresh behavior:
Test variant selection across amount thresholds:
Validate correct variant selection for different parameter combinations:
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:
payment_presentation_variant_idCode example:
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:
Problem: Outdated presentation data displayed in checkout
Possible causes:
Solutions:
Problem: Cache refresh fails when calling Variant API
Possible causes:
Solutions:
Once you have cached presentation variants, choose how to present Klarna at checkout:
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.
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.