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

→ CLOSED

INITIATED

→ 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 policy

NONE

(always)

NONE

(ON_DISPUTE_OPEN activates Nov 1, 2026)
Appeal workflowNot availableAvailable from Nov 1, 2026
Outcome detailNot available

dispute_outcome_detailed

(open enum, 40+ values)
Settlement: reversalLegacy type

CREDIT

/ CHARGEBACK_REVERSAL
Settlement: feesNot applicable

FEE

/ 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
{
  "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
{
  "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_OPEN

Funds placed on hold when a dispute is opened. Only applies to disputes opened on or after Nov 1, 2026.

NONE

No 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

opened

Dispute opened

started

Investigation has started

unresolved

Dispute is unresolved

replied

Merchant has replied to request

deadline_expired

Response deadline passed without reply

loss_accepted

Merchant accepted loss

closed

Dispute 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<br/>(INITIATED)"] -->|up to 21 days| B["Evidence Under Review<br/>(REPRESENTMENT)"] B -->|60 days| C["CLOSED"]

Disputes opened on or after Nov 1, 2026 (full):

flowchart TD A["Open / Evidence Requested<br/>(INITIATED)"] -->|up to 21 days| B["Evidence Under Review<br/>(REPRESENTMENT)"] B -->|30 days| C["CLOSED"] B --> D["PRE_ARBITRATION<br/>(preliminary decision)"] D --> E["ARBITRATION<br/>(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

INITIATED

Dispute opened with evidence request. Evidence window is open.

REPRESENTMENT

Partner submitted evidence; Klarna is reviewing. Deadline to accept or escalate.

PRE_ARBITRATION

Preliminary decision made. Partner can accept outcome or appeal.

ARBITRATION

Arbitration in progress. Final binding decision pending.

CLOSED

Dispute is closed with a final outcome.

Within INITIATED and REPRESENTMENT, a nested representment.state tracks the evidence request status:

V4 representment.stateMeaning

EVIDENCE_REQUESTED

Partner can submit evidence or accept loss

EVIDENCE_RECEIVED

Evidence submitted; under review; no further partner action

EVIDENCE_REQUEST_EXPIRED

Deadline passed without partner response

EVIDENCE_WAIVED

Partner accepted loss in INITIATED state

REPRESENTMENT_AUTOMATICALLY_REJECTED

Dispute amount below threshold; auto-resolved as LOST

V2 → V4 state mapping

V2 investigation_statusV4 stateV4 representment.stateNotes

opened

/ started

INITIATED

EVIDENCE_REQUESTED

Evidence window open

replied

REPRESENTMENT

EVIDENCE_RECEIVED

Evidence under review

unresolved

REPRESENTMENT

—Awaiting partner action on preliminary outcome

deadline_expired

REPRESENTMENT

EVIDENCE_REQUEST_EXPIRED

Missed the evidence window

loss_accepted

CLOSED

EVIDENCE_WAIVED

Outcome = LOST

closed

CLOSED

—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
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. For the first 1–2 weeks after onboarding, process FRAMEWORK_2026 disputes exclusively via V4.
  2. Optionally cross-access: use V4 to view and respond to a subset of FRAMEWORK_2020 disputes to confirm compatibility.
  3. Validate that dispute_outcome_detailed values are handled correctly — this is an open enum; unknown values must not crash your system.
  4. Confirm settlement files include the new transaction types for FRAMEWORK_2026 disputes.
  5. If using webhooks: confirm FRAMEWORK_2020 events arrive on the V1/V2/V3 subscription and FRAMEWORK_2026 events on the V4 subscription.
  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. Cancel the V1/V2/V3 webhook subscription.
  2. Retire your V1/V2/V3 API integration.
  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 disputes

GET /disputes/v2/disputes

GET /v4/payment/disputes

Get dispute

GET /disputes/v2/disputes/{dispute_krn}

GET /v4/payment/disputes/{payment_dispute_id}

Submit response / evidence

POST /disputes/v2/disputes/{dispute_krn}/requests/{request_id}/responses

POST /v4/payment/disputes/{payment_dispute_id}/represent

Accept loss

POST /disputes/v2/disputes/{dispute_krn}/accept-loss

POST /v4/payment/disputes/{payment_dispute_id}/accept-loss

Upload attachment

POST /disputes/v2/disputes/{dispute_krn}/attachments

POST /v4/payment/disputes/{payment_dispute_id}/attachments

Download attachment

GET /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 ID

dispute_krn

payment_dispute_id

Format changed; store both during migration.
Overall state

status

(open/closed)

state

(5 values)
Binary → 5-state model.
Investigation detail

investigation_status

(7 values)

state

+ representment.state
Two-level hierarchy.
Creation date

opened_at

created_at

Renamed; 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 deadline

deadline_expires_at

representment.expires_at

Moved to nested object; can be extended (see deadline extension event).
Dispute reason

reason

(lower_snake_case)

dispute_reason

(UPPER_SNAKE_CASE)
See reason mapping.
Disputed amount

disputed_amount.amount

(integer, minor units)

dispute_amount

(integer, minor units)
Renamed and moved to top level.
Currency

disputed_amount.currency

currency

Moved to top level.
Chargeback amount

chargeback_amount

—Removed; use settlement data.
Region

region

—Removed.
Request/response history

requests[]

(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_at

New.
State transition history—

previous_state

New.
Exceptions—

process_exceptions[]

New — tracks window extensions, immediate resolution.

Dispute reason mapping

V2 reasonV4 dispute_reason

goods_not_received

PRODUCTS_OR_SERVICES_NOT_RECEIVED

faulty_goods

PRODUCTS_DEFECTIVE_OR_NOT_AS_DESCRIBED

return

REFUND_NOT_PROCESSED

already_paid

/ incorrect_invoice

INCORRECT_AMOUNT

unauthorized_purchase

PURCHASE_UNAUTHORIZED

high_risk_order

PURCHASE_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_at

sort_by=created_at

Field renamed.

next_page

(cursor)

starting_after

(cursor)
Renamed.

limit

(max 250)

size

Renamed.
—

created_at_start

/ created_at_end
New date range filter.
—

closed_at_start

/ closed_at_end
New 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
// 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.",
  "attachments": [1, 2, 3]
}

V4 — free-text with attachments

V4 replaces structured fields with a flexible free-text model:

JSON
// 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",
      "description": "Courier tracking history screenshot"
    }

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
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.initiated

Dispute moves to INITIATED

payment.dispute.state-change.representment

Dispute moves to REPRESENTMENT

payment.dispute.state-change.pre-arbitration

Dispute moves to PRE_ARBITRATION

payment.dispute.state-change.arbitration

Dispute moves to ARBITRATION

payment.dispute.state-change.closed

Dispute moves to CLOSED

payment.dispute.updated

Non-state update on dispute

payment.dispute.updated.representment-deadline-extended

Evidence response deadline extended

Routing by framework

Use base_framework in the webhook payload to route processing:

TEXT
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_REVERSAL

Dispute held under ON_DISPUTE_OPEN closes in merchant's favor — held funds returnedNov 1, 2026

APPEAL_FEE

Merchant files an appeal in PRE_ARBITRATION stateNov 1, 2026

Error response format

V2:

JSON
{
  "error_code": "INCOMPATIBLE_DISPUTE_STATE",
  "error_message": "Cannot perform operation in current dispute state"
}

V4:

JSON
{
  "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.