Credits and commits
Complimentary grants, paid top-ups and ledger adjustments.
Goal
Three common balance changes on Acme Corp's active contract:
| Change | Command | Metronome call |
|---|---|---|
| Add or remove an amount on an existing balance | metro ledger-adjustment preflight --amount=<signed-int> | manual ledger entry |
| Grant a new credit, or a complimentary commit | metro ledger-adjustment preflight --grant=credit or --grant=commit | contract edit, add_credits or add_commits |
| Remove a whole grant | metro ledger-adjustment preflight --archive-balance-id=<id> | contract edit, archive |
Every write carries a uniqueness_key, so a retry returns 409 instead of a second grant. See Credits & commits.
Preview
First, read the balances:
metro customer balances --ingest-alias=acme-corp --sandbox --only-nonzero --jsonThe output includes spendableNet: the net balance per credit type next to the sum of the balance list. If they disagree, metro warns with MTR-CREDIT-NET-001 and refuses additions for that credit type. Trust the net.
Then preflight the change. A $500 service credit for one year, as a new grant on a USD-cents credit type:
metro ledger-adjustment preflight --grant=credit --amount=50000 \
--product-id=00000000-0000-4000-8000-000000000011 \
--starting-at=2026-12-01T00:00:00.000Z --ending-before=2027-12-01T00:00:00.000Z \
--reason="Service credit for the November outage" \
--ingest-alias=acme-corp --sandbox --out=ledger.jsonThe credit type comes from metro catalog bind --sandbox --write, or pass --credit-type-id=; metro won't guess it. The amount is in that credit type's units. Name the grant with --grant-name=, and set --priority= to control drawdown order. --grant=commit adds a PREPAID commit with no invoice schedule: a complimentary commit.
Or an adjustment of an existing balance. Additions need a target: --contract-id= or --balance-id=. A removal picks the one balance that covers it, or asks you to choose.
metro ledger-adjustment preflight --amount=-2500 --reason="Correct double grant" \
--ingest-alias=acme-corp --balance-id=00000000-0000-4000-8000-000000000008 \
--sandbox --out=ledger.jsonThe preflight prints the diff, for example balance 00000000-0000-4000-8000-000000000008: 10000 -> 7500, the steps and the Payload hash.
Offline first, if you want
The complimentary-credit-grant and paid-credit-top-up shapes check a grant with no API call at all. This is real output:
metro plan template complimentary-credits --sandbox --out credit.json
metro validate --shape complimentary-credit-grant --file credit.json
metro credit preview --shape complimentary-credit-grant --file credit.json --sandbox✓ Validation passed for complimentary-credit-grant.
Why: The input matches the reviewed shape rules and guardrails.
Preview built for complimentary-credit-grant on sandbox.
Payload hash: sha256:d96a502b2c89d69048dfd7aff170ea47e1b0af9f71e2c57905bf6718b8f43f6e
Actions: 1
Apply supported: noShapes don't apply. Use them to agree on the grant, then run the ledger-adjustment preflight above.
Confirm
Show the human the customer, the balance before and after (or the new grant's amount and dates), the reason and the hash. Then dry-run:
metro ledger-adjustment apply --file ledger.json --sandbox --confirm-hash sha256:...Apply
metro mode write
metro ledger-adjustment apply --file ledger.json --sandbox --confirm-hash sha256:... \
--apply --confirm-live-apply=I_UNDERSTAND_THIS_WILL_WRITE_LIVE_METRONOME_SANDBOXOn production: --prod --confirm-prod-apply=I_UNDERSTAND_BILLING_SIDE_EFFECTS, after the human's typed yes for this change.
Readback
metro re-reads the balances. The check depends on the mode:
Applied (sandbox).
Read-back (expected vs actual):
ok balance 00000000-0000-4000-8000-000000000008: expected 7500 actual 7500A grant checks add_credits present with amount 50000 (or add_commits). An archive checks <balance id> archived. Any FAIL exits 3. Illustrative IDs; the format is exact.