# Billing (/entities/billing)



All Billing entities are Stripe-backed. Creating a Subscription in headless.ly creates a Stripe subscription. Stripe webhooks flow back as events.

Customer [#customer]

Stripe Customer — the billing identity. Links an Organization to Stripe.

```typescript
import { Noun } from 'digital-objects'

export const Customer = Noun('Customer', {
  name: 'string!',
  email: 'string!#',
  organization: '-> Organization',
  stripeCustomerId: 'string##',
  subscriptions: '<- Subscription.customer[]',
  invoices: '<- Invoice.customer[]',
  payments: '<- Payment.customer[]',
  paymentMethod: 'string',
  currency: 'string',
  taxExempt: 'string',
})
```

Product [#product]

What you sell — software, services, addons, bundles.

```typescript
export const Product = Noun('Product', {
  name: 'string!',
  slug: 'string##',
  description: 'string',
  tagline: 'string',
  type: 'Software | Service | Addon | Bundle',
  icon: 'string',
  image: 'string',
  features: 'string',
  highlights: 'string',
  status: 'Draft | Active | Archived',
  visibility: 'Public | Private | Hidden',
  featured: 'boolean',
  plans: '<- Plan.product[]',
  stripeProductId: 'string##',
})
```

Plan [#plan]

Pricing tiers with trial configuration and feature limits.

```typescript
export const Plan = Noun('Plan', {
  name: 'string!',
  slug: 'string##',
  description: 'string',
  product: '-> Product.plans',
  prices: '<- Price.plan[]',
  trialDays: 'number',
  features: 'string',
  limits: 'string',
  status: 'Draft | Active | Grandfathered | Archived',
  isDefault: 'boolean',
  isFree: 'boolean',
  isEnterprise: 'boolean',
  badge: 'string',
  order: 'number',
})
```

Price [#price]

Pricing configuration — maps to Stripe Prices.

```typescript
export const Price = Noun('Price', {
  amount: 'number!',
  currency: 'string',
  interval: 'Monthly | Quarterly | Yearly | OneTime',
  intervalCount: 'number',
  originalAmount: 'number',
  discountPercent: 'number',
  active: 'boolean',
  plan: '-> Plan.prices',
  stripeId: 'string##',
})
```

| Interval    | Description                |
| ----------- | -------------------------- |
| `Monthly`   | Recurring monthly charge   |
| `Quarterly` | Recurring quarterly charge |
| `Yearly`    | Recurring yearly charge    |
| `OneTime`   | Single purchase            |

Subscription [#subscription]

Active paying relationships.

```typescript
export const Subscription = Noun('Subscription', {
  status: 'Active | PastDue | Cancelled | Trialing | Paused | Incomplete | Reactivated | Upgraded | Downgraded',
  organization: '-> Organization.subscriptions',
  customer: '-> Customer.subscriptions',
  plan: '-> Plan',
  currentPeriodStart: 'datetime!',
  currentPeriodEnd: 'datetime!',
  cancelAtPeriodEnd: 'boolean',
  trialStart: 'datetime',
  trialEnd: 'datetime',
  startedAt: 'datetime!',
  canceledAt: 'datetime',
  pausedAt: 'datetime',
  resumesAt: 'datetime',
  endedAt: 'datetime',
  cancelReason: 'string',
  cancelFeedback: 'string',
  quantity: 'number',
  paymentMethod: 'string',
  collectionMethod: 'string',
  stripeSubscriptionId: 'string##',
  stripeCustomerId: 'string',
  pause: 'Paused',
  cancel: 'Cancelled',
  reactivate: 'Reactivated',
  upgrade: 'Upgraded',
  downgrade: 'Downgraded',
})
```

| Verb         | Event         | Description                      |
| ------------ | ------------- | -------------------------------- |
| `pause`      | `Paused`      | Temporarily suspend billing      |
| `cancel`     | `Cancelled`   | End the subscription             |
| `reactivate` | `Reactivated` | Restart a cancelled subscription |
| `upgrade`    | `Upgraded`    | Move to a higher-value plan      |
| `downgrade`  | `Downgraded`  | Move to a lower-value plan       |

Invoice [#invoice]

Bills — monthly/annual.

```typescript
export const Invoice = Noun('Invoice', {
  number: 'string!##',
  organization: '-> Organization',
  customer: '-> Customer.invoices',
  subscription: '-> Subscription',
  subtotal: 'number!',
  tax: 'number',
  discount: 'number',
  total: 'number!',
  amountPaid: 'number',
  amountDue: 'number!',
  currency: 'string',
  status: 'Draft | Open | Paid | Voided | Uncollectible',
  periodStart: 'datetime',
  periodEnd: 'datetime',
  issuedAt: 'datetime',
  dueAt: 'datetime',
  paidAt: 'datetime',
  voidedAt: 'datetime',
  lineItems: 'json',
  receiptUrl: 'string',
  pdfUrl: 'string',
  hostedUrl: 'string',
  stripeInvoiceId: 'string##',
  pay: 'Paid',
  void: 'Voided',
})
```

| Verb   | Event    | Description          |
| ------ | -------- | -------------------- |
| `pay`  | `Paid`   | Mark invoice as paid |
| `void` | `Voided` | Void the invoice     |

Payment [#payment]

Money movement — charges, refunds.

```typescript
export const Payment = Noun('Payment', {
  amount: 'number!',
  currency: 'string',
  status: 'Pending | Succeeded | Failed | Refunded',
  method: 'string',
  customer: '-> Customer.payments',
  invoice: '-> Invoice',
  stripePaymentId: 'string##',
  refund: 'Refunded',
})
```

| Verb     | Event      | Description        |
| -------- | ---------- | ------------------ |
| `refund` | `Refunded` | Refund the payment |
