Skip to content

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.

    Use the QPay Ledger

  • Bring your own ledger


    Register your callback endpoints, TLS trust anchor, and signing secret, then implement the contract.

    Connect Your Own Ledger

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:

Limit_Total_Granted = Limit_Available + Limit_Used

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.

    Learn more

  • Ledger Accounts API


    Interactive reference for tenants, cardholders, cards, and invoicing.

    API docs

  • Ledger Callback API


    The eight-operation contract the processor and clearing call against a ledger.

    API docs

  • Terminology


    Definitions for pool accounts, shadow accounts, cutoffs, finance charges, and more.

    Glossary