# Charge per use

URL: /start/guides/charge-per-use · Id: `guide:charge-per-use`

> Say "charge per use" and get a Meter that counts each use, a metered Offer on Stripe, and one invoice a month for what each customer used.

Charge for what each customer uses: a [Meter](/business/nouns/meter) counts every use, and Stripe bills the total once a month. Set the rate so your heaviest customer still makes you money.

Needs: [Startup](/business/nouns/startup)

**Before real money moves**

- Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval).
- You leave the chat: Once, at Stripe: to confirm who you are and add the bank account payouts land in.
- First question at Idea: “Sell a prepaid pack of 1,000 lookups first?”
- First question at Repeatable: “Move current customers to it at their next renewal?”
- What it costs: The card fee on each invoice.
- To undo it: Withdraw the Offer. Usage already counted still bills.

## What you get
- 1 Meter that counts each lookup once (Meter)
- 1 Offer at one cent per lookup (Offer)
- 1 product, metered price and meter on Stripe (Stripe's Product, Price and Billing Meter)
- 1 usage sent to Stripe each hour (Stripe's Meter Event)
- 1 Invoice each month for that month’s use (Invoice, on Stripe's Invoice)
- 1 usage page in the customer Portal (Portal)
- 2 ledger entries per Invoice: receivable and revenue (Entry)

## Your agent does
**For agents**

- Guide: `guide:charge-per-use`, status `beta`. Page: [/start/guides/charge-per-use.md](/start/guides/charge-per-use.md).
- Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it.
- Leaves the chat: Once, at Stripe: to confirm who you are and add the bank account payouts land in.
- Needs first: [Startup](/business/nouns/startup).
- Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own.

| Step | Verb | Inputs (type, required, this guide’s value) | Returns |
| --- | --- | --- | --- |
| 1 | [`Meter.create`](/business/nouns/meter/create) (`verb:Meter.create`) | `unit` string, required: example `"lookups"`; `of` string, required: example `"Lease.read"`; `aggregation` string, required: example `"count"`; `window` string, required: example `"month"` | `meter` Meter |
| 2 | [`Offer.create`](/business/nouns/offer/create) (`verb:Offer.create`) | `price` money, required: example `{"amount":0.01,"currency":"USD"}`; `terms` text: example `"One cent per renewal lookup, billed monthly for the month before."`; `interval` string: example `"month"` | `offer` Offer |
| 3 | [`Offer.publish`](/business/nouns/offer/publish) (`verb:Offer.publish`) | `offer` Offer (an id), required: the `$id` step 2 returns | `offer` Offer |

Returns: the last call answers with `offer` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`:

```json
{
  "api": "https://api.sb/leaseline.app",
  "offer": {
    "$id": "https://api.sb/leaseline.app/offers/offer_1",
    "$type": "Offer",
    "price": {
      "amount": 0.01,
      "currency": "USD"
    },
    "terms": "One cent per renewal lookup, billed monthly for the month before.",
    "interval": "month"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Offer.publish",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/leaseline.app/actions/action_1"
  }
}
```

Next: offer “Give every customer 1,000 free lookups a month”, or “Add a $49 plan with 10,000 lookups included”.

Calls: `Meter.create` → `Offer.create` → `Offer.publish`

Ask:

```text
Charge per use.
Bill by usage.
Charge a cent per API call.
```

API:

```bash
# 1. Meter.create
curl -X POST https://api.sb/leaseline.app/meters \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"unit":"lookups","of":"Lease.read","aggregation":"count","window":"month"}'

# 2. Offer.create
OFFER=$(curl -X POST https://api.sb/leaseline.app/offers \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"price":{"amount":0.01,"currency":"USD"},"terms":"One cent per renewal lookup, billed monthly for the month before.","interval":"month"}' | jq -r '.offer["$id"] | split("/") | last')

# 3. Offer.publish
curl -X POST https://api.sb/leaseline.app/offers/$OFFER/publish \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
```

SDK:

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

await $.Meter.create({ unit: 'lookups', of: 'Lease.read', aggregation: 'count', window: 'month' })
const offer = await $.Offer.create({ price: { amount: 0.01, currency: 'USD' }, terms: 'One cent per renewal lookup, billed monthly for the month before.', interval: 'month' })
await $.Offer.publish({ offer: offer.$id })
```

CLI:

```bash
npx startup-builder do Meter.create --json '{"unit":"lookups","of":"Lease.read","aggregation":"count","window":"month"}'
OFFER=$(npx startup-builder do Offer.create --json '{"price":{"amount":0.01,"currency":"USD"},"terms":"One cent per renewal lookup, billed monthly for the month before.","interval":"month"}' | jq -r '.offer["$id"] | split("/") | last')
npx startup-builder do Offer.publish --json '{"offer":"'"$OFFER"'"}'
```

MCP:

```json
{
  "name": "do",
  "arguments": {
    "code": "await $.Meter.create({ unit: 'lookups', of: 'Lease.read', aggregation: 'count', window: 'month' })\nconst offer = await $.Offer.create({ price: { amount: 0.01, currency: 'USD' }, terms: 'One cent per renewal lookup, billed monthly for the month before.', interval: 'month' })\nreturn await $.Offer.publish({ offer: offer.$id })"
  }
}
```

The same sentence does more as the business grows:

| State | Calls | Asks first |
| --- | --- | --- |
| [Idea](/business/lifecycle/states/idea) | [`Offer.create`](/business/nouns/offer/create), [`Offer.publish`](/business/nouns/offer/publish) | Sell a prepaid pack of 1,000 lookups first? |
| [Live](/business/lifecycle/states/live) | [`Meter.create`](/business/nouns/meter/create), [`Offer.create`](/business/nouns/offer/create), [`Offer.publish`](/business/nouns/offer/publish) |  |
| [Repeatable](/business/lifecycle/states/repeatable) | [`Meter.create`](/business/nouns/meter/create), [`Offer.create`](/business/nouns/offer/create), [`Offer.publish`](/business/nouns/offer/publish), [`Subscription.switch`](/business/nouns/subscription/switch) | Move current customers to it at their next renewal? |

## Change it
- Give every customer 1,000 free lookups a month.
- Add a $49 plan with 10,000 lookups included.
- Email me when a customer passes $500 in a month.

## Under the hood
- Systems: [Billing](/systems/billing), [Ledger](/systems/ledger), [Tax](/systems/tax)
- Nouns: [Meter](/business/nouns/meter), [Offer](/business/nouns/offer), [Price](/business/nouns/price), [Invoice](/business/nouns/invoice), [Entry](/business/nouns/entry)
- Events: [`Offer.published`](/business/events/Offer.published), [`Invoice.billed`](/business/events/Invoice.billed)
- Stripe objects: `Product`, `Price`, `Billing Meter`, `Meter Event`, `Invoice`

The Meter counts each `Lease.read` [Event](/business/nouns/event) once, even when a call retries. Each month closes into one [Invoice](/business/nouns/invoice) per [Customer](/business/nouns/customer), paid by the card on file.