# Invoice

URL: /business/nouns/invoice · Id: `noun:invoice`

> An Invoice is what a Customer owes for one or more Offers over one billing period.

An Invoice is what a [Customer](/business/nouns/customer) owes for one or more [Offers](/business/nouns/offer) over one billing period.

## Properties
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `total` | `money` | Yes | The amount due. |
| `due` | `date` | Yes | When payment is due. |
| `paidAt` | `datetime` | No | When it was paid. |
| `status` | `string` | No | One of `draft`, `open`, `paid`, `void`, or `uncollectible`. |
| `collection` | `string` | No | `charge` charges the saved payment method; `send` sends the Invoice and waits for a transfer. `charge` by default. |
| `terms` | `integer` | No | Days from issue until a `send` Invoice is due, such as 30; sets `due`. |
| `purchaseOrder` | `string` | No | The Customer’s purchase order number, printed on the Invoice. |
| `refunded` | `money` | No | The total returned to the Customer, from zero up to the amount paid. |
| `number` | `string` | No | The Invoice number, sequential per Startup and never reused, voided Invoices included. |
| `lines` | `json` | No | Each Offer billed: its quantity, Period and amount, with any Coupon or Credit Grant applied. |
| `pdf` | `url` | No | The Invoice, or its receipt once paid, as a PDF on the Startup’s Domain that names the seller of record. |
| `payUrl` | `url` | No | The page on the Startup’s Domain where the Customer pays it by card or bank transfer. |

## Object
```json
{
  "$id": "https://api.sb/patentpad.com/invoices/invoice_1",
  "$type": "Invoice",
  "total": {
    "amount": 499,
    "currency": "USD"
  },
  "due": "2026-10-22",
  "paidAt": "2026-10-22T12:00:00Z",
  "status": "draft",
  "collection": "charge",
  "terms": 1,
  "purchaseOrder": "PO-48213",
  "refunded": {
    "amount": 499,
    "currency": "USD"
  },
  "number": "LEDG-0042",
  "lines": {},
  "pdf": "https://patentpad.com",
  "payUrl": "https://patentpad.com"
}
```

## Relationships
- <a id="rel-billed-for"></a>An Invoice **is billed for** one [Subscription](/business/nouns/subscription): the Invoices the [Subscription](/business/nouns/subscription) issues, one for each period it renews. `billedFor`, inverse [`bills`](/business/nouns/subscription#rel-bills).
- <a id="rel-charges"></a>An Invoice **charges** one [Customer](/business/nouns/customer): each Invoice is owed by one [Customer](/business/nouns/customer). `charges`, inverse [`invoices`](/business/nouns/customer#rel-invoices).
- <a id="rel-credit-grants"></a>An Invoice **has** many [Credit Grants](/business/nouns/credit-grant): the Invoices the grant paid toward when they finalized. `creditGrants`, inverse [`offsets`](/business/nouns/credit-grant#rel-offsets).

## Lifecycle

| State | Meaning | Moves to |
| --- | --- | --- |
| `draft` (first) | Its lines can still change, and the Customer has not seen it. | `open` by [Invoice.bill](/business/nouns/invoice/bill); `void` by [Invoice.void](/business/nouns/invoice/void) |
| `open` | Finalized and presented to the Customer, its lines frozen. | `paid` by [Invoice.collect](/business/nouns/invoice/collect); `void` by [Invoice.void](/business/nouns/invoice/void); `uncollectible` on [`Invoice.overdue`](/business/nouns/invoice#invoiceoverdue) when every retry on the Startup’s retry schedule has failed |
| `paid` | Paid in full; a refund adds to its refunded total and never reopens it. | None: it ends here. |
| `void` | Canceled unpaid and kept on record, with its reversing Entries posted. | None: it ends here. |
| `uncollectible` | Kept on record as unpaid once every retry has failed. | None: it ends here. |

## Verbs
| Verb | Description | Subject | Event | Class |
| --- | --- | --- | --- | --- |
| [Invoice.bill](/business/nouns/invoice/bill) | Bill finalizes an Invoice and presents it to the Customer for payment. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.billed`](/business/events/Invoice.billed) | One-way (customer): `send`, `do` |
| [Invoice.collect](/business/nouns/invoice/collect) | Collect charges a Customer’s saved payment method for an open Invoice and retries on failure. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.collected`](/business/events/Invoice.collected) | One-way (money, customer): `send`, `do` |
| [Invoice.refund](/business/nouns/invoice/refund) | Refund returns all or part of a paid Invoice to the Customer’s original payment method and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.refunded`](/business/events/Invoice.refunded) | One-way (money, customer): `send`, `do` |
| [Invoice.void](/business/nouns/invoice/void) | Void cancels an unpaid Invoice, keeps it on record, and posts the reversing Entries. | [Billing Specialist](/agents/finance/billing-specialist) | [`Invoice.voided`](/business/events/Invoice.voided) | One-way (money, customer): `send`, `do` |
| <a id="create"></a>[Invoice.create](/business/nouns/invoice/create) | Creates an Invoice. Inherited from [Noun](/business/nouns/noun). | None. | `Invoice.created` | Two-way: `try`, `send`, `do` |
| <a id="get"></a>[Invoice.get](/business/nouns/invoice/get) | Returns one Invoice by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="list"></a>[Invoice.list](/business/nouns/invoice/list) | Returns Invoices, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="update"></a>[Invoice.update](/business/nouns/invoice/update) | Changes the given properties of an Invoice. Inherited from [Noun](/business/nouns/noun). | None. | `Invoice.updated` | Two-way: `try`, `send`, `do` |

An Invoice is never deleted: it ends by [Invoice.void](/business/nouns/invoice/void), and its records stay.

## Events
Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape.

### Invoice.overdue
An open Invoice passed its `due` date unpaid, or a retry on the Startup’s retry schedule failed. Raised by a clock.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | Yes | `Invoice.overdue`. |
| `at` | `datetime` | Yes | When it happened. |
| `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. |
| `data` | `json` | Yes | The Thing as the Action left it. |
| `data.invoice` | [Invoice](/business/nouns/invoice) | Yes | The Invoice as the change left it. |
| `data.invoice.total` | `money` | Yes | The amount due. |
| `data.invoice.due` | `date` | Yes | When payment is due. |
| `data.invoice.paidAt` | `datetime` | No | When it was paid. |
| `data.invoice.status` | `string` | No | One of `draft`, `open`, `paid`, `void`, or `uncollectible`. |
| `data.invoice.collection` | `string` | No | `charge` charges the saved payment method; `send` sends the Invoice and waits for a transfer. `charge` by default. |
| `data.invoice.terms` | `integer` | No | Days from issue until a `send` Invoice is due, such as 30; sets `due`. |
| `data.invoice.purchaseOrder` | `string` | No | The Customer’s purchase order number, printed on the Invoice. |
| `data.invoice.refunded` | `money` | No | The total returned to the Customer, from zero up to the amount paid. |
| `data.invoice.number` | `string` | No | The Invoice number, sequential per Startup and never reused, voided Invoices included. |
| `data.invoice.lines` | `json` | No | Each Offer billed: its quantity, Period and amount, with any Coupon or Credit Grant applied. |
| `data.invoice.pdf` | `url` | No | The Invoice, or its receipt once paid, as a PDF on the Startup’s Domain that names the seller of record. |
| `data.invoice.payUrl` | `url` | No | The page on the Startup’s Domain where the Customer pays it by card or bank transfer. |
| `data.attempt` | `integer` | Yes | Which retry failed; 0 when the due date passed. |
| `data.nextRetryAt` | `datetime` | No | When the next retry runs; empty after the last one. |

```json
{
  "$id": "https://api.sb/patentpad.com/events/event_1",
  "$type": "Event",
  "name": "Invoice.overdue",
  "at": "2026-10-22T12:00:00Z",
  "data": {
    "invoice": {
      "$id": "https://api.sb/patentpad.com/invoices/invoice_1",
      "$type": "Invoice",
      "total": {
        "amount": 499,
        "currency": "USD"
      },
      "due": "2026-10-22",
      "paidAt": "2026-10-22T12:00:00Z",
      "status": "open",
      "collection": "charge",
      "terms": 1,
      "purchaseOrder": "PO-48213",
      "refunded": {
        "amount": 499,
        "currency": "USD"
      },
      "number": "LEDG-0042",
      "lines": {},
      "pdf": "https://patentpad.com",
      "payUrl": "https://patentpad.com"
    },
    "attempt": 1,
    "nextRetryAt": "2026-10-22T12:00:00Z"
  },
  "seq": 1
}
```

## Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.

| Operation | `owner` | `admin` | `member` | `viewer` |
| --- | --- | --- | --- | --- |
| `Invoice.create` | Yes | Yes | Yes | No |
| `Invoice.get` | Yes | Yes | Yes | Yes |
| `Invoice.list` | Yes | Yes | Yes | Yes |
| `Invoice.update` | Yes | Yes | Yes | No |
| `Invoice.bill` | Yes | No | No | No |
| `Invoice.collect` | Yes | No | No | No |
| `Invoice.refund` | Yes | No | No | No |
| `Invoice.void` | Yes | No | No | No |

## Stripe
**Invoice** (`invoice`). The source of truth is db.sb, and Stripe holds a copy written from it.

| Property | Stripe field | Source of truth |
| --- | --- | --- |
| `total` | `total` | db.sb |
| `due` | `due_date` | db.sb |
| `status` | `status` | Stripe |
| `paidAt` | `status_transitions.paid_at` | Stripe |
| `collection` | `collection_method` | db.sb |
| `terms` | `days_until_due` | db.sb |
| `number` | `number` | db.sb |
| `lines` | `lines.data` | db.sb |

| State | Stripe status |
| --- | --- |
| `draft` | `draft` |
| `open` | `open` |
| `paid` | `paid` |
| `void` | `void` |
| `uncollectible` | `uncollectible` |

## Call it

**Ask**

```text
Bill the latest invoice.
```

**API**

```bash
curl -X POST https://api.sb/tutorloop.com/invoices/invoice_1/bill \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
```

```json
{
  "api": "https://api.sb/tutorloop.com",
  "invoice": {
    "$id": "https://api.sb/tutorloop.com/invoices/invoice_1",
    "$type": "Invoice",
    "total": {
      "amount": 60,
      "currency": "USD"
    },
    "due": "2026-10-22"
  },
  "action": {
    "$id": "https://api.sb/tutorloop.com/actions/action_1",
    "operation": "Invoice.bill",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/tutorloop.com/actions/action_1"
  }
}
```

**SDK**

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

const invoice = await $.Invoice.bill({ invoice: 'invoice_1' })
```

**CLI**

```bash
npx startup-builder do Invoice.bill --json '{"invoice":"invoice_1"}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "return await $.Invoice.bill({ invoice: 'invoice_1' })"
  }
}
```

## Example
The monthly Invoice to a dental group bills $99 for the base plan and $36 for 1,200 reminders over its [Limit](/business/nouns/limit). It is due in 15 days.