User guide
Credit Notes & Client Billing — Guide
Looking for what it does rather than how to use it? Read the Credit notes and statements overview .
Audience: MSP staff who issue and apply credits, organization admins who read their own billing position, and platform administrators who set credit limits.
What it is
A credit note is an accounts-receivable credit that reduces what a customer owes. Solidlio records each credit, lets MSP staff apply it against one or more invoices, keeps a per-invoice ledger of every application, and reflects the result in the customer’s balance, statements and transaction history.
Separately, Solidlio records credit lines — how much a client may owe at once and on what terms. Credit lines and credit notes are different things and are covered separately below.
Concepts
The three balances — read this first
Three modules in the API client are named “credit”. They are three unrelated tables, not three views of one balance. Nothing reconciles them against each other, and nothing is supposed to.
| Balance | Table | Means | Who sets it | Ledger? |
|---|---|---|---|---|
CreditNote.remainingCredit | credit_notes | Unapplied value of an A/R credit memo owed back to a customer | QuickBooks sync | Yes — credit_note_applications |
ClientCreditAccount.availableCredit | client_credit_accounts | An MSP→client net-terms credit line | MSP staff | No |
MspCreditAccount.availableCredit | msp_credit_accounts | A platform→MSP credit line | Platform admin | Yes — MspCreditTransaction |
Two consequences you need to know:
- The MSP→client credit line is advisory. It is recorded, displayed and editable, and it is what an MSP tells a client their terms are. Adjust it by hand, or treat it as documentation of agreed terms.
- Only a credit note moves an invoice balance. A credit line never does.
Credit note
| Field | Meaning |
|---|---|
number | Sequential identifier |
organizationId | The organization being credited |
currency | The note’s currency. A credit can only be applied to an invoice in the same currency |
total | Face value |
remainingCredit | Unapplied balance still available |
status | ISSUED → APPLIED (see §2.4), plus DRAFT and VOID, which nothing currently writes |
invoiceId | The invoice the note was raised against, if any. Not the apply history — see applications |
applications | One CreditNoteApplication row per draw: amount, target invoice, actor, timestamp |
Credit note application
Each time a credit is applied to an invoice, Solidlio writes one application row:
| Field | Meaning |
|---|---|
amount | The value drawn for this specific invoice |
invoiceId | The invoice credited |
currency | Denormalised from the note |
appliedBy | The person who applied it |
appliedAt | When |
reversedAt / reversedBy | Set when the application is undone |
Applications are reversed, never deleted. The database foreign keys are RESTRICT, so a credit note that has been applied cannot be deleted while its history exists. Reversed rows stay in place and are excluded from balance arithmetic.
Lifecycle
QuickBooks credit-memo sync
│
▼
ISSUED ──── apply (partial) ──► ISSUED (remainingCredit reduced)
│ │
│ │ apply the remainder
▼ ▼
APPLIED ◄─────────────────────────┘ (remainingCredit == 0)
│
│ reverse an application
▼
ISSUED (credit restored)
There is no PARTIALLY_APPLIED status. A partly-applied note stays ISSUED with a reduced remainingCredit; read remainingCredit, not status, to know what is left.
See §9.
Accounts and organizations
A managed client is a separate Account, not an organization inside the MSP’s account. Two different scopes follow from that, and mixing them up is a real failure mode:
| Scope | Applies to | Behaviour |
|---|---|---|
billingScope | Client-owned transactional rows — credit notes, invoices | Widens MSP staff to their own account plus every client account they service |
accountScope | The MSP’s own configuration and its client credit lines | The caller’s own account only |
Credit notes use billingScope: an MSP applying a credit for a client it services is a legitimate cross-account action. Client credit lines stay on accountScope, because a credit line is the providing MSP’s own commercial position and must not be visible to a co-managing MSP.
Roles and permissions
Role hierarchy: platform administrator > MSP administrator > MSP technician > organization administrator > power user > CUSTOMER`.
| Action | platform administrator | MSP administrator | MSP technician | organization administrator | power user | CUSTOMER |
|---|---|---|---|---|---|---|
| List / read credit notes, read application history | ● | ● | ● | ● | — | — |
| Apply a credit note to an invoice | ● | ● | ● | — | — | — |
| Reverse a credit-note application | ● | ● | ● | — | — | — |
| Read / create / edit a client credit line | ● | ● | ● | — | — | — |
| Read own org billing summary, statements, history | ● | ● | ● | ● | — | — |
| Change auto-pay settings | ● | ● | ● | ● | — | — |
| Set an MSP credit line (platform→MSP) | ● | — | — | — | — | — |
| Finalize escalation billing | ● | ● | ● | — | — | — |
Two deliberate splits:
- Reading a credit note is not the same as applying one. An organization that has been granted a credit can see it — it is that customer’s own financial document. Writing off a receivable is the MSP’s decision, so
POST /applyandPOST /reversecarry a MSP technician floor inside the router while the three read routes are mounted at organization administrator. - organization administrator, not unfloored. power user and
CUSTOMERcannot read credit notes. All three reads arebillingScoped regardless, so the floor changes who may ask, never which rows return.
Walkthroughs
Apply a credit note to an invoice (MSP staff)
Credit notes arrive from the QuickBooks credit-memo sync. Once present:
- Pick a target invoice belonging to the same organization and the same currency.
- The response reports both sides:
appliedAmount,creditNoteRemaining,creditNoteStatus,invoicePaidAmount,invoiceBalance,invoiceStatus, and theapplicationIdyou need to reverse it later.
A partial application leaves the note ISSUED with a reduced remainingCredit, so you can apply the rest to a different invoice. Each application is recorded separately.
Reverse an application
- The credit returns to the note (an exhausted
APPLIEDnote becomesISSUEDagain), and the invoice’s balance is restored.
A VOID note stays VOID after a reversal — voiding is a deliberate act and a reversal must not undo it. Reversing twice returns 409 ALREADY_REVERSED.
Set up a client credit line (MSP staff)
- Open the client. If no credit line exists, the panel shows Set Up Credit Account.
- That creates the account with a zero limit and Net 30 terms.
- Set Credit Limit, Net Terms, Payment History and Credit Status, then save.
Utilization shown on the panel is derived as creditLimit − availableCredit. Because nothing draws the line down automatically (§2.1), that figure only moves when someone edits it.
Read your billing position (organization admin)
- Billing shows the credit line, outstanding and overdue balances, the next invoice due, and auto-pay settings.
- Billing Statements → Monthly Statements shows the reconciling series described in §5.
- Billing Statements → Transaction History shows invoices, payments and credit notes in one feed. Anything that reduces the balance carries a negative amount.
Make escalation work billable (platform admin)
- The assignment must be
COMPLETEDorPENDING_REVIEWand not already finalized. - Press Finalize Billing.
- Solidlio stamps
finalAmountCentson the assignment and creates two records: aPlatformFeecharged to the requesting account, and aServiceOrdercarrying the revenue.
Finalizing twice returns 409 with Billing has already been finalized for this assignment — it will not charge twice.
Statements: how they reconcile
closingBalance = openingBalance + charges − payments − credits
| Figure | Source |
|---|---|
openingBalance | The previous month’s closingBalance |
charges | Invoices issued that month, at face value |
payments | Payments received that month, net of refunds |
credits | Credit notes issued that month; VOID notes excluded |
closingBalance | The identity above |
Two details that make the series tie out end to end rather than starting from an implied zero:
- Pre-window seed. The oldest month’s
openingBalanceis computed from every invoice, payment and credit note dated before the requested window, not assumed to be zero. - Chaining. Months are computed oldest-first so each opening is literally the previous closing, then returned newest-first for display.
Months are grouped on issueDate, not row-creation time: an invoice drafted in March and issued in April belongs on the April statement, which is the one the customer is asked to pay.
?months= is clamped to 1–24 (default 12) at both ends.
How an invoice’s paid amount is calculated
Invoice.paidAmount is derived, never incremented:
paidAmount =
SUM(payment.amount − payment.refundedAmount)
over payments WHERE status IN (SUCCEEDED, PARTIALLY_REFUNDED, REFUNDED)
+ SUM(application.amount)
over credit_note_applications WHERE invoiceId = ? AND reversedAt IS NULL
Three properties follow:
- A credit and a payment cannot erase each other. Both are terms in one sum, so applying a credit and then taking a card payment produces the correct total regardless of order.
- A refund is subtracted by amount, not filtered out by status. A fully refunded payment contributes exactly zero; a $10 refund against a $100 payment leaves $90, not $0. Over-refunds are clamped per payment, so an over-refund on one payment can never consume another payment’s money.
Status is only recomputed for SENT, VIEWED, PARTIAL, PAID and OVERDUE. DRAFT and VOID are left alone — a refund against a cancelled invoice must not silently re-issue it. An OVERDUE invoice with a balance remaining stays OVERDUE; partial payment does not make it current again.
Why the formula exists twice
It has already earned its keep: it caught the two implementations disagreeing on whether an over-refund clamps per payment or on the aggregate, on its first run.
Configuration
| Setting | Where | Effect if unset |
|---|---|---|
ClientCreditAccount.creditLimit | MSP → Clients → <client> → Credit Account | No credit line; the org billing summary reports NONE |
ClientCreditAccount.netTermsDays | Same panel | Defaults to 30 |
ClientCreditAccount.status | Same panel | Defaults to ACTIVE |
Organization.autoPayEnabled / method / max | Org → Billing | Auto-pay off |
Organization.sellCurrency | Org settings | Falls back to the account’s defaultCurrency, then CAD |
| QuickBooks connection | Integrations → QuickBooks | No credit notes enter the system at all (§9) |
Credit limits and available credit are stored as dollars (Decimal(12,2)), not cents.
Plan tiers
Credit notes and client billing carry no plan gate. Every capability in this guide is included in every plan, including Free. The only money-related plan gate in the catalogue is limits.maxContracts, which belongs to Contracts.
Limits and known behaviour
Say these out loud to a prospect rather than discovering them in week two.
- Without a QuickBooks connection this feature has no input.
- The MSP→client credit line is advisory. Nothing draws it down and nothing blocks an order that exceeds it (§2.1).
- Credits cannot cross currencies. Applying a note to an invoice in a different currency is refused rather than converted — a conversion would need an FX rate and a rate date this domain does not hold. Change one document’s currency or issue a note in the invoice’s currency.
CreditNote.numberis a single global sequence, shared across tenants, so a customer’s credit notes are not contiguous. Retained deliberately: renumbering issued financial documents would break records customers already hold.CreditNote.invoiceIdis not the apply history. It records only the first target. Readapplications.- Credit notes do not have a PDF or a delivery path. They are visible in the API and in the org billing statements; nothing emails them.
- Statement figures are presentation values. They are computed in floating point and rounded to cents.
- The transaction feed’s page window fetches
page × limitrows from each of the three streams. Counts are exact; very deep pages read proportionally more.
Troubleshooting
Messages below are the strings the service actually returns.
| Symptom / message | Cause | Fix |
|---|---|---|
Credit note is in USD but the invoice is in CAD; a credit can only be applied to an invoice in the same currency (400) | Currencies differ; no conversion is performed | Apply to an invoice in the note’s currency |
Amount exceeds the credit note's remaining credit (400 INSUFFICIENT_CREDIT) | Note is partly or fully used | Read remainingCredit; status stays ISSUED when partly applied |
Amount exceeds the invoice's outstanding balance (400 OVER_APPLY) | Would over-pay the invoice | Apply the balance only, then apply the rest elsewhere |
Credit note is void (400) | Note was voided outside Solidlio | Resync from QuickBooks or use a different note |
Amount must be positive (400) | Zero or negative amount | Use reverse, not a negative apply |
Credit note application is already reversed (409) | Double reversal | Re-read the ledger; the first reversal already restored the credit |
Credit note not found on an id you can see in QuickBooks | Outside your tenant boundary, or the QB customer is not mapped to an organization | Map the QuickBooks customer, then resync |
| Credit note list is empty for an org admin | You are power user or CUSTOMER; the floor is organization administrator | Use an org-admin account |
Organization not found when setting up a client credit line | The organization is not in an account you service | Confirm the management link is ACTIVE |
Credit account already exists for this organization-account pair (409) | One credit line per organization per providing MSP | Edit the existing line |
Cannot delete credit account with outstanding balance (400) | creditLimit − availableCredit > 0 | Restore available credit to the limit first |
Assignment must be in COMPLETED or PENDING_REVIEW status to finalize billing (400) | Wrong lifecycle state | Submit for review first |
Billing has already been finalized for this assignment (409) | Finalize is not repeatable, by design | Nothing to do — the fee and service order already exist |
Provider rate card not found (404) | The escalation provider has no rate card | Configure the provider’s rate card |
| Escalation billing summary shows zero | It aggregates finalized assignments only | Finalize the assignments (§4.5) |
| Statement closing balance looks wrong | Check openingBalance + charges − payments − credits; credits and refund netting are included | If the identity holds, the inputs are what to check |
Verification
| What | Result |
|---|---|
| Credit-note suites | 69 tests passing across 3 files |
| Full area suite | 211 passing, 1 todo (automatic draw-down), across 14 files |
The single todo is automatic credit draw-down (§2.1), left deliberately unimplemented and deliberately absent from the datasheet.