A payment processor and a general ledger are both authoritative for something, and neither is authoritative for the thing in between: which invoice a given deposit actually paid.
That gap is where a surprising amount of manual reconciliation work quietly lives.
Three authorities, one chain
| System | Authoritative for | Not authoritative for |
|---|---|---|
| Stripe / Razorpay | Charge succeeded; customer paid on hosted page | Which open invoice a batch payout covers |
| Bank statement | Cash landed | Why payer name ≠ customer legal name |
| ERP / GL | Books of record | Contract interpretation, rating, proration |
| Sonic (middle) | Invoice sent; schedule/rate truth; match + journal trail | Processing payments; filing tax returns |
Sonic's job is to keep the billing documents consistent from contract → invoice → match → journal-ready entries. It is not a processor and not the GL.
Processor path — link on the invoice, reconcile in the bank
Connected Stripe or Razorpay puts a pay-now link on invoice emails. Customer pays; webhook marks invoice paid. That is correct for AR status and stops Watchtower on that invoice.
Deposits still arrive net of fees, often batched across many charges. The amount in the bank rarely equals one invoice total. Bank reconciliation matches payouts to invoices with variance for fees and FX — not a naive one-to-one deposit search.
Test webhooks in sandbox before go-live. Missing webhook configuration is the classic "money arrived, invoice still open" failure.
Bank rec path — payer identity is fuzzy
Matching compares amount, reference, and billed party name plus contacts:
- Subscription workspace → customer catalog
- Shipment workspace → shipper catalog and shipper contacts
A payment labelled with a personal name in the bank feed may still match a company account when contacts align. Exact string match on paid_by alone creates an unmatched pile that grows every week.
Work the unmatched queue daily during close. Unmatched deposits mean you may chase someone who already paid. Unmatched invoices mean books say cash arrived when it did not.
Ledger path — journal before transport
The ERP wants debits equal credits, dated correctly, traceable to source documents. If billing hands it a number without a path back to the invoice or shipment, every audit becomes archaeology.
Sonic posts journal entries from invoices, credit notes, usage accruals, adjustments, forfeits, and true-ups — with links back to sources. Export CSV or sync through integration. Your controller owns account mapping and period sign-off.
Revenue recognition in Sonic is not ASC 606 certified. It applies methods you configure and preserves trails — it does not replace policy judgement or ERP posting controls.
The integration test that matters
The honest measure is not "did the API call succeed."
Can a controller start from a bank statement line, walk to the invoice it paid, and walk from there to the journal entry it posted — without opening three tools and asking ops what happened in March?
If not, you have two systems and two truths.
Watch out for
- Card paid ≠ bank matched. Both matter for different questions.
- Partial payments need split logic, not forced match to the largest invoice.
- GST on Razorpay receipts must agree with invoice tax lines for Indian customers reclaiming credit.
- Freight uses shipper identity in bank rec and collections — not customer catalog.
- Do not let the ERP become where proration is "fixed." Fix the schedule or adjustment document upstream.