Klarna

Disputes migration to V4

To ensure a seamless migration from Disputes API V1/V2/V3 to V4 with no service disruptions or loss of capability, follow this migration guide.

Overview

Klarna is introducing Disputes API V4, which adds multi-phase review, an appeal workflow, and richer dispute outcomes. To allow a seamless migration with no service disruption, V1, V2, V3 and V4 operate in parallel during the migration window.
Two key dates drive the migration:
  • Your V4 onboarding timestamp — the dividing line between dispute frameworks. Disputes opened before it are FRAMEWORK_2020 (legacy); disputes opened after it are FRAMEWORK_2026. Assignment is automatic and permanent. The framework is always readable from configuration.base_framework.
  • November 1, 2026 — a second cutoff within FRAMEWORK_2026 when the 30-day review window, the appeal workflow, and the ON_DISPUTE_OPEN hold policy activate.
Two access models to remember:
  • REST is cross-version: Once onboarded to V4, every dispute (any framework) is readable and actionable on every API version.
  • Webhooks are framework-scoped: V1/V2/V3 subscriptions deliver FRAMEWORK_2020 events only; V4 subscriptions deliver FRAMEWORK_2026 events only. Both must run in parallel until all FRAMEWORK_2020 disputes have closed.

Framework comparison at a glance

PropertyFRAMEWORK_2020FRAMEWORK_2026
Applies to disputes openedBefore V4 onboarding timestampAfter V4 onboarding timestamp
Lifecycle states (V4)INITIATED → CLOSEDINITIATED → REPRESENTMENT → PRE_ARBITRATION → ARBITRATION → CLOSED
Evidence windowUp to 14 days (after up to 21-day open period)Up to 21 days (from dispute open)
Review periodUp to 60 days60 days before Nov 1, 2026 / 30 days from Nov 1, 2026
Total max duration~95 days~81 days before Nov 1, 2026 / ~51 days from Nov 1, 2026 (longer if arbitration)
API access (REST)All API versionsAll API versions
Webhook subscriptionV1/V2/V3V4
Default hold policyNONE (always)NONE (ON_DISPUTE_OPEN activates Nov 1, 2026)
Appeal workflowNot availableAvailable from Nov 1, 2026
Outcome detailNot availabledispute_outcome_detailed (open enum, 40+ values)
Settlement: reversalLegacy typeCHARGEBACK_REVERSAL / CHARGEBACK_RELEASED
Settlement: feesNot applicableFEE / APPEAL_FEE
RollbackN/AFull rollback to V1/V2/V3 is possible at any time

Concepts

Dispute frameworks

FRAMEWORK_2020 (legacy)

Applies to disputes opened before your V4 onboarding timestamp. Follows the legacy dispute rules and lifecycle. No changes are made to disputes already under this framework.
JSON
1 2 3 4 5 6 7
{ "configuration": { "base_framework": "FRAMEWORK_2020", "options": { "hold_policy": "NONE" } } }

FRAMEWORK_2026

Applies to disputes opened after your V4 onboarding timestamp. Follows the FRAMEWORK_2026 lifecycle with multi-phase review, new settlement transaction types, and a configurable hold policy.
Default configuration from onboarding:
JSON
1 2 3 4 5 6 7
{ "configuration": { "base_framework": "FRAMEWORK_2026", "options": { "hold_policy": "NONE" } } }
Phased feature rollout — November 1, 2026. Not all FRAMEWORK_2026 features activate at onboarding. The features below only apply to disputes opened on or after Nov 1, 2026:
FeatureBefore Nov 1, 2026From Nov 1, 2026
Evidence windowUp to 21 daysUp to 21 days
Review window60 days (same as FRAMEWORK_2020)30 days
PRE_ARBITRATION / appealNot availableAvailable
Hold policy ON_DISPUTE_OPENNot activeActive
Implications:
  • The appeal flow will not trigger for any dispute until Nov 1, 2026 — do not treat it as a day-one requirement.
  • SLA monitoring must account for the 60-day review window for all FRAMEWORK_2026 disputes opened before that date.
  • New settlement transaction types (CHARGEBACK_REVERSAL, APPEAL_FEE) must be integrated before Nov 1, 2026 — see Settlement transaction types.

hold_policy reference

ValueMeaning
ON_DISPUTE_OPENFunds placed on hold when a dispute is opened. Only applies to disputes opened on or after Nov 1, 2026.
NONENo fund hold on dispute open (FRAMEWORK_2026 default).

Dispute lifecycle and states

FRAMEWORK_2020 lifecycle (V1/V2/V3)

flowchart LR A[Open] -->|up to 21 days| B[Evidence Requested] B -->|up to 14 days| C[Evidence Under Review] C -->|60 days| D[Closed]
Total maximum duration: ~95 days.
In V1/V2/V3 this is reflected in investigation_status:
V2 investigation_statusMeaning
openedDispute opened
startedInvestigation has started
unresolvedDispute is unresolved
repliedMerchant has replied to request
deadline_expiredResponse deadline passed without reply
loss_acceptedMerchant accepted loss
closedDispute is closed

FRAMEWORK_2026 lifecycle (V4)

FRAMEWORK_2026 has two sub-phases depending on whether the dispute opened before or on/after November 1, 2026.
Disputes opened before Nov 1, 2026 (transitional):
flowchart LR A["Open / Evidence Requested (INITIATED)"] -->|up to 21 days| B["Evidence Under Review (REPRESENTMENT)"] B -->|60 days| C["CLOSED"]
Disputes opened on or after Nov 1, 2026 (full):
flowchart TD A["Open / Evidence Requested (INITIATED)"] -->|up to 21 days| B["Evidence Under Review (REPRESENTMENT)"] B -->|30 days| C["CLOSED"] B --> D["PRE_ARBITRATION (preliminary decision)"] D --> E["ARBITRATION (final binding decision)"] E --> C
Key differences from FRAMEWORK_2020:
  • "Open" and "Evidence Requested" are combined into a single state (INITIATED) — the dispute opens with an immediate evidence request, giving up to 21 days from day one.
  • Review period is 30 days (down from 60), from Nov 1, 2026.
  • Two new phases: PRE_ARBITRATION (preliminary decision, partner can appeal) and ARBITRATION (final binding review).
In V4 this is reflected in state:
V4 stateMeaning
INITIATEDDispute opened with evidence request. Evidence window is open.
REPRESENTMENTPartner submitted evidence; Klarna is reviewing. Deadline to accept or escalate.
PRE_ARBITRATIONPreliminary decision made. Partner can accept outcome or appeal.
ARBITRATIONArbitration in progress. Final binding decision pending.
CLOSEDDispute is closed with a final outcome.
Within INITIATED and REPRESENTMENT, a nested representment.state tracks the evidence request status:
V4 representment.stateMeaning
EVIDENCE_REQUESTEDPartner can submit evidence or accept loss
EVIDENCE_RECEIVEDEvidence submitted; under review; no further partner action
EVIDENCE_REQUEST_EXPIREDDeadline passed without partner response
EVIDENCE_WAIVEDPartner accepted loss in INITIATED state
REPRESENTMENT_AUTOMATICALLY_REJECTEDDispute amount below threshold; auto-resolved as LOST

V2 → V4 state mapping

V2 investigation_statusV4 stateV4 representment.stateNotes
opened / startedINITIATEDEVIDENCE_REQUESTEDEvidence window open
repliedREPRESENTMENTEVIDENCE_RECEIVEDEvidence under review
unresolvedREPRESENTMENT—Awaiting partner action on preliminary outcome
deadline_expiredREPRESENTMENTEVIDENCE_REQUEST_EXPIREDMissed the evidence window
loss_acceptedCLOSEDEVIDENCE_WAIVEDOutcome = LOST
closedCLOSED—Check dispute_outcome for WON/LOST

Dual integration model

REST: cross-version access

Once onboarded to V4, every REST operation is available on every API version, regardless of dispute framework. You can shift workflows dispute-by-dispute or team-by-team at your own pace — for example, accessing FRAMEWORK_2020 disputes via V4, or FRAMEWORK_2026 disputes via your existing V2 integration.

Webhooks: framework-scoped delivery

Webhook event delivery does not cross framework boundaries:
Webhook subscriptionFRAMEWORK_2020 eventsFRAMEWORK_2026 events
V1/V2/V3 subscriptionReceivesDoes NOT receive
V4 subscriptionDoes NOT receiveReceives
You must run both webhook subscriptions in parallel throughout the migration. Events are already segregated by framework — there is no overlap and no deduplication needed. Do not cancel the V1/V2/V3 subscription until all FRAMEWORK_2020 disputes are closed.

Migration

The migration follows five sequential steps. The diagram below summarises the end-to-end flow:
sequenceDiagram participant M as Merchant participant V1 as V1/V2/V3 API participant V4 as V4 API participant K as Klarna Note over M,K: Step 1 — Settlement & infrastructure readiness (before Nov 1, 2026) Note over M,K: Step 2 — Onboard MID to V4 M->>V4: POST /v4/payment/disputes/merchants/{merchant_id}/enroll V4->>K: Record onboarding timestamp T0 K-->>M: V4 active Note over M,K: Step 3 — Subscribe to V4 webhooks M->>V4: Create V4 webhook subscription Note over M,V1: V1/V2/V3 webhook subscription remains active Note over M,K: Step 4 — Dual operations K-->>V1: FRAMEWORK_2020 webhooks (disputes opened before T0) K-->>V4: FRAMEWORK_2026 webhooks (disputes opened after T0) M->>V1: Read / respond to FRAMEWORK_2020 disputes M->>V4: Read / respond to FRAMEWORK_2026 disputes M->>V4: (Optional) Cross-access FRAMEWORK_2020 disputes via V4 Note over M,K: Step 5 — Full transition (after all FRAMEWORK_2020 disputes closed) M->>V1: Cancel V1/V2/V3 webhook subscription M->>V1: Retire V1/V2/V3 integration

Prerequisites

Complete every item below before calling the V4 onboarding endpoint. Once onboarded, disputes opened after the timestamp immediately use FRAMEWORK_2026.
Dispute routing:
  • Dispute management system reads configuration.base_framework and routes to the correct processing logic.
  • State machine updated to handle the V4 5-state model: INITIATED, REPRESENTMENT, PRE_ARBITRATION, ARBITRATION, CLOSED.
  • Code handles unknown dispute_outcome_detailed values gracefully (open enum — new values may be added).
Evidence submission:
  • Evidence submission updated to use free-text additional_information (max 5000 chars) instead of structured requested_fields.
  • Attachment handling updated to use KRN-based IDs and include descriptions.
Authentication:
  • V4 API key credentials obtained.
  • V4 authentication tested (HTTP Basic auth with API key, not V2 client credentials).
Webhooks (if applicable):
  • HMAC-SHA256 signature verification implemented in your webhook handler.
  • Webhook handler routes events based on base_framework.
  • V1/V2/V3 webhook subscription confirmed active and will remain active during migration.

Step 1: Prepare settlement handling (before November 1, 2026)

No settlement changes are required before V4 onboarding. With hold_policy: NONE (the FRAMEWORK_2026 default), no funds are held when a dispute opens, so settlement behaviour is unchanged from the legacy behavior:
  • Dispute closes in merchant's favor → no settlement entry (nothing was held).
  • Dispute closes against the merchant → CREDIT appears in the settlement report.
  • FEE continues to appear as it does today.
Two new transaction types activate on November 1, 2026 when hold_policy: ON_DISPUTE_OPEN and the appeal workflow go live. These must be integrated before that date — see Settlement transaction types in the API reference for the full table.

Step 2: Onboard your MID to V4

Call the V4 self-onboarding endpoint. This records the timestamp that divides FRAMEWORK_2020 from FRAMEWORK_2026.
TEXT
1 2
POST /v4/payment/disputes/merchants/{merchant_id}/enroll
After this call:
  • Your MID is active on V4.
  • Disputes opened before this timestamp → FRAMEWORK_2020.
  • Disputes opened after this timestamp → FRAMEWORK_2026 with the default config (hold_policy: NONE).
  • All FRAMEWORK_2020 disputes are immediately accessible via V4 — you can view and respond to them using either V1/V2/V3 or V4 from this point forward.

Step 3: Subscribe to V4 webhooks (webhook users only)

Subscribe to V4 webhooks to receive events for FRAMEWORK_2026 disputes.
Contact your Klarna technical point of contact to enable webhook subscriptions for your integration.
Rules:
  • Your existing V1/V2/V3 webhook subscription stays active — it continues delivering events with base_framework = FRAMEWORK_2020.
  • Your V4 webhook subscription delivers FRAMEWORK_2026 events only.
  • Disputes opened before onboarding will never appear on the V4 subscription.
  • Disputes opened after onboarding will never appear on the V1/V2/V3 subscription.
  • Run both subscriptions in parallel for the entire migration period.
For the full event catalogue, payload routing logic, and deadline-extension handling, see Webhook events and routing in the API reference.

Step 4: Run dual operations and validate

With both integrations active, incrementally migrate dispute workflows to V4 while FRAMEWORK_2020 disputes continue via your existing integration.
Recommended validation sequence:
  1. 1.
    For the first 1–2 weeks after onboarding, process FRAMEWORK_2026 disputes exclusively via V4.
  2. 2.
    Optionally cross-access: use V4 to view and respond to a subset of FRAMEWORK_2020 disputes to confirm compatibility.
  3. 3.
    Validate that dispute_outcome_detailed values are handled correctly — this is an open enum; unknown values must not crash your system.
  4. 4.
    Confirm settlement files include the new transaction types for FRAMEWORK_2026 disputes.
  5. 5.
    If using webhooks: confirm FRAMEWORK_2020 events arrive on the V1/V2/V3 subscription and FRAMEWORK_2026 events on the V4 subscription.
  6. 6.
    Monitor PRE_ARBITRATION events — if your workflow requires challenging preliminary decisions, implement the appeal flow before this occurs in production.

Step 5: Full transition to V4

Once all FRAMEWORK_2020 disputes have reached CLOSED:
  1. 1.
    Cancel the V1/V2/V3 webhook subscription.
  2. 2.
    Retire your V1/V2/V3 API integration.
  3. 3.
    All future disputes will be FRAMEWORK_2026.

Rollback

V4 onboarding does not modify or break your existing V1/V2/V3 integration. At any point you can:
  • Stop sending requests to V4 — your V1/V2/V3 integration continues to work without change.
  • FRAMEWORK_2020 disputes are unaffected by V4 onboarding.
The only irreversible effect is framework assignment: disputes opened after your onboarding timestamp cannot be moved back to FRAMEWORK_2020.

API reference

Endpoint paths

OperationV2 pathV4 path
List disputesGET /disputes/v2/disputesGET /v4/payment/disputes
Get disputeGET /disputes/v2/disputes/{dispute_krn}GET /v4/payment/disputes/{payment_dispute_id}
Submit response / evidencePOST /disputes/v2/disputes/{dispute_krn}/requests/{request_id}/responsesPOST /v4/payment/disputes/{payment_dispute_id}/represent
Accept lossPOST /disputes/v2/disputes/{dispute_krn}/accept-lossPOST /v4/payment/disputes/{payment_dispute_id}/accept-loss
Upload attachmentPOST /disputes/v2/disputes/{dispute_krn}/attachmentsPOST /v4/payment/disputes/{payment_dispute_id}/attachments
Download attachmentGET /disputes/v2/disputes/{dispute_krn}/requests/{request_id}/attachments/{attachment_id}GET /v4/payment/disputes/{payment_dispute_id}/attachments/{payment_dispute_attachment_id}/download
Appeal (new in V4)—POST /v4/payment/disputes/{payment_dispute_id}/appeal

Field mapping

ConceptV2 fieldV4 fieldNotes
Dispute IDdispute_krnpayment_dispute_idFormat changed; store both during migration.
Overall statestatus (open/closed)state (5 values)Binary → 5-state model.
Investigation detailinvestigation_status (7 values)state + representment.stateTwo-level hierarchy.
Creation dateopened_atcreated_atRenamed; values may differ for the same dispute due to FRAMEWORK_2026 lifecycle changes. Do not treat as equivalent — use a single API version as the source of truth for time-based logic.
Response deadlinedeadline_expires_atrepresentment.expires_atMoved to nested object; can be extended (see deadline extension event).
Dispute reasonreason (lower_snake_case)dispute_reason (UPPER_SNAKE_CASE)See reason mapping.
Disputed amountdisputed_amount.amount (integer, minor units)dispute_amount (integer, minor units)Renamed and moved to top level.
Currencydisputed_amount.currencycurrencyMoved to top level.
Chargeback amountchargeback_amount—Removed; use settlement data.
Regionregion—Removed.
Request/response historyrequests[] (nested array)representment (flat object)Structure flattened.
Outcome(inferred from status)dispute_outcome (WON/LOST)Now explicit, CLOSED state only.
Outcome detail—dispute_outcome_detailed (open enum, 40+ values)New — see Open enums.
Last updated—updated_atNew.
State transition history—previous_stateNew.
Exceptions—process_exceptions[]New — tracks window extensions, immediate resolution.

Dispute reason mapping

V2 reasonV4 dispute_reason
goods_not_receivedPRODUCTS_OR_SERVICES_NOT_RECEIVED
faulty_goodsPRODUCTS_DEFECTIVE_OR_NOT_AS_DESCRIBED
returnREFUND_NOT_PROCESSED
already_paid / incorrect_invoiceINCORRECT_AMOUNT
unauthorized_purchasePURCHASE_UNAUTHORIZED
high_risk_orderPURCHASE_HIGH_RISK
pandemic_impact(removed in V4)
—NON_COMPLIANCE (new)
—NON_GUARANTEED_PAYMENT_PROGRAM (new)

List disputes: query parameter changes

V2 parameterV4 parameterNotes
merchant_id[](removed)Authentication now scopes to your MID.
order_id[]order_ids[]Renamed.
investigation_status[]state[]New enum values (see state table).
reason[]reason[]Values renamed to UPPER_SNAKE_CASE.
sort_by=opened_atsort_by=created_atField renamed.
next_page (cursor)starting_after (cursor)Renamed.
limit (max 250)sizeRenamed.
—created_at_start / created_at_endNew date range filter.
—closed_at_start / closed_at_endNew date range filter.
—purchase_references[]New filter.
—payment_transaction_ids[]New filter.

Evidence submission (V2 vs V4)

The evidence submission model changed significantly between V2 and V4.

V2 — structured field responses

V2 required merchants to respond to explicit field requests with structured enum values:
JSON
1 2 3 4 5 6 7 8 9 10
// POST /disputes/v2/disputes/{dispute_krn}/requests/{request_id}/responses { "requested_fields": { "tracking_id": "ABC123", "shipping_date": "2024-01-15", "shipping_carrier": "DHL", "delivered_with_proof": "yes", "goods_returned": "yes_in_full" }, "comment": "All requested information provided.",

V4 — free-text with attachments

V4 replaces structured fields with a flexible free-text model:
JSON
1 2 3 4 5 6 7 8 9 10
// POST /v4/payment/disputes/{payment_dispute_id}/represent { "additional_information": "Shipment was delivered on 2024-01-20 with signature confirmation. Tracking: XYZ789.", "attachments": [ { "payment_dispute_attachment_id": "krn:payment:eu1:dispute:123:attachment:1", "description": "Signed delivery confirmation" }, { "payment_dispute_attachment_id": "krn:payment:eu1:dispute:123:attachment:2",
Key differences:
  • additional_information max length: 5000 characters.
  • No structured field mapping — include all relevant information in the text or as attachments.
  • Attachments referenced by KRN identifier, not numeric ID.
  • Attachment descriptions are optional but recommended.
  • Include tracking numbers, dates, and carrier information in additional_information; supporting documents as attachments.

Appeal endpoint (V4 only)

V4 introduces an appeal flow for the PRE_ARBITRATION state. If Klarna issues a preliminary decision and you wish to challenge it:
TEXT
1 2
POST /v4/payment/disputes/{payment_dispute_id}/appeal
PRE_ARBITRATION and the appeal workflow are only available for FRAMEWORK_2026 disputes opened on or after November 1, 2026. For disputes opened before that date, the dispute goes directly from REPRESENTMENT to CLOSED — no appeal is possible. This endpoint has no V2 equivalent.

Webhook events and routing

Event catalogue

Event typeTrigger
payment.dispute.state-change.initiatedDispute moves to INITIATED
payment.dispute.state-change.representmentDispute moves to REPRESENTMENT
payment.dispute.state-change.pre-arbitrationDispute moves to PRE_ARBITRATION
payment.dispute.state-change.arbitrationDispute moves to ARBITRATION
payment.dispute.state-change.closedDispute moves to CLOSED
payment.dispute.updatedNon-state update on dispute
payment.dispute.updated.representment-deadline-extendedEvidence response deadline extended

Routing by framework

Use base_framework in the webhook payload to route processing:
TEXT
1 2 3 4 5
if payload.configuration.base_framework == "FRAMEWORK_2020": route to V1/V2/V3 processing flow elif payload.configuration.base_framework == "FRAMEWORK_2026": route to V4 processing flow
Webhook events are not duplicated across subscriptions — each subscription receives only its framework's events, so no deduplication is needed.

Handling deadline extensions

V4 introduces deadline extensions via the payment.dispute.updated.representment-deadline-extended event. When received:
  • Update the stored representment.expires_at value in your system.
  • Re-queue any deadline-based automations using the new expiry.

Settlement transaction types

CREDIT and FEE are unchanged — they exist today under FRAMEWORK_2020 and continue to work identically under FRAMEWORK_2026.
Before November 1, 2026 (with hold_policy: NONE):
  • Dispute closes in merchant's favor → no settlement entry (nothing was held, nothing to return).
  • Dispute closes against the merchant → CREDIT in settlement report, same as the legacy behavior.
  • FEE continues to appear as it does today.
  • Disputes transition directly from REPRESENTMENT to CLOSED.
Two new transaction types activate on November 1, 2026, when hold_policy: ON_DISPUTE_OPEN and the appeal workflow go live:
New transaction typeWhen it appearsRequired by
CHARGEBACK_REVERSALDispute held under ON_DISPUTE_OPEN closes in merchant's favor — held funds returnedNov 1, 2026
APPEAL_FEEMerchant files an appeal in PRE_ARBITRATION stateNov 1, 2026

Error response format

V2:
JSON
1 2 3 4 5
{ "error_code": "INCOMPATIBLE_DISPUTE_STATE", "error_message": "Cannot perform operation in current dispute state" }
V4:
JSON
1 2 3 4 5 6 7 8 9 10
{ "error_id": "abc123", "error_type": "BAD_VALUE", "error_code": "INVALID_FIELD_VALUE", "error_message": "Human-readable error message", "validation_errors": [ { "field": "representment.additional_information", "message": "Field must be between 0 and 5000 characters" }
V4 errors include a unique error_id for tracing, an error_type for programmatic handling, and a validation_errors array for field-level detail.

Authentication

V4 uses API key credentials with HTTP Basic Authentication — different from V2's OAuth2 client credentials flow. Ensure your V4 requests use the correct authentication scheme.

Open enums

V4 introduces dispute_outcome_detailed in the CLOSED state with 40+ possible values (e.g. partner_provided_valid_shipping_details, no_proof_of_delivery, customer_cancelled_dispute). New values may be added in the future. Your code must not crash or reject unknown values — handle them gracefully and log them for review.