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 referencepassed by the shop or your application
- Order number in the metadatafor example custom_id for PayPal
- Order number in the reference textor in the payment's description
How matching works
Matching tries several routes, in this order:
- Payment reference: the reference the shop or your application passed with the payment.
- Order number from the payment's metadata (for example custom_id for PayPal).
- 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" |
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:
- Type the order number in the assign dialog.
- Click "Bestellung jetzt aus dem Shop laden" (load order from the shop now), and the order arrives right away.
- 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.
- "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.
- If no email address is known, copy the link with "Copy link" and send it yourself, by chat for example.
- 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".
- Task createdPayment is heldno document with an incomplete address
- Request detailsEmail with a link to the buyerin your name, or automatically by document rule
- Buyer repliesAddress added, no login"Buyer details received on"
- Right afterDocument created automaticallythe task closes
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.
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.
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.
- Up to 30 days beforePayments are loadedas "Historic", so payouts reconcile
- September 30Order in the shopinvoiced by your previous system, even if paid or shipped in October
- October 1Belegstartset once when going live
- From then onDocuments from Rechnungskitfor every new order
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.