Subscriptions and seats
Add subscriptions and change quantities or seats on a contract.
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.jsonmetro 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_SANDBOXReadback
Applied (sandbox).
Read-back (expected vs actual):
ok quantity at 2027-01-01T00:00:00.000Z: expected 12 actual 12subscription 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 12Don't re-run the plan. Read the contract fresh with metro ops who "Acme Corp" --sandbox, find the cause, then preflight again.