Billing
Adjustments, refunds, invoice lifecycle, and user suspension. Endpoint signatures: HTTP API.
Adjustments and refunds
Manual billing corrections are first-class events, not embedded fields on other records. POST /adjustments appends adjustment.posted; amounts are signed integers
(negative = credit, positive = charge) with no currency code. kind is prorate, credit, or debit (inferred from sign if omitted for
manual entries). Plan changes with refund_immediately append refund.issued automatically — refund amount is always positive; the invoice line is negative. Query
history with GET /adjustments and GET /refunds.
Invoice lifecycle
Invoices move through explicit states: draft → finalized → paid, or void from draft/finalized.
POST /invoices/generate— draft with line items for any billing windowPOST /invoices/{id}/finalize— lock amounts before collectionPOST /invoices/{id}/mark-paid— record payment withpayment_refPOST /invoices/{id}/void— cancel an unpaid invoice
Events: invoice.generated, invoice.finalized, invoice.paid, invoice.voided. Replay restores status, timestamps, and payment_ref.
Generation semantics: subscription periods reconstructed from the event log; base fee proportional to
active time (trials and pauses excluded); plan segments billed separately; billing_interval: year applies annual discount; usage scaled for partial windows; metric groups and usage pools share included across members; included_rollover adds unused included from the previous period at invoice time;
the same metric across multiple subscriptions for one user is billed only once;
built-in JSON billing or Luau pricing. JSON classify runs only at usage ingest.
User block, unblock, and delete
Blocking is for non-payment of your customers: the user can still send POST /usage and StatsD events (metering continues), but your app must treat them as
suspended. Invoice APIs are tenant-admin — generate, finalize, mark-paid, and void
work while a user is blocked so dunning can record payment without unblocking first.
| Operation | Blocked user | Deleted user |
|---|---|---|
POST /usage, StatsD | allowed | rejected |
| Entitlements, usage list, subscription GET, adjustments | 403 blocked | 403 deleted |
| Invoice generate / read / finalize / mark-paid / void | allowed (tenant admin) | generate rejected; existing invoices readable |
GET /users, GET /users/{id}, ?external_id= | listed / returned with flags | hidden from list; GET by id still works |
| Unblock | yes | no (permanent) |
Events: user.blocked, user.unblocked, user.deleted.
Tenant invoice suspension (platform non-payment)
When a HUME project is past the unpaid grace period, the site suspends POST /invoices/generate on that tenant via POST /tenant/suspend-invoices. Metering, plans, and webhooks keep working.
After payment: POST /tenant/resume-invoices. Inspect with GET /tenant (invoices_suspended).