2026-07-26 · Balance alert webhooks
Two new webhook events — credit.low_balance when spendable credits cross a threshold you set, and credit.exhausted when they hit zero. Both track effective balance and fire once per episode rather than on every debit.
Balance alert webhooks
Additive release. Nothing existing changes behaviour — but you can now find out that a customer is running low before their next call fails, instead of inferring it from credit.consumed deltas.
Added — credit.low_balance
Fires when a customer’s effective balance crosses below a threshold you configure, while still remaining above zero. A soft warning: prompt a top-up, show a banner, send an email.
Off by default. The tenant threshold low_balance_threshold_mc starts at 0, which disables the event.
# Tenant default (admin session — owner or admin role)
curl -X PATCH https://api.quotastack.io/v1/admin/tenants/{tenant_id}/config \
-H "Cookie: qs_admin_session=..." \
-H "Idempotency-Key: config-low-balance:{tenantId}" \
-H "Content-Type: application/json" \
-d '{"low_balance_threshold_mc": 5000}'
Individual customers can override it via PATCH /v1/customers/{customer_id} with your normal API key — null inherits the tenant default, 0 turns the event off for that customer alone.
Added — credit.exhausted
Fires when effective balance crosses from above zero to zero or below. Always on, with no tenant toggle, because a zero balance is always worth knowing about.
Effective balance can go negative when a hold outlives the balance behind it — a block expiring while a reservation is still open, for instance. That still counts as exhausted.
How they behave
| Behaviour | Detail |
|---|---|
| Balance tracked | Effective — balance − reserved_balance − pending_balance, so a large reservation can trip a threshold with no ledger debit |
| Firing | Once per episode, on the crossing. Further debits while still below do not re-fire |
| Re-arming | A grant, restore, or reservation release that lifts balance back over the line re-arms the event |
| Both at once | A single drop from above the threshold to zero emits credit.exhausted only, never both |
| Failure mode | Best-effort — emission never fails the underlying debit, reservation, or expiry |
Payloads carry before_effective_balance, after_effective_balance, threshold_mc, and trigger, on top of the standard envelope.
Not included
These are webhooks only. QuotaStack does not send email and does not automatically top anyone up — the events are the signal, and what you do with them is yours.
Proactive warnings before a block’s expires_at shipped separately as credit.expiring_soon. credit.expired continues to fire when a block actually expires, and if that drop zeroes the customer out you will get credit.exhausted alongside it.
See credit.low_balance and credit.exhausted for the full payloads.
Loading…