Klarna settlement CSVs and Shopify sales logs rarely disagree because sales disappeared. They disagree because Klarna settles captured orders on payout timing, while Shopify records orders on storefront timing and labels them with different references.

That means a clean Shopify export can still look wrong beside a clean Klarna file. One row may carry a Shopify order name. The other may carry a Klarna order_id, a short_order_id, or one of the merchant reference fields. A refund can land in a later settlement. A partially shipped order can become more than one capture. Fees, holdbacks, and reversals can reduce the payout without ever having a matching sales row in Shopify.

If you compare the two files row by row from the first tab you exported, the mismatch looks random. It is not random. You are comparing order activity, settlement activity, and payout adjustments as if they were the same thing.

The fix is to separate those layers first, choose one match key, and only then compare amounts.

Read the mismatch before you touch the data

Most failed matches fall into the same handful of patterns. Identify which one you have before you build formulas or start filtering unmatched rows.

What you see on screenHow Klarna stores itHow Shopify stores itWhat happens when you match blindly
#10482 appears in Shopify, but no equal value appears in Klarnaorder_id = c504a9bb-1948-46d5..., merchant_reference1 = #10482Name = #10482The order looks missing if you matched Shopify Name to Klarna order_id
The order date matches, but the payout date does notsale_date = 2026-05-02T21:18:00Z, payout_date = 2026-05-04T07:45:00ZPaid at = 2026-05-02The order looks delayed or missing when it is only settled later
A refund exists in Klarna, but not under the same capture rowtype = RETURN, capture_id = "", same order_id as original saleRefund recorded on the order or transaction history under the original order nameThe refund looks orphaned if you use capture_id as the main key
Klarna shows negative rows that Shopify does nottype = FEE, HOLDBACK, CHARGENo matching order row in a sales logThe settlement looks short even though the sales are fine
One Shopify order total becomes two Klarna sales rowsTwo SALE rows with different capture_id values under one order_idOne order row or one order name in the sales logThe order looks duplicated or partially missing unless you group it first

If your files look like more than one row in that table, that is normal. Klarna and Shopify are tracking different stages of the same commercial event. The comparison works when you decide which stage each file is responsible for proving.

Put each file on the right level first

The Klarna settlement CSV proves what Klarna included in a payout and why that payout moved up or down. The Shopify sales log proves that an order was created, paid, refunded, or adjusted inside the store. Those are related records, but they are not interchangeable.

Use the Klarna file to prove settlement composition, payment reference, and whether fees came out of the payout or were invoiced separately. Use the Shopify file to prove which orders were paid through Klarna, which order identifier belongs to each sale, and whether refunds or duplicate line-item rows exist.

FileKeep these fieldsUse it to proveDo not use it to prove
Klarna settlement CSVpayment_reference, payout_date, type, amount, order_id, short_order_id, merchant_reference1, merchant_reference2, capture_idSettlement composition and payout logicThat every row should have a one-to-one Shopify sales twin
Shopify sales logOrder name/number, payment method or gateway, paid date, refund date, amount, statusStore-side order and transaction activityThe exact makeup of a Klarna settlement payout

This is the first place many reconciliations go wrong. The bookkeeper expects the Shopify sales file to explain fees and reserves. It cannot. Then they expect the Klarna settlement file to behave like an order export. It does not.

Choose the match key before the amount

Amounts are the last thing to compare. If the key is wrong, equal amounts only create false confidence.

The best cross-system match key is usually one of the merchant reference fields in Klarna, because those are the values submitted when the order was created. If merchant_reference1 or merchant_reference2 contains the Shopify order name or order number, use that first. If those fields are blank or unreliable, the next best option is the relationship between Klarna short_order_id and the Shopify order name.

Klarna order_id still matters, but for grouping Klarna activity across the life of one order: sale, fee, return, reversal, correction. It is not automatically the best direct bridge to Shopify because Shopify may never display that UUID. Do not use capture_id as the main key either. Returns and reversals can have it blank, and one Shopify order can produce multiple captures when fulfillment is split.

KeyBest useWeak point
merchant_reference1 / merchant_reference2Direct match to Shopify order name or order numberSometimes blank or inconsistently populated
short_order_idFallback when Klarna and Shopify expose the same customer-facing order referenceNot always the same as the merchant's internal order name
order_idGroup every Klarna event for one orderUsually not present in Shopify sales logs
capture_idDiagnose split captures and shipment-level activityReturns and reversals can have no value here

If the same order already has to be bridged across storefront and payout systems elsewhere in your workflow, the underlying problem is the same one described in why matching Shopify orders to payout files gets slow: the data is not failing because the amounts are wrong, but because the references and event timing drift across exports.

Build the comparison in three passes

Once the key is chosen, run the comparison in layers. Do not start with the payout total.

1. Isolate Shopify rows that belong to Klarna

Filter the Shopify sales log to the relevant gateway first. If the file contains card payments, PayPal payments, gift cards, or manual orders beside Klarna transactions, every later comparison gets noisy.

Then reduce the Shopify side to one order identifier, one paid amount, one paid date, one refund amount if refunded, and one payment status. If your Shopify export repeats an order across multiple product lines, collapse that to one order-level record before matching to Klarna.

2. Split the Klarna settlement into order-linked rows and settlement-only rows

Not every Klarna row is supposed to match a Shopify sales row. Keep order-linked rows such as SALE, RETURN, REVERSAL, REVERSAL_MERCHANT_PROTECTION, CORRECTION, and FEE separate from settlement-only rows such as HOLDBACK, RELEASE, CHARGE, CREDIT, COMMISSION, and FEE_REFUND. If you mix them together, the comparison produces fake exceptions that are really reserve movements or payout-level adjustments.

3. Compare presence first, amounts second, payout impact third

Presence is the first test. Ask whether the order exists on both sides under the chosen key.

Then compare the order economics:

  • Shopify gross sale against Klarna SALE total
  • Shopify refunds against Klarna RETURN and REVERSAL totals
  • Klarna fee rows separately, not inside the gross sale match

When one order produced several SALE rows from split captures, total them by order_id before you compare to the Shopify sale:

Formula
=SUMIF(Klarna!$F:$F,F2,Klarna!$H:$H)

Here column F is order_id and H is the row amount. Compare that subtotal, not each capture line.

Only after those checks pass should you tie the settlement back to the payout amount. That final step is where payment reference, payout date, holdbacks, releases, and other non-order adjustments belong.

This grouped view is the level you want:

Order referenceShopify sales logKlarna settlement viewMeaning
#10482Paid 120.00SALE 120.00, FEE -3.20Order matches; fee explains part of net payout
#10483Paid 80.00, later refunded 80.00SALE 80.00, later RETURN -80.00Refund timing must be tracked separately from original sale
#10484Paid 150.00No SALE row in current settlementLikely not yet captured, not yet settled, or outside date range
#10485One order row for 200.00Two SALE rows of 120.00 and 80.00 under one order_idPartial capture; group before testing amounts

The question is not "Do these two exports look identical?" They should not. The useful question is "Can I explain every difference at the right level?"

Separate delayed settlements from real mismatches

The most expensive mistake in this workflow is treating a timing difference as a missing sale.

Klarna exposes at least three dates that matter in practice:

  • sale_date: when the order was created
  • capture_date: when the event was registered and, for SALE, when the goods were shipped and captured
  • payout_date: when Klarna initiated the payout

Shopify sales logs often center the order or payment event instead. That means a valid order can appear in Shopify on one day, in Klarna capture rows on another day, and in the payout on a later day again.

Use this decision table when a row looks missing:

PatternWhat it usually meansWhat to do
Present in Shopify, absent from Klarna SALE rows, payment still pending or not capturedThe order is not settled yetDo not mark missing; review capture status and next settlement window
Present in Shopify, absent from Klarna, but other gateways appear in the same exportThe gateway filter is wrongRebuild the Shopify subset for Klarna-only transactions
Present in Klarna SALE rows, absent from Shopify match keyThe reference mapping is wrongCheck merchant_reference1, merchant_reference2, and order-name formatting
Present as Klarna RETURN or REVERSAL in a later settlementA later refund or dispute is reducing a current payoutMatch it back to the original order and classify as delayed negative activity

This is also where month-end confusion starts. A Shopify sales log for April can contain orders whose cash impact hits a May Klarna settlement. That is not bad data. It is settlement timing.

If your unresolved list still contains a large block of negative or unmatched rows after you separate timing from presence, the next problem is often reference structure rather than missing sales. The same pattern shows up in other cross-platform comparisons, including finding unmatched sales between Shopify and another payment export, where the order reference exists but not in the same shape on both sides.

Handle the rows that should never be forced into a one-to-one order match

Some Klarna rows belong in the reconciliation but not in the order match grid.

FEE rows matter because they explain why sales do not equal the payout. But they are not evidence that a Shopify order is missing. They are deductions on top of matched order activity.

HOLDBACK and RELEASE rows matter because they move cash without representing new customer sales. A holdback reduces this payout to cover future risk. A release returns previously held funds into a later payout. Neither should be tested against a Shopify order amount.

CHARGE, CREDIT, and COMMISSION rows also belong in their own bucket. They can change the settlement total without meaning that the order-level sales comparison failed.

You also need to check Klarna's settlement type. If the merchant settlement type is NET, Klarna fees are deducted from the payout. If it is GROSS, the fees are invoiced separately, so your order match can be right even when the payout math differs from a net-settlement expectation. That single field changes the logic of the final cash tie-out.

A clean reconciliation therefore has four outputs, not one:

OutputWhat belongs there
Matched ordersSales and refunds that agree by the chosen order key
Delayed settlementsValid orders whose settlement or payout sits in a later window
Settlement-only adjustmentsFees, holdbacks, releases, charges, credits, commissions
True exceptionsRows that still fail after reference and timing checks

If those four groups are clear, you are done. If they are still blended together in one unmatched tab, the comparison is not finished yet.

When the monthly comparison stops being worth rebuilding by hand

This workflow works. It also repeats the same labor every cycle: export Shopify, export Klarna, strip out non-Klarna rows, choose the same key again, regroup split orders, separate payout adjustments, and rebuild the exception list.

That is manageable when the volume is low and the payout mix is stable. It becomes expensive when every settlement contains delayed refunds, partial captures, reserve movements, and a fresh round of reference cleanup.

At that point the bottleneck is no longer accounting judgment. It is file preparation and exception sorting, and that is the part worth taking out of the spreadsheet.