---
title: "Every month"
url: https://services.dev/docs/grow/subscription
captured: [grow-subscription-tabs.txt, grow-subscription.txt]
---
# Every month

URL: https://services.dev/docs/grow/subscription

> Sell Translation by the month on the buyer's site. A schedule and an event order it, four a month are included, the fifth is offered at its price, and renewal resets the count.

Some buyers want the work kept up, not ordered one job at a time. A subscription charges once a cycle and orders the jobs itself: on a schedule, and whenever the buyer's systems say something changed. This is Grow 7: the four-line Translation stays as it is, and a plan beside it sells it by the month.

## Add the plan

`check` counts 7 lines:

```ts title="grow/subscription.ts"
import { Service } from 'services.dev'
import translation from '../services/translation.ts'

// Grow 7, every month: the four-line Translation, kept up on the buyer's site. The plan is a subscription on the site,
// $149 a month. On the 1st it translates the site's document, and each page.changed the buyer's systems send translates
// that page. Four translations a month are included, at $0; past four, the next is offered at Translation's own $49.
export default Service({
  name: 'Translation Plan',
  description: 'A site kept translated, every month and on every change.',
  input: { site: 'text: your site, such as acme.example', document: 'file', to: 'language: a BCP 47 tag, such as fr-CA' },
  output: { report: 'text' },
  subject: { kind: 'site', key: 'site' },
  on: { schedule: { monthly: { at: 'every month', order: translation } }, event: { 'page.changed': translation } },
  price: { usd: 149, every: 'month', includes: { translation: 4 } },
})
```

`subject` is what the plan keeps up, the buyer's site. `on` orders Translation on the 1st and on every `page.changed`, and `price` makes an order a subscription.

| Key | What it does | Default |
|---|---|---|
| `subject` | What the work is kept on: `kind`, in your words, and `key`, the input (or the output a receipt fills) whose value names it. It outlives every job; [Subjects](https://services.dev/docs/service/subject.md) adds `keeps`, `period` and `of_record` | none |
| `on.schedule` | Dates, by name, each ordering this Service, or with `{ at, order }` the one it names: `'every month'` is the 1st, and `'every monday'`, `'every quarter'`, `'Feb 1'` and `'2027-02-01'` work too. Each mints at the calendar's `rings_at` | none |
| `on.event` | Events, by name, each ordering a Service: from your other Services' jobs on the subject, or from the buyer's systems through `POST /events` as `{ type, id, data }`. `data` names the subject and fills the order; the same `id` again mints nothing more | none |
| `price.every` | `'day'`, `'week'`, `'month'`, `'quarter'` or `'year'`: an order is a subscription, `sbn_…`, charged `usd` at the start of each cycle, counted from the day it's ordered | one job |
| `price.includes` | Allowances per cycle, by Service id: inside one a job is $0 and counted; past it, the order answers 402 OFFER at the job's own price. Renewal resets them | none |

[Schedules and triggers](https://services.dev/docs/service/subscriptions.md) covers routing, `each` and `catch_up`, and [Subjects](https://services.dev/docs/service/subject.md) what a subject keeps.

## Check it

```bash
npx services.dev check
```

```txt title="magic values: none"
services/plan.ts · 7 lines · $149 per month, charged at the start of each month, 4 translation included each month.
  who     AI delivers every job.
  steps   draft · ai → review · ai · adversarial
  subject site · keyed by site
  agent   order_plan · 29 of 30 words · bought sbn_7Hq2 · $149.00 · no person
  ledger  +$149.00 · AI $0.84 (example) · you $148.16
  margin  at least $119.20 a job (80%) · a job that stops costs you at most $29.80
  apps    customer portal · owner console

services/translation.ts · 4 lines · $49 per job, within 48 hours, charged on delivery.
  who     AI delivers every job.
  steps   draft · ai → review · ai · adversarial
  agent   order_translation · 24 of 30 words · bought job_7Hq2 · $49.00 · no person
  ledger  +$49.00 · AI $0.84 (example) · you $48.16
  margin  at least $39.20 a job (80%) · a job that stops costs you at most $9.80
  apps    customer portal · owner console

mcp     14 buyer tools · 5,166 of 8,000 tokens · 9 more with ?toolset=sandbox
✓ ready to sell · 2 Services · AI delivers both alone · each keeps at least 80% of every job
  next    npx services.dev dev

AI and money are simulated until you wire them. $0.42 a call is an example.
```

The plan prices a cycle, not a job. Translation still reads $49 a job.

## Subscribe

The order answers a subscription, its allowance at 0 of 4:

**CLI**

```bash title="CLI"
npx services.dev plan site=acme.example document=https://example.com/acme/index.html to=fr-CA --max 149 --key plan --json
```

```json title="magic values: none"
{
  "id": "sbn_7Hq2",
  "object": "subscription",
  "livemode": false,
  "service": "plan",
  "status": "active",
  "subject": "sbj_7Hq2",
  "policy": {},
  "price": {
    "usd": 149,
    "every": "month"
  },
  "cycle": {
    "number": 1,
    "start": "2026-10-25T14:02:11.000Z",
    "end": "2026-11-25T14:02:11.000Z"
  },
  "allowances": {
    "translation": {
      "used": 0,
      "included": 4
    }
  },
  "schedule": [
    {
      "name": "monthly",
      "service": "translation",
      "next": "2026-11-01T00:00:00.000Z"
    }
  ],
  "events": [
    {
      "event": "page.changed",
      "service": "translation"
    }
  ],
  "charges": [
    {
      "cycle": 1,
      "usd": 149,
      "at": "2026-10-25T14:02:11.000Z"
    }
  ],
  "minted": [],
  "jobs": [],
  "metadata": {},
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

**API**

```bash title="API"
curl -X POST http://localhost:8787/plan -d '{"site":"acme.example","document":{"url":"https://example.com/acme/index.html","name":"index.html"},"to":"fr-CA","max_usd":149,"key":"plan"}'
```

```json title="200 · magic values: none"
{
  "id": "sbn_7Hq2",
  "object": "subscription",
  "livemode": false,
  "service": "plan",
  "status": "active",
  "subject": "sbj_7Hq2",
  "policy": {},
  "price": {
    "usd": 149,
    "every": "month"
  },
  "cycle": {
    "number": 1,
    "start": "2026-10-25T14:02:11.000Z",
    "end": "2026-11-25T14:02:11.000Z"
  },
  "allowances": {
    "translation": {
      "used": 0,
      "included": 4
    }
  },
  "schedule": [
    {
      "name": "monthly",
      "service": "translation",
      "next": "2026-11-01T00:00:00.000Z"
    }
  ],
  "events": [
    {
      "event": "page.changed",
      "service": "translation"
    }
  ],
  "charges": [
    {
      "cycle": 1,
      "usd": 149,
      "at": "2026-10-25T14:02:11.000Z"
    }
  ],
  "minted": [],
  "jobs": [],
  "metadata": {},
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

**MCP**

```txt title="MCP"
→ tools/call order_plan {"site":"acme.example","document":{"url":"https://example.com/acme/index.html","name":"index.html"},"to":"fr-CA","max_usd":149,"key":"plan"}
```

```json title="magic values: none"
{
  "id": "sbn_7Hq2",
  "object": "subscription",
  "livemode": false,
  "service": "plan",
  "status": "active",
  "subject": "sbj_7Hq2",
  "policy": {},
  "price": {
    "usd": 149,
    "every": "month"
  },
  "cycle": {
    "number": 1,
    "start": "2026-10-25T14:02:11.000Z",
    "end": "2026-11-25T14:02:11.000Z"
  },
  "allowances": {
    "translation": {
      "used": 0,
      "included": 4
    }
  },
  "schedule": [
    {
      "name": "monthly",
      "service": "translation",
      "next": "2026-11-01T00:00:00.000Z"
    }
  ],
  "events": [
    {
      "event": "page.changed",
      "service": "translation"
    }
  ],
  "charges": [
    {
      "cycle": 1,
      "usd": 149,
      "at": "2026-10-25T14:02:11.000Z"
    }
  ],
  "minted": [],
  "jobs": [],
  "metadata": {},
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

**SDK**

```ts title="SDK"
await lingua.plan.order({"site":"acme.example","document":{"url":"https://example.com/acme/index.html","name":"index.html"},"to":"fr-CA","max_usd":149,"key":"plan"})
```

```json title="magic values: none"
{
  "id": "sbn_7Hq2",
  "object": "subscription",
  "livemode": false,
  "service": "plan",
  "status": "active",
  "subject": "sbj_7Hq2",
  "policy": {},
  "price": {
    "usd": 149,
    "every": "month"
  },
  "cycle": {
    "number": 1,
    "start": "2026-10-25T14:02:11.000Z",
    "end": "2026-11-25T14:02:11.000Z"
  },
  "allowances": {
    "translation": {
      "used": 0,
      "included": 4
    }
  },
  "schedule": [
    {
      "name": "monthly",
      "service": "translation",
      "next": "2026-11-01T00:00:00.000Z"
    }
  ],
  "events": [
    {
      "event": "page.changed",
      "service": "translation"
    }
  ],
  "charges": [
    {
      "cycle": 1,
      "usd": 149,
      "at": "2026-10-25T14:02:11.000Z"
    }
  ],
  "minted": [],
  "jobs": [],
  "metadata": {},
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

## One month

A test clock runs the cycle. Three pages change, then the 1st comes, and each mints Translation at $0:

```txt
→ POST /plan {"site":"acme.example","document":"lease.pdf","to":"fr-CA","max_usd":149,"key":"plan","test_clock":"tc_7Hq3"}
```

```txt title="magic values: none"
← sbn_7Hq2 · plan · active · cycle 1 · 2026-10-25 → 2026-11-25 · $149.00 per month
  allowances  translation 0 of 4
  schedule    monthly → translation · next 2026-11-01
  event       page.changed → translation

# three pages change this month: each mints Translation on the plan, inside its four
→ POST /events {"type":"page.changed","id":"page-1","data":{"site":"acme.example","document":"page-1.html"}}
← subscription.minted · event page.changed → job_7Hq2 translation · $0.00
→ POST /events {"type":"page.changed","id":"page-2","data":{"site":"acme.example","document":"page-2.html"}}
← subscription.minted · event page.changed → job_7Hq3 translation · $0.00
→ POST /events {"type":"page.changed","id":"page-3","data":{"site":"acme.example","document":"page-3.html"}}
← subscription.minted · event page.changed → job_7Hq4 translation · $0.00

# the 1st mints the fourth
→ POST /test_clocks/tc_7Hq3/advance {"to":"2026-11-02T00:00:00Z"}
  2026-11-01  sbn_7Hq2  schedule monthly → job_7Hv5 translation · $0.00 · allowance 4 of 4
```

A fifth change is past the four, so Translation is offered at its own $49, a 402 OFFER whose `next` is the order to place. Placing it holds $49 on a job `from` the plan:

```txt
→ POST /events {"type":"page.changed","id":"page-5","data":{"site":"acme.example","document":"page-5.html"}}
```

```txt title="magic values: none"
← subscription.minted · event page.changed → translation offered at $49.00
  next    order translation {"document":"page-5.html","to":"fr-CA","max_usd":49,"key":"sbn_7Hq2:event page.changed:page-5","test_clock":"tc_7Hq3","subscription":"sbn_7Hq2"}

→ POST /translation {"document":"page-5.html","to":"fr-CA","max_usd":49,"key":"sbn_7Hq2:event page.changed:page-5","test_clock":"tc_7Hq3","subscription":"sbn_7Hq2"}
← job_7Hq6 · working · $49.00 held · from sbn_7Hq2
```

On the 25th the plan renews: it charges $149 again and resets the allowance, so the 1 December job is 1 of 4 at $0.

```txt
→ POST /test_clocks/tc_7Hq3/advance {"to":"2026-12-02T00:00:00Z"}
```

```txt title="magic values: none"
  2026-11-25  sbn_7Hq2  renews · cycle 2 · $149.00 charged · allowances reset · ends 2026-12-25
  2026-12-01  sbn_7Hq2  schedule monthly → job_7Hq7 translation · $0.00 · allowance 1 of 4

← sbn_7Hq2 · plan · active · cycle 2 · 2026-11-25 → 2026-12-25 · $149.00 per month
  allowances  translation 1 of 4
  schedule    monthly → translation · next 2027-01-01
  event       page.changed → translation
  minted      2026-10-25  event page.changed → job_7Hq2 translation · $0.00
  minted      2026-10-25  event page.changed → job_7Hq3 translation · $0.00
  minted      2026-10-25  event page.changed → job_7Hq4 translation · $0.00
  minted      2026-11-01  schedule monthly → job_7Hv5 translation · $0.00
  minted      2026-11-02  event page.changed → translation offered at $49.00
  minted      2026-12-01  schedule monthly → job_7Hq7 translation · $0.00
```

## What changed

```bash
npx services.dev diff . with-plan
```

```txt title="magic values: none"
. (4 lines) → with-plan (2 Services)
Translation Plan · new
Translation · changed nothing

API   ~ operation service.order        POST /jobs  item.requestBody.content.application/json.schema.properties.service.enum
      + operation service.order.plan   POST /plan
      + operation service.quote.plan   GET /plan.json
      + operation subject.list         GET /subjects
      + operation subject.get          GET /subjects/{id}
      + operation member.subjects      GET /me/subjects
      + operation subject.withdraw     POST /subjects/{id}/withdraw
      + operation subscription.list    GET /subscriptions
      + operation subscription.get     GET /subscriptions/{id}
      + operation subscription.cancel  POST /subscriptions/{id}/cancel
      ~ operation brand.manifest       GET /manifest.json  answers.services, answers.tools
      + object sbj_                    subject
      + object sbn_                    subscription
      + 6 events                       subscription.created, subscription.renewed, subscription.minted, allowance.used, allowance.exceeded, subscription.canceled
CLI   + operation service.order.plan   services.dev plan site=… document=… to=…
      + operation subject.list         services.dev subjects list
      + operation subject.get          services.dev subjects get <subject>
      + operation member.subjects      services.dev me subjects
      + operation subject.withdraw     services.dev subjects withdraw <subject> <successor>
      + operation subscription.list    services.dev subscriptions list
      + operation subscription.get     services.dev subscriptions get <subscription>
      + operation subscription.cancel  services.dev subscriptions cancel <subscription>
      + 6 events                       subscription.created, subscription.renewed, subscription.minted, allowance.used, allowance.exceeded, subscription.canceled
MCP   + operation order_plan           order_plan
      ~ operation order_translation    order_translation  inputSchema.properties.subscription
      + operation list_subscriptions   list_subscriptions
      + operation get_subscription     get_subscription
      + operation cancel_subscription  cancel_subscription
      + prompt buy_plan                prompts/get buy_plan
SDK   + operation service.order.plan   plan.order()
      + operation subscription.list    subscriptions.list()
      + operation subscription.get     subscriptions.get()
      + operation subscription.cancel  subscriptions.cancel()
      + object job_ (plan)             Job<"plan">
      + object sbj_                    subject
      + object sbn_                    subscription
      + 6 events                       subscription.created, subscription.renewed, subscription.minted, allowance.used, allowance.exceeded, subscription.canceled
Site  + operation service.order.plan   /plan
      + operation service.quote.plan   /plan.json
Docs  + operation service.order.plan   /llms.txt · Translation Plan
      + operation subject.list         /llms.txt · Operations
      + operation subject.get          /llms.txt · Operations
      + operation subscription.list    /llms.txt · Operations
      + operation subscription.get     /llms.txt · Operations
      + operation subscription.cancel  /llms.txt · Operations
App   ~ operation job.list             /portal · customer portal  + plan: AI delivers every job.
      + operation subscription.cancel  /portal · subscriptions and allowances used
      ~ operation job.ledger           /console · owner console  + plan: $149 per month, charged at the start of each month, 4 translation included each mont
```

The plan brings the subject and subscription objects, their calls, [cancel](https://services.dev/docs/money/subscriptions.md#cancel) among them, and six events. The customer portal gains subscriptions and allowances used, and Translation's MCP tool takes a `subscription`, so an agent orders past an allowance on the plan. [Subscriptions and allowances](https://services.dev/docs/money/subscriptions.md) covers what each cycle charges and pays.

In a brand, [the tax example](https://services.dev/docs/examples/tax/tax-plan.md) routes one plan's schedule and events to several small Services, and [the legal example](https://services.dev/docs/examples/legal/docket-watch.md) orders a job on each event it watches.

## Next

[All four, in one filing](https://services.dev/docs/grow/together.md) puts Grow 1 to 4 in one regulated Service.

---

- Up: [Your first paid job](https://services.dev/docs.md)
- Previous: [Paid on the close](https://services.dev/docs/grow/outcome.md)
- Next: [All four, in one filing](https://services.dev/docs/grow/together.md)
