QPay Ledger Core¶
Every card QPay issues is backed by an account somewhere. The ledger is the system of record that holds those accounts, decides whether a transaction has the funds or the credit to proceed, and records the money movement afterwards. It is the component that answers "can this purchase go through?" and "what does this cardholder owe?".
QPay does not force you to build one. You can run your card programme on QPay's internal ledger, or you can keep your existing ledger and let QPay call into it. The rest of the platform — cards, products, embossing, the card network integration — is identical either way.
Two ways to run a ledger¶
| QPay's internal ledger | Your own ledger | |
|---|---|---|
| Who holds the accounts | QPay | You |
| What you implement | Nothing — you call a REST API | The eight-operation Ledger Callback API on your own infrastructure |
| Account onboarding | Ledger Accounts API | Your own systems |
| Credit invoicing, statements, finance charges | Included — see Credit Card Invoicing | Your responsibility |
| How the processor reaches it | Internally | Outbound HTTPS, TLS pinned to your certificate, HMAC-signed |
| How you select it | Leave your issuer's auth_url empty |
Set your issuer's auth_url |
The switch is a single field on your issuer record. Leave auth_url empty and the processor calls QPay's internal ledger. Set it and the processor calls yours. Clearing it again (sending an empty string) routes authorization back to the internal ledger, so the choice is reversible.
-
Use QPay's ledger
Join the internal ledger, onboard cardholders, and issue credit cards without building a ledger.
-
Bring your own ledger
Register your callback endpoints, TLS trust anchor, and signing secret, then implement the contract.
How the internal ledger is organised¶
QPay's internal ledger is split into two services with strictly separate responsibilities.
graph LR
Console[Your systems / Console]
Accounts[Ledger Accounts<br/>owns account existence]
Authorizer[Ledger Authorizer<br/>owns money movement]
Processor[QPay Processor Core]
Clearing[Clearing]
Console -->|Onboard tenants, cardholders, cards| Accounts
Accounts -->|Establishes account IDs| Authorizer
Processor -->|Authorize, cancel, reverse, inquire| Authorizer
Clearing -->|Settle, refund| Authorizer
style Accounts fill:#fff4e1
style Authorizer fill:#f0e1ff
style Processor fill:#e1f5ff
style Clearing fill:#e1ffe1
Ledger Accounts owns account existence, hierarchy, and identity: which accounts exist and who they belong to. It is what you call to join the ledger, activate a currency, onboard a cardholder, approve their KYC, and issue a card. It never moves money.
Ledger Authorizer owns balance movement. It posts debits and credits against account IDs that Ledger Accounts has already established, and it never creates or restructures an account. If it receives a transaction referencing an account that was never onboarded, it declines rather than creating one implicitly.
This is the same contract either way
The Ledger Authorizer implements exactly the Ledger Callback API that an external issuer would implement. There is no privileged internal interface — QPay's own ledger is a peer of yours.
Chart of accounts¶
Accounts are instantiated automatically as the business events that justify them occur. Nothing is created speculatively.
Per tenant, per currency¶
Created when you join the ledger and each time you activate a further currency.
| Account | Kind | Holds |
|---|---|---|
Pool_Account_Asset |
Asset | Mirrors the physical bank account holding cardholder funds — heavily regulated |
Corporate_Account_Asset |
Asset | Mirrors your own operational bank account and revenue |
Float_Inbound |
Liability | Funds deposited but not yet allocated to a cardholder |
Float_Outbound |
Liability | Funds leaving, awaiting bank confirmation |
Float_Dispute |
Liability | Funds frozen for chargeback or fraud investigation |
Revenue_Accounts |
P&L | Fees, interchange, interest |
Expense_Accounts |
P&L | Processing costs and operational losses |
Two further float accounts support credit invoicing: one for incoming invoice payments and one for credit settlement.
Per cardholder, per currency¶
| Account | Kind | Created when |
|---|---|---|
Checking_Account |
Liability | KYC is approved for that cardholder and currency — never at cardholder creation |
A cardholder record can exist with no accounts at all. A cardholder onboarded under two tenants gets two fully isolated checking accounts, never a shared one.
Per credit card application¶
Created only for card applications whose account type is CREDIT, and only once a credit limit has been approved.
| Account | Kind | Holds |
|---|---|---|
Card_Invoice_Asset |
Asset | The cardholder's real, settled debt |
Limit_Total_Granted |
Shadow | The approved credit ceiling |
Limit_Available |
Shadow | Current purchasing power |
Limit_Used |
Shadow | Amount already consumed |
Shadow accounts are off-balance-sheet. They control spending without inflating your balance sheet, which is why granting a credit limit does not create an asset.
Card applications that are not CREDIT (CHEQUE and the rest) get no new accounts — they are backed by the cardholder's existing Checking_Account.
Accounting principles¶
Double-entry. Every posting affects at least two accounts, and the sum of debits always equals the sum of credits. A posting that does not balance is rejected synchronously.
Immutability. Once a movement is committed it is never deleted, updated, or altered. A mistake is corrected by posting a new counter-transaction — a cancellation, reversal, or refund — that mathematically neutralises the first. The error stays on the ledger as a historical fact.
Isolation. Accounts are partitioned per tenant and per currency. A request for another tenant's resource returns 404, not 403, so the existence of other tenants' data is never revealed.
Currencies. Only BRL (ISO 4217 numeric 986) and USD (840) are available today. Currencies are always identified by their numeric code on the wire.
Amounts. Money is expressed in minor units as decimal strings ("100002" is R$ 1,000.02), not JSON numbers. Balances can exceed a JSON number's safe integer range, and available / used can legitimately be negative.
The Golden Limit Equation¶
At every instant, for every credit card application:
The ledger enforces this structurally. An authorization moves the same amount out of Limit_Available and into Limit_Used, so the equation never breaks.
Limit_Available is allowed to go negative. An emergency approval can be granted above the available limit, and Limit_Used still reflects the true amount consumed. The same thing happens benignly after an overpayment: a credit balance drives Limit_Used below zero and Limit_Available above the granted ceiling, and the cardholder can legitimately spend beyond their line.
How money moves during a transaction¶
Card processing is asynchronous. Authorization happens in milliseconds at the point of sale; clearing and settlement arrive days later. The two phases touch different accounts.
sequenceDiagram
actor Cardholder
participant Network as Card Network
participant Processor as QPay Processor Core
participant Ledger
Note over Cardholder,Ledger: Phase 1 — Authorization (milliseconds)
Cardholder->>Network: Presents card
Network->>Processor: ISO 8583 authorization
Processor->>Processor: Validate card, cryptograms, PIN
Processor->>Ledger: POST /authorization
Ledger->>Ledger: Credit: Limit_Used ← Limit_Available (hold)
Note over Ledger: Card_Invoice_Asset unchanged
Ledger-->>Processor: Approved / declined
Processor-->>Network: Response code
Network-->>Cardholder: Purchase approved
Note over Cardholder,Ledger: Phase 2 — Clearing & settlement (days later)
Network->>Processor: Clearing file
Processor->>Ledger: POST /settlement
Ledger->>Ledger: Debt recognised on Card_Invoice_Asset
Note over Ledger: Limit_Used and Limit_Available unchanged
Phase 1 — authorization reduces purchasing power and nothing else. For a credit product the amount moves from Limit_Available to Limit_Used as a pending hold; Card_Invoice_Asset is untouched, because no debt has been incurred yet. For a prepaid product the amount is held against the Checking_Account's available balance, leaving its ledger balance unchanged.
Phase 2 — settlement recognises the debt. For a credit product the settled amount is debited to Card_Invoice_Asset; Limit_Used and Limit_Available do not change, because they already reflected the consumption from Phase 1. For a prepaid product the Checking_Account is debited and the money clears the physical rail through the float and pool accounts.
Settlement handles partial and excess amounts natively: settling less than was authorized releases the remainder, settling more charges the difference on top.
Credit limit is restored by payment, not by settlement
This is the single most important product semantic to internalise. Settling a purchase does not give the cardholder their limit back — it converts a hold into debt. The limit returns only when the cardholder pays their invoice. A cardholder who spends their whole limit and waits for settlement has no more purchasing power than before.
Corrections after the fact¶
| Operation | When | Effect |
|---|---|---|
| Cancellation | The hold has not settled yet | Voids the hold; purchasing power returns immediately |
| Reversal | Either before or after settlement | Before: voids the hold. After: posts an independent counter-movement for what actually settled, and for a credit product also unwinds the invoice so the limit and the debt move together |
| Refund | Any time, with or without an original transaction | Posts its own amount as a new credit; never a void |
A refund, chargeback, or reversal for a charge that already appeared on a closed statement never changes that statement. It credits the current open cycle instead. See Credit Card Invoicing.
Next steps¶
-
Credit Card Invoicing
Billing cycles, statement closing, payments, finance charges, and reconciliation.
-
Ledger Accounts API
Interactive reference for tenants, cardholders, cards, and invoicing.
-
Ledger Callback API
The eight-operation contract the processor and clearing call against a ledger.
-
Terminology
Definitions for pool accounts, shadow accounts, cutoffs, finance charges, and more.