Subscriptions and seats

Add subscriptions and change quantities or seats on a contract.

View .md

Goal

Give Acme Corp 10 monthly seats from 1 December 2026, then raise them to 12 from 1 January 2027. See Subscriptions & seats.

Preview

Add the subscription:

metro subscription add preflight --ingest-alias=acme-corp \
  --product-id=00000000-0000-4000-8000-000000000010 --billing-frequency=MONTHLY \
  --quantity=10 --starting-at=2026-12-01T00:00:00.000Z --sandbox --out=plans/sub.json
metro subscription add preflight (sandbox, key sha256:80f0714120b8) - read-only, nothing written to Metronome.
  contract 00000000-0000-4000-8000-000000000105.subscriptions: 0 -> 1
Steps: POST /v2/contracts/edit
Payload hash: sha256:...

The dry run shows the add_subscriptions body metro will send:

{"customer_id":"00000000-0000-4000-8000-000000000101","contract_id":"00000000-0000-4000-8000-000000000105",
 "add_subscriptions":[{"subscription_rate":{"product_id":"00000000-0000-4000-8000-000000000010","billing_frequency":"MONTHLY"},
   "collection_schedule":"ADVANCE","proration":{"is_prorated":true,"invoice_behavior":"BILL_ON_NEXT_COLLECTION_DATE"},
   "quantity_management_mode":"QUANTITY_ONLY","initial_quantity":10,"starting_at":"2026-12-01T00:00:00.000Z"}],
 "uniqueness_key":"metro-edit-9ab86777e09e8ede13fee5e3"}

Preflight refuses when the product isn't a SUBSCRIPTION product, when the contract's rate card has no entitled SUBSCRIPTION rate for it at that frequency, or when the contract already has that subscription (pass --allow-duplicate to add it anyway). If the customer has more than one contract, pass --contract-id=.

For a seat-based subscription, or any field the flags don't cover, pass a full spec with --file=subscription.yaml. Your Metronome account needs contract editing enabled.

Then the quantity change:

metro subscription set-quantity preflight --ingest-alias=acme-corp \
  --subscription-id=00000000-0000-4000-8000-000000000106 --quantity=12 \
  --starting-at=2027-01-01T00:00:00.000Z --sandbox --out=plans/qty.json
  subscription 00000000-0000-4000-8000-000000000106 quantity @ 2027-01-01T00:00:00.000Z: 10 -> 12
Steps: POST /v2/contracts/edit

--delta=2 works too. metro always sends an absolute quantity, computed from the current schedule, so apply writes exactly what you previewed.

Seats

For a SEAT_BASED subscription, change seats instead of quantity:

metro subscription seats preflight --ingest-alias=acme-corp \
  --subscription-id=00000000-0000-4000-8000-000000000106 \
  --starting-at=2027-01-01T00:00:00.000Z --add-seat-ids=user-41,user-42 --sandbox

--remove-seat-ids=, --add-unassigned=<n> and --remove-unassigned=<n> work the same way.

Confirm

Show the human the contract, the product, the quantity before and after, and the hash. Increases are prorated onto the next invoice by default; decreases take effect at the next billing boundary. Then dry-run:

metro subscription set-quantity apply --file plans/qty.json --sandbox --confirm-hash sha256:...

Apply

metro subscription add apply --file plans/sub.json --sandbox --confirm-hash sha256:... \
  --apply --confirm-live-apply=I_UNDERSTAND_THIS_WILL_WRITE_LIVE_METRONOME_SANDBOX
metro subscription set-quantity apply --file plans/qty.json --sandbox --confirm-hash sha256:... \
  --apply --confirm-live-apply=I_UNDERSTAND_THIS_WILL_WRITE_LIVE_METRONOME_SANDBOX

Readback

Applied (sandbox).
Read-back (expected vs actual):
  ok   quantity at 2027-01-01T00:00:00.000Z: expected 12 actual 12

subscription add checks the subscription count for that product and frequency, and the quantity at its start. subscription seats reads the seats history and checks the assigned seat IDs; it checks the total only when you change unassigned seats alone, because assigned seats fill unassigned ones first.

A failed readback looks like this and exits 3:

Applied, but read-back FAILED (sandbox).
Read-back (expected vs actual):
  FAIL quantity at 2027-02-01T00:00:00.000Z: expected 15 actual 12

Don't re-run the plan. Read the contract fresh with metro ops who "Acme Corp" --sandbox, find the cause, then preflight again.

On this page