wallet.low_balance
Fires when the workspace wallet balance drops below the configured alert threshold.
wallet.low_balance fires when a wallet debit brings the balance below the workspace's configured alert threshold. It is emitted at most once per threshold-crossing event; subsequent debits while already below the threshold do not re-fire until the balance recovers above the threshold and drops again.
This event is subscribable via workspace webhooks (POST /v1/webhooks).
{
"kind": "wallet.low_balance",
"event_id": "01900000-0000-7000-8000-000000000001",
"workspace_id": "01900000-0000-7000-8000-000000000002",
"occurred_at": "2026-06-27T10:00:00.000Z",
"data": {
"balance_minor": 4800,
"currency": "KES",
"threshold_minor": 5000
}
}Every webhook delivery includes the following request headers:
| Header | Description |
|---|---|
X-Sautikit-Signature | HMAC-SHA256 of the raw body, hex-encoded. Verify with your subscription secret. |
X-Sautikit-Idempotency-Key | Unique delivery ID for deduplication. |
X-Sautikit-Event | Literal event kind: wallet.low_balance. |
event_id or the X-Sautikit-Idempotency-Key header.dead_letter.import { createHmac } from "node:crypto";
export async function POST(req) {
const sig = req.headers["x-sautikit-signature"];
const body = await req.text();
const expected = createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(body)
.digest("hex");
if (sig !== expected) return new Response("Forbidden", { status: 403 });
const event = JSON.parse(body);
if (event.kind === "wallet.low_balance") {
const { balance_minor, currency, threshold_minor } = event.data;
console.warn(`Low balance: ${balance_minor / 100} ${currency} (threshold: ${threshold_minor / 100})`);
// trigger top-up, send Slack alert, page on-call...
}
return new Response("OK", { status: 200 });
}events: ["wallet.low_balance"].wallet.top_up to clear alerts when funds are replenished.