# Credits

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

> Credits let a Customer prepay or receive a balance that its metered calls draw down, checked before each call and settled on the Invoice.

Credits let a [Customer](/business/nouns/customer) prepay or receive a balance that its metered calls draw down. Each call checks the balance as a [Limit](/business/nouns/limit) first, and the [Invoice](/business/nouns/invoice) settles what was spent.

## Contract
A balance is a set of [Credit Grants](/business/nouns/credit-grant). [db.sb](/code/platform/db-sb) keeps the live balance, and Stripe settles it when each Invoice finalizes.

| Category | Comes from | Books as | Issued by |
| --- | --- | --- | --- |
| `paid` | An [Order](/business/nouns/order) for an [Offer](/business/nouns/offer) that sets `Offer.credit`, such as a $50 pack | Cash on purchase, deferred revenue until spent | [Order.pay](/business/nouns/order/pay) |
| `promotional` | A gift: a launch bonus, an apology, a referral reward | An expense when spent, never cash | [CreditGrant.issue](/business/nouns/credit-grant/issue) |

| Rule | Detail |
| --- | --- |
| Before each call | The [Meter](/business/nouns/meter)’s next unit is checked against `CreditGrant.remaining`. At zero, the Offer’s bound applies: stop, bill overage through the Meter, or upgrade. |
| After each call | `CreditGrant.remaining` drops once per metered [Event](/business/nouns/event), never twice. |
| Order of use | Promotional grants spend first, then the lowest `CreditGrant.priority`, then the earliest `CreditGrant.expiresAt`. |
| Scope | `CreditGrant.appliesTo` holds a grant to one metered Offer; without it, the grant pays for any metered Offer of the [Startup](/business/nouns/startup). |
| Settlement | [CreditGrant.apply](/business/nouns/credit-grant/apply) pays the metered lines of each finalizing Invoice through Stripe credit grants. |
| Expiry | A balance lapses at `CreditGrant.expiresAt`. [CreditGrant.void](/business/nouns/credit-grant/void) ends a promotional grant early and tells the Customer why. |
| Recharge | `Customer.creditRecharge` buys another pack when the balance falls below its floor, charged to the default [Payment Source](/business/nouns/payment-source). |
| Closed loop | `CreditGrant.apply` spends credit only on the Startup’s own metered Offers: never transferred, never spent at another Startup, never paid out. |

## Verbs
| Verb | Object | Event |
| --- | --- | --- |
| [CreditGrant.issue](/business/nouns/credit-grant/issue) | [Credit Grant](/business/nouns/credit-grant) | [`CreditGrant.issued`](/business/events/CreditGrant.issued) |
| [CreditGrant.apply](/business/nouns/credit-grant/apply) | [Credit Grant](/business/nouns/credit-grant) | [`CreditGrant.applied`](/business/events/CreditGrant.applied) |
| [CreditGrant.void](/business/nouns/credit-grant/void) | [Credit Grant](/business/nouns/credit-grant) | [`CreditGrant.voided`](/business/events/CreditGrant.voided) |
| [CreditGrant.list](/business/nouns/credit-grant/list) | [Credit Grant](/business/nouns/credit-grant) | None. |

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

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

// routewise.dev sells routes at $0.002 each. A logistics team bought the $50 credit pack,
// and Order.pay issued a paid Credit Grant. Add a $10 launch bonus that lapses at year end.
await $.CreditGrant.issue({
  customer: 'customer_1',
  amount: { amount: 10, currency: 'USD' },
  category: 'promotional',
  expiresAt: '2026-12-31T23:59:59Z',
})

// When the balance falls below $5, buy another $50 pack with the default card.
await $.Customer.update({ id: 'customer_1', creditRecharge: { below: 5, amount: 50, offer: 'offer_credit_pack' } })

// After 27,600 routes ($55.20, the bonus spent first), the balance falls to $4.80 and the recharge runs.
const creditGrants = await $.CreditGrant.list({ where: 'remaining.amount > 0' })
```