Skip to content
Rechnungskit

Payments, matching and payout reconciliation

Updated

Rechnungskit matches every incoming payment to the right order automatically. Anything that is not clear never disappears silently; it lands as a task in the clarification list.

This page explains how matching works, what a payment's status means, how to resolve open cases and how Rechnungskit breaks your payment providers' payouts down into their parts.

Payment · matching · document
From payment to document
Incoming
Paymentfrom the payment provider, by webhook or fetch
Orderfrom the matching source, such as your shop
Matching, in this order
  1. Payment referencepassed by the shop or your application
  2. Order number in the metadatafor example custom_id for PayPal
  3. Order number in the reference textor in the payment's description
Result
Matchedinvoice is created, for goods on shipping
Awaiting syncorder not there yet, the next sync usually solves it
Needs reviewtask in the clarification list under /payments
Rechnungskit only searches the matching source you set per payment provider. Each status is explained under What the statuses mean.

How matching works

Matching tries several routes, in this order:

  1. Payment reference: the reference the shop or your application passed with the payment.
  2. Order number from the payment's metadata (for example custom_id for PayPal).
  3. Order number in the payment reference text or the payment's description.

Under Connections → Connect you see a preview per payment provider of whether matching works with your real data.

The matching source must fit your shop

Per payment provider, under Connections → Connect, you set where the order data comes from, for example Shopify, WooCommerce, Shopware or Stripe subscriptions. Rechnungskit looks for the matching order in this source, and only there.

If it says API there although your orders come from a shop, every payment searches an empty set. Nothing is found and no document is created. Because matching runs through cleanly from a technical point of view, not even an error message appears. The failure only shows in payments piling up unmatched.

That is why Rechnungskit helps in two places:

  • Warning: the connection shows a notice when the source is set to API while a shop is connected.
  • Preselection: when you add a new provider and exactly one shop is connected, that shop is preselected as the source.

If many payments stay at "Needs review" for no apparent reason, look here first. After switching, "Re-match all" catches up on the stuck payments and creates the missing documents.

Direct PayPal payments and the order number

PayPal payments only carry the order number if the shop checkout writes it into the PayPal field invoice_id (or custom_id). WooCommerce (Invoice Prefix) and Shopware do this by default. Simple PayPal buttons often don't, and then matching works through amount and email.

PayPal with Shopify

With Shopify, the field is filled in different ways. Some payments carry the real order number, while for the rest it holds an internal key of the checkout session, for which there is no order number.

For these payments, Rechnungskit asks Shopify directly for the order and reads the PayPal transaction number stored there. It links order and payment unambiguously. So matching works through the transaction number, not estimated from amount and time. You don't need to set anything up; the existing Shopify connection is enough.

PayPal through another provider

PayPal runs through Authoritative source What happens with the direct PayPal connection
Mollie or Stripe the Mollie or Stripe connection It would record the same payments twice. Rechnungskit detects the duplicates and automatically classifies them as not a sale. Recommendation: disconnect the direct connection
Unzer the Unzer connection Automatic duplicate detection is technically not possible, because Unzer does not return the PayPal transaction number. Rechnungskit warns and also recommends disconnecting the direct connection

Unzer payments and the order number

Unzer payments only carry the order number if the shop's Unzer module passes it as the order ID. The Unzer modules for Shopware and WooCommerce do this by default; for other shops, check the module configuration. In addition, the shop must be selected as the matching source of the Unzer connection.

The 4-hour sync covers Unzer too. Known payments from the last 48 hours are fetched again, and recent orders without an Unzer payment are queried directly at Unzer.

What the statuses mean

Every payment under /payments carries exactly one status.

Status Meaning What you do
Matched The payment is assigned to an order. Nothing
Needs review No clear order, contract or payment reference was found. Assign it manually, trigger "Re-match" again, or file it as "Not a sale"
Awaiting sync The payment is there, the related order is not yet. Usually nothing, the next sync with the shop solves this by itself
Refund A repayment to the customer. If needed, the related correction invoice has already been created. Nothing
Not a sale Deliberately filed as not revenue-relevant, such as transfers, card verifications of €0.00 or transitory items. Nothing
Historic The payment dates from before your Belegstart (the date from which Rechnungskit issues your invoices). Nothing, see below
VAT ID check running / decision needed The qualified check of the customer's VAT ID with the Federal Central Tax Office (BZSt) is still pending or needs your decision before the invoice is created. Decide when it says "decision needed"
Statuses under /payments
Where you need to act and where not
Done
Matched, Refund, Not a sale, Historic
For younothing to do
Waiting
Awaiting sync, VAT ID check running
For youusually solves itself
Your turn
Needs review, decision needed
For youassign or decide
The meaning of each status is in the table above.

Matched: invoice or "After shipping"

  • If the Invoice column shows a number, the invoice has been created.
  • If it says "After shipping", the invoice is only created on shipping (date of supply = shipping date). Whether it has shipped you see on the order. The order number in the row leads straight there.

In both cases there is nothing to do.

Historic

The payment dates from BEFORE your Belegstart. Your previous system already invoiced it. Rechnungskit only loads it so the payouts reconcile: no document, no task, nothing to do.

You can also file an unresolved payment this way yourself, through the payment's menu → Ignore or the link in the assign dialog. That is correct if its order dates from before the system start and was invoiced in the previous system. The task closes, the decision is logged and can be reversed with "Reopen".

When something does not fit

Every open case appears as a task under /payments. Chargebacks and payout differences land there too.

Payment without assignment

Payments without an assignable order appear as the task "Zahlung ohne Zuordnung" (payment without assignment). There you assign it manually or clear up the case.

The most common reason: the payment was faster than the shop sync, and the order simply is not there yet. For WooCommerce:

  1. Type the order number in the assign dialog.
  2. Click "Bestellung jetzt aus dem Shop laden" (load order from the shop now), and the order arrives right away.
  3. Confirm the assignment as usual with "Create invoice".

Webhook connection silent

If your shop reports orders with a payment provider from which Rechnungskit has not received a single payment since connecting (neither webhook nor fetch), the task "Webhook-Verbindung still" (webhook connection silent) appears. It contains the specific check. For PayPal, for example: enable "Transaction Search" on the REST app, and the app must belong to the account where the shop payments land.

The invoice cannot be created

If something is missing for the invoice, such as a VAT rate, complete recipient details or your company details, the payment is held. The task links directly to the setting that is missing.

Requesting buyer details

For incomplete recipient details, you get the address straight from the buyer.

  1. "Request details" on the task sends them an email with a link, with you as the sender. Through the link they add their billing address without logging in.
  2. If no email address is known, copy the link with "Copy link" and send it yourself, by chat for example.
  3. As soon as the buyer submits the details, the document is created automatically and the task closes.

The link stays valid. Clicking "Request details" again sends the same link once more. The row shows "Requested on" or "Buyer details received on".

Incomplete recipient details
From the buyer link to the document
  1. Task createdPayment is heldno document with an incomplete address
  2. Request detailsEmail with a link to the buyerin your name, or automatically by document rule
  3. Buyer repliesAddress added, no login"Buyer details received on"
  4. Right afterDocument created automaticallythe task closes
If the buyer does not reply, the payment stays held and the task stays open. Rechnungskit does not remind the buyer on its own.

Send automatically: under Settings, Document rules, you can have the buyer link sent automatically. The request then goes out in your name as soon as the task is created and the buyer's email address is known. This happens once per payment, never in test mode. The task stays visible until the buyer has replied.

No reply: if the buyer does not reply, nothing happens on its own. The payment stays held, no document is created, the task stays open and appears in the task reminder email. Rechnungskit does not remind the buyer automatically. You can resend the link at any time or add the address yourself in the shop or the Stripe customer profile. The document is then created at the next matching run.

Safety net for lost webhooks

In case a webhook got lost, a safety net syncs with the source regularly:

Source Sync
Shopify every 4 hours
WooCommerce every 4 hours, 24-hour window, fully paginated
Shopify Payments every 4 hours
Shopware fetched every 15 minutes anyway

For goods, the invoice is only created on shipping (date of supply). For shop orders it therefore depends on the status change "Completed" also arriving.

Task reminder by email

You don't have to keep an eye on open tasks yourself. Rechnungskit sends the account owners an overview by email, grouped by project, with the count and the age of the oldest task. The email only comes if something is actually open.

Setting When the email comes
Weekly (default) Fridays at 8 a.m.
Daily every morning at 8 a.m.
Off never

You change this under Settings → "Task reminder by email". The choice applies to the whole account and saves immediately. Every reminder email names its frequency and links to this setting.

Independently of this, Rechnungskit emails you immediately when an invoice is held because a decision is needed, after a failed VAT ID check for example. This immediate email cannot be switched off.

Payout reconciliation

Under /payouts, Rechnungskit breaks your providers' payouts down into their parts, so the bookkeeping adds up. Every item (payment, refund, fee) is shown separately. Fees are never netted against revenue.

Example · made-up amounts
One payout, broken down into its items
Payout from the providerAmount
12 payments+€1,250.00 each matched to an order
1 refund−€59.90 with a correction invoice
Fees−€18.74 the provider's real cent amounts
Correction item−€0.01 rounding per the provider's report
Payout€1,171.35 sum of the items, reconciles to the cent
When it does not add upWhat follows
Payment missingfetched automatically for Stripe and Mollie
Item without paymenttask "items unresolved"
Difference remainstask to clear up, never rounded away
Accept as resolvedwith a reason, immutable in the audit log
Fees always stand as their own item and are never netted against revenue. An accepted difference is lifted as soon as the payout actually reconciles.

How payouts come in

Provider How Rechnungskit gets the payout
Stripe automatically per payout via webhook
Mollie daily through the Settlements API (organization access token required)
PayPal daily through the transaction history, withdrawals to the bank account as a transfer
Shopify Payments automatically through the shop connection
Unzer no payout interface, fees come from the monthly ETN CSV upload
Klarna daily through the Settlements API (no webhooks, Rechnungskit fetches actively), fee per transaction included

When the fee per payment appears

The fee per payment appears as soon as the provider delivers it. Until then the payment list shows "folgt" (to follow).

When Provider
right away with the payment PayPal
with the sync around the payout Mollie, Stripe, GoCardless, Klarna, Shopify Payments
only with the monthly ETN import Unzer

Missing payments and differences

If the payment for an item is missing, typically for sales before the Belegstart or after a missed webhook, the reconciliation fetches it automatically from the provider for Stripe and Mollie. This happens daily and on "Re-match all". Payments before the Belegstart appear as "Historic" and create no document.

If a difference still remains, you can accept it as resolved with a reason. The decision is recorded immutably in the audit log and is lifted as soon as the payout actually reconciles. How the DATEV export books a difference is explained under Reconciliation difference.

Unresolved items in a payout

Not only the total is checked, but every single item. Unresolved means no payment can be found for this item. The task "items unresolved" therefore appears even when the payout reconciles to the cent.

Items without a payment
What Rechnungskit resolves itself and what lands with you
Refund with Shopify PaymentsResolved through the order Shopify includes, if it has exactly one payment from the provider
Automatic
Refund for an order before the BelegstartThe payment still ran in the previous system
Visible, no task
ChargebackA separate process with its own clarification
Own clarification
Original payment missingFirst "Re-match all", then assign by hand on the payout
Task

Rechnungskit resolves two cases itself:

  • Refunds with Shopify Payments: Shopify books them under the transaction number of the refund, while the correction invoice hangs on the payment of the original order. Because Shopify includes the order on every booking, Rechnungskit resolves the item through it, provided that order has exactly one payment from the provider. Chargebacks are deliberately left out, because they are a separate process with their own clarification.
  • Time before the Belegstart: there are often weeks between purchase and refund. A current payout therefore sometimes contains refunds for orders that were still invoiced in the previous system, and Rechnungskit never saw their payment. Such items stay visible but do not keep a task open.

If a task remains, something really is missing, usually the original payment for a refunded order. Then "Re-match all" under /payments helps. If the item is still open afterwards, you assign it by hand on the payout.

Rounding differences in fees and payouts

Payment providers calculate fees per transaction and internally with fractions of a cent. Mollie and Unzer deliver up to four decimal places. Only whole cents reach the bank account, though. That is why the providers' own settlement reports contain correction items such as rounding differences.

How Rechnungskit handles this:

  • Real amounts: Rechnungskit never recalculates fees as a percentage; it takes the provider's real cent amounts per transaction. Internally only whole cents are used, no floating-point numbers.
  • Round once: for provider items with decimal places (Mollie costs, for example), the total is formed exactly and rounded only once. The remainder is distributed across the items by the largest remainder method, so the sum of the items always equals the real total. Rechnungskit therefore creates no rounding differences of its own.
  • Provider corrections: correction items (rounding, fee corrections, tax on fees, withholdings) are recorded as separate items of the payout.
  • Never rounded away: if a payout still does not reconcile to the cent, the difference is shown as a task to clear up. A difference points to a missing, duplicate or wrongly valued transaction.

Belegstart and old data

Rechnungskit only creates documents for sales from the Belegstart onward. You set it once when going live (Go live page): immediately or scheduled for a cut-over date, such as the first of the month for a system switch. In test mode, the day of setup applies. Under Settings, Document rules, you see the date, but it cannot be changed there.

Example · Belegstart on October 1
The order date decides
  1. Up to 30 days beforePayments are loadedas "Historic", so payouts reconcile
  2. September 30Order in the shopinvoiced by your previous system, even if paid or shipped in October
  3. October 1Belegstartset once when going live
  4. From then onDocuments from Rechnungskitfor every new order
Rechnungskit does not invoice retroactively. A second, non-identical invoice for the same supply can trigger an additional tax liability.

Older payments

Older payments from the last 30 days are still loaded. They appear as "Historic" in the payment list and make sure that payouts reconcile that partly fall before the switch.

They are not invoiced, because the previous system already issued invoices for them. A second, non-identical invoice for the same supply can mean you owe the tax shown on it in addition (§ 14c Abs. 1 UStG, Abschn. 14c.1 Abs. 4 Satz 5 UStAE).

The order date decides

  • An order from September 30 that is only paid or shipped in October is still invoiced by your previous system. Rechnungskit files its payment as "Historic".
  • Shops connected through the API send the order date in the field orderedAt. If it is missing, the time the order reached Rechnungskit counts.
  • If you assign such a payment to an order yourself, a document is still created.

Rechnungskit does not invoice retroactively: set the cut-over date, and from then on everything goes through Rechnungskit. If you need an earlier Belegstart because no invoice exists yet for those sales, contact support.

Limits, stated plainly

  • No bank reconciliation: bank account reconciliation (FinTS) is not part of the product. The basis is the data from the payment providers and the shop.
  • €0.00: payments of €0.00 are automatically classified as not a sale and create no document.
  • Foreign currency: invoices are created for EUR, CHF, USD, GBP, SEK, DKK, NOK, PLN and CZK. The EUR tax amount is determined with the project's rate method (default for new projects: the BMF monthly rate of the month of supply, with the ECB daily rate as a provisional rate until it is published) and frozen on the document together with the rate date. Other currencies (JPY, for example) and payments whose currency does not match the order create no document but a task to clear up.

Notice on the AWV reporting obligation (Bundesbank)

If a single cross-border payment over €50,000 is matched to an order (German seller, foreign payer), Rechnungskit shows a notice on the Payments page. As a resident, you may have to report it to the Deutsche Bundesbank: a Z4 report under §§ 67 ff. AWV (the German Foreign Trade and Payments Ordinance), due by the 7th working day of the following month (§ 71 Abs. 6 AWV).

To put this in context:

  • Statistics only: it is purely a statistical report on foreign trade, not a tax obligation. It changes nothing about your invoice, the VAT or the DATEV export.
  • Per payment: the €50,000 limit applies since the reporting month January 2025 (previously €12,500, according to the Bundesbank) and is checked per individual payment, not as a monthly total (§ 67 Abs. 2 Nr. 1 AWV).
  • Goods exports: payments for the export or shipment of goods are exempt (§ 67 Abs. 2 Nr. 2 AWV). The notice still appears, because Rechnungskit cannot reliably classify the purpose of the payment.
  • Not the ZM: don't confuse it with the €50,000 limit of the EC sales list (ZM). That is a different return to the Federal Central Tax Office through ELSTER, and it only shares the number with the AWV notice.
  • You file the report: Rechnungskit only points this out and does not file the Z4 report. The report itself goes through the Bundesbank's reporting portal. The task in the clarification area can be ticked off once done.

Where to find it in the app

Rechnungskit is not a tax advisory or law firm. This article explains general principles and does not replace advice from a tax advisor (Steuerberater, § 5 StBerG) or a lawyer (§ 3 RDG). Rechnungskit is built for businesses based in Germany and prepares documents, tax rates and bookings automatically. How your specific case is treated remains your decision, ideally together with your tax advisor or a lawyer.

de en