# Make a custom plan for one customer

URL: /products/offers/make-a-custom-plan · Id: `guide:make-a-custom-plan`

> Say "make this customer a custom plan at $24,000 a year" and get a private Offer, a Quote with an accept link and an invoice on their terms.

A custom plan is a private [Offer](/business/nouns/offer) that one buyer sees, sent as a [Quote](/business/nouns/quote). The buyer accepts it, and the [Agreement](/business/nouns/agreement) and invoice follow from the same terms.

Needs: [Charge monthly](/systems/finance/charge-monthly) · [Open a bank account](/systems/finance/open-a-bank-account)

**Before it runs**

- Who says yes: You. Your agent shows you the run and waits for your [Approval](/business/nouns/approval).
- You leave the chat: Never: it all happens in the chat.

## What you get
- 1 private Offer at $24,000 a year that only Harbor Residential sees (Offer)
- 1 Quote with its own accept link, valid until November 30 (Quote)
- 1 order form the Contracts Manager signs, within the amount it may sign for (Agreement)
- 1 yearly invoice due in 30 days, with their purchase order number (Invoice)

## Your agent does
**For agents**

- Guide: `guide:make-a-custom-plan`, status `live`. Page: [/products/offers/make-a-custom-plan.md](/products/offers/make-a-custom-plan.md).
- Approval: ask the founder first. Show the run, then wait for their Approval; a refusal ends it.
- Leaves the chat: never.
- Needs first: [Charge monthly](/systems/finance/charge-monthly), [Open a bank account](/systems/finance/open-a-bank-account).
- 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 | [`Offer.create`](/business/nouns/offer/create) (`verb:Offer.create`) | `price` money, required: example `{"amount":24000,"currency":"USD"}`; `terms` text: example `"Yearly, invoiced net 30. Up to 4,000 units, single sign-on and 99.9% monthly uptime."`; `interval` string: example `"year"`; `privateTo` Party (an id): example `"organization_harbor"` | `offer` Offer |
| 2 | [`Quote.create`](/business/nouns/quote/create) (`verb:Quote.create`) | `total` money, required: example `{"amount":24000,"currency":"USD"}`; `validUntil` date, required: example `"2026-11-30"`; `lines` json, required: example `[{"offer":"$1.$id","quantity":1}]`; `paymentTerms` json: example `{"collection":"send","terms":30,"purchaseOrder":"PO-2291"}` | `quote` Quote |
| 3 | [`Quote.send`](/business/nouns/quote/send) (`verb:Quote.send`) | `quote` Quote (an id), required: the `$id` step 2 returns | `quote` Quote |

Returns: the last call answers with `quote` 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",
  "quote": {
    "$id": "https://api.sb/leaseline.app/quotes/quote_1",
    "$type": "Quote",
    "total": {
      "amount": 24000,
      "currency": "USD"
    },
    "lines": [
      {
        "offer": "offer_1",
        "quantity": 1
      }
    ],
    "validUntil": "2026-11-30",
    "paymentTerms": {
      "collection": "send",
      "terms": 30,
      "purchaseOrder": "PO-2291"
    },
    "status": "sent"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Quote.send",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/leaseline.app/actions/action_1"
  }
}
```

Next: offer “Give them 10% off if they sign by Friday”, or “Split it into two years at $22,000 and $26,000”.

Calls: `Offer.create` → `Quote.create` → `Quote.send`

Ask:

```text
Make Harbor Residential a custom plan at $24,000 a year.
Quote an enterprise deal.
Give one buyer its own private price.
```

API:

```bash
# 1. 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":24000,"currency":"USD"},"interval":"year","privateTo":"organization_harbor","terms":"Yearly, invoiced net 30. Up to 4,000 units, single sign-on and 99.9% monthly uptime."}' | jq -r '.offer["$id"] | split("/") | last')

# 2. Quote.create
QUOTE=$(curl -X POST https://api.sb/leaseline.app/quotes \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"total":{"amount":24000,"currency":"USD"},"validUntil":"2026-11-30","lines":[{"offer":"'"$OFFER"'","quantity":1}],"paymentTerms":{"collection":"send","terms":30,"purchaseOrder":"PO-2291"}}' | jq -r '.quote["$id"] | split("/") | last')

# 3. Quote.send
curl -X POST https://api.sb/leaseline.app/quotes/$QUOTE/send \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
```

SDK:

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

const offer = await $.Offer.create({ price: { amount: 24000, currency: 'USD' }, interval: 'year', privateTo: 'organization_harbor', terms: 'Yearly, invoiced net 30. Up to 4,000 units, single sign-on and 99.9% monthly uptime.' })
const quote = await $.Quote.create({ total: { amount: 24000, currency: 'USD' }, validUntil: '2026-11-30', lines: [{ offer: offer.$id, quantity: 1 }], paymentTerms: { collection: 'send', terms: 30, purchaseOrder: 'PO-2291' } })
await $.Quote.send({ quote: quote.$id })
```

CLI:

```bash
OFFER=$(npx startup-builder do Offer.create --json '{"price":{"amount":24000,"currency":"USD"},"interval":"year","privateTo":"organization_harbor","terms":"Yearly, invoiced net 30. Up to 4,000 units, single sign-on and 99.9% monthly uptime."}' | jq -r '.offer["$id"] | split("/") | last')
QUOTE=$(npx startup-builder do Quote.create --json '{"total":{"amount":24000,"currency":"USD"},"validUntil":"2026-11-30","lines":[{"offer":"'"$OFFER"'","quantity":1}],"paymentTerms":{"collection":"send","terms":30,"purchaseOrder":"PO-2291"}}' | jq -r '.quote["$id"] | split("/") | last')
npx startup-builder do Quote.send --json '{"quote":"'"$QUOTE"'"}'
```

MCP:

```json
{
  "name": "do",
  "arguments": {
    "code": "const offer = await $.Offer.create({ price: { amount: 24000, currency: 'USD' }, interval: 'year', privateTo: 'organization_harbor', terms: 'Yearly, invoiced net 30. Up to 4,000 units, single sign-on and 99.9% monthly uptime.' })\nconst quote = await $.Quote.create({ total: { amount: 24000, currency: 'USD' }, validUntil: '2026-11-30', lines: [{ offer: offer.$id, quantity: 1 }], paymentTerms: { collection: 'send', terms: 30, purchaseOrder: 'PO-2291' } })\nreturn await $.Quote.send({ quote: quote.$id })"
  }
}
```

## Change it
- Give them 10% off if they sign by Friday.
- Split it into two years at $22,000 and $26,000.
- Let them pay by card instead.

## Under the hood
- Systems: [CRM](/systems/crm), [Billing](/systems/billing)
- Nouns: [Offer](/business/nouns/offer), [Quote](/business/nouns/quote), [Agreement](/business/nouns/agreement), [Invoice](/business/nouns/invoice)
- Events: `Offer.created`, [`Quote.sent`](/business/events/Quote.sent), [`Quote.accepted`](/business/events/Quote.accepted)
- Stripe objects: `Quote`, `Invoice`