# Invoicing

URL: /systems/finance/invoicing · Id: `capability:invoicing`

> Invoicing bills a Customer with a numbered Invoice, payment terms and a hosted payment page, then collects, reminds or voids it.

Invoicing bills a [Customer](/business/nouns/customer) with a numbered [Invoice](/business/nouns/invoice), then collects it by charging a saved card or by waiting for a bank transfer on terms. Refunds and voids correct an Invoice; nothing deletes one.

## Contract
| Status | What it means | Moved by |
| --- | --- | --- |
| `draft` | Lines still change, and nothing is owed. | [Subscription.renew](/business/nouns/subscription/renew) drafts each period’s Invoice |
| `open` | Numbered, frozen and presented to the Customer. | [Invoice.bill](/business/nouns/invoice/bill) |
| `paid` | Collected, with `Invoice.paidAt` set. | [Invoice.collect](/business/nouns/invoice/collect) |
| `void` | Canceled unpaid, and kept forever. | [Invoice.void](/business/nouns/invoice/void) |

`Invoice.collection` sets how an Invoice is paid.

| How | `charge` | `send` |
| --- | --- | --- |
| Suits | Buyers who pay by card | Buyers on terms, whose `Invoice.purchaseOrder` must print on it |
| Due | On issue | `Invoice.terms` days after issue, such as 30 |
| Paid by | `Invoice.collect` charging the default [Payment Source](/business/nouns/payment-source) | A bank transfer into the [Startup](/business/nouns/startup)’s Stripe balance, or a card on `Invoice.payUrl` |
| When unpaid | [Dunning](/workflows/processes/billing/dunning) retries on its schedule | [Invoice reminders](/workflows/processes/billing/invoice-reminders) write a week before due and the day after, with no retry |
| Paid when | The charge succeeds | The transfer reconciles and `Invoice.collected` fires |

| Rule | Detail |
| --- | --- |
| Number | `Invoice.number` runs in sequence per Startup and is never reused, voided Invoices included. |
| Lines | `Invoice.lines` freezes at `Invoice.bill`. A correction voids and bills again, or refunds part of a paid Invoice. |
| Purchase order | `Invoice.purchaseOrder` prints on the Invoice; an accepted [Quote](/business/nouns/quote) carries it in `Quote.paymentTerms`. |
| Receipt | `Invoice.pdf` names the seller of record and lives on the Startup’s own [Domain](/business/nouns/domain). |
| Tax | Stripe Tax computes it at `Invoice.bill` from `Customer.billingAddress` and `Customer.taxIds`. |
| Credits | [CreditGrant.apply](/business/nouns/credit-grant/apply) pays metered lines from [Credit Grants](/business/nouns/credit-grant) as the Invoice finalizes. |
| Refund | [Invoice.refund](/business/nouns/invoice/refund) returns all, part, or the unused share of the [Period](/business/nouns/period) to the original payment, never to a balance. |
| Refund gates | `Invoice.refund` waits its delay window and refuses while a [Dispute](/business/nouns/dispute) is open. Above the [Billing Specialist](/agents/finance/billing-specialist)’s [Limit](/business/nouns/limit), it opens an [Approval](/business/nouns/approval) for the [Finance Lead](/agents/finance/finance-lead). |

## Verbs
| Verb | Object | Event |
| --- | --- | --- |
| [Invoice.bill](/business/nouns/invoice/bill) | [Invoice](/business/nouns/invoice) | [`Invoice.billed`](/business/events/Invoice.billed) |
| [Invoice.collect](/business/nouns/invoice/collect) | [Invoice](/business/nouns/invoice) | [`Invoice.collected`](/business/events/Invoice.collected) |
| [Invoice.void](/business/nouns/invoice/void) | [Invoice](/business/nouns/invoice) | [`Invoice.voided`](/business/events/Invoice.voided) |
| [Invoice.refund](/business/nouns/invoice/refund) | [Invoice](/business/nouns/invoice) | [`Invoice.refunded`](/business/events/Invoice.refunded) |

## Interfaces
- [API](/code/api/reference)
- [SDK](/code/sdk/reference)
- [CLI](/code/cli/reference)
- [MCP](/code/mcp/reference)
- Webhooks

## Example
```ts
import { $ } from 'startup-builder'

// ledgerlark.com renews a firm's $6,000 annual plan. The firm's accepted Quote set send collection,
// net-30 terms and purchase order PO-88412, so the renewal drafted invoice_1 with all three.
await $.Invoice.bill({ invoice: 'invoice_1' })

// The firm asks to bill its second entity. Void the first and bill the corrected draft; both stay on record.
await $.Invoice.void({ invoice: 'invoice_1', reason: 'Billed to the wrong entity.' })
await $.Invoice.update({ id: 'invoice_2', collection: 'send', terms: 30, purchaseOrder: 'PO-88412' })
await $.Invoice.bill({ invoice: 'invoice_2' })

// Day 27: the bank transfer reconciles in the Stripe balance, and Invoice.collected fires.
const invoices = await $.Invoice.list({ where: "status = 'paid'" })

// Month 3: the firm drops its $1,000 reporting add-on. Refund the 9 unused months to the original payment.
await $.Invoice.refund({ invoice: 'invoice_2', amount: { amount: 750, currency: 'USD' }, reason: 'Reporting add-on removed after month 3.' })
```