Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.topograph.co/llms.txt

Use this file to discover all available pages before exploring further.

Topograph can notify you about three billing events:
  1. Low balance: your prepaid credit balance crosses a configured threshold.
  2. High usage: your spend in a rolling window reaches a configured threshold. High usage has two independent passes, described below.
  3. Auto top-up: an automatic recharge succeeds or fails.
Each notification can go out as an email to your account admins and as a webhook event delivered through the same webhook endpoint setup as company data events. You can independently enable or disable each channel per notification kind.
All master toggles are off by default on new accounts. Nothing fires until an admin enables the specific kind they want from the Billing page. Channel sub-toggles (email / webhook) start at on, so flipping a master routes through both channels with a single click.

How notifications fire

Notifications are evaluated after billable usage changes your balance or spend window. A notification is recorded once per threshold crossing, not once per request. The tier is rearmed when you refill or usage drops below the threshold and later crosses it again.

Global vs per-workspace high usage

High usage runs two independent passes on every reserve. Both can fire in the same evaluation, and overriding one does not affect the other:
  • Global (account aggregate): sums billable usage across every workspace over the configured global period and checks it against your global tiers. Use this to alert on total account burn regardless of which workspace drove it.
  • Per-workspace: sums billable usage for a single workspace over the configured workspace period and checks it against workspace tiers. Account-level workspace settings act as defaults; specific workspaces can override them.
Each pass has its own master toggle, channels, period, and tier list. High usage uses formal absolute thresholds. There is no multiplier or baseline comparison. Auto top-up notifications fire when an automatic top-up succeeds or fails.

Channels

Every notification kind has two channels, configured independently:
  • Email: sent to account admins.
  • Webhook: delivered through the same endpoints you already set up for company.updated.
You control each channel with a boolean. A notification is sent on a given channel when the kind’s master switch and the channel switch are both on. Turning both channel switches off while leaving the master on keeps the event visible in recent notification history without dispatching email or webhook alerts.

Webhook event types

All billing webhook payloads carry a type and version: "1". Future schema changes will emit new event types rather than mutate v1.

billing.low_balance.triggered

{
  "type": "billing.low_balance.triggered",
  "version": "1",
  "accountId": "acc_...",
  "tier": "warning",
  "balanceCents": 4523,
  "thresholdCents": 5000,
  "autoTopupEnabled": true,
  "firedAt": "2026-04-14T10:23:45.000Z"
}
The tier field is one of warning, critical, or depleted. You can configure multiple tiers via the REST API or dashboard.

billing.high_usage.triggered

The high-usage event now carries a scope field that tells you which pass fired:
  • scope: "workspace" with a set workspaceId: the per-workspace pass fired for that workspace.
  • scope: "global" with workspaceId: null: the global aggregate pass fired for the whole account.
Per-workspace example:
{
  "type": "billing.high_usage.triggered",
  "version": "1",
  "accountId": "acc_...",
  "scope": "workspace",
  "workspaceId": "ws_...",
  "tier": "warning",
  "periodMinutes": 60,
  "periodSpendCents": 2300,
  "thresholdCents": 2000,
  "balanceCents": 87000,
  "firedAt": "2026-04-14T10:23:45.000Z"
}
Global aggregate example:
{
  "type": "billing.high_usage.triggered",
  "version": "1",
  "accountId": "acc_...",
  "scope": "global",
  "workspaceId": null,
  "tier": "critical",
  "periodMinutes": 60,
  "periodSpendCents": 61000,
  "thresholdCents": 50000,
  "balanceCents": 200000,
  "firedAt": "2026-04-14T10:23:45.000Z"
}
Each pass starts with a default warning tier. Add or edit tiers from the dashboard or via PATCH. Workspace overrides only affect the per-workspace pass. Setting highUsageEnabled: false on a workspace override stops that workspace from firing its own per-workspace notifications but does not silence the global pass. If you want to silence the global pass too, turn off globalHighUsageEnabled at the account level.

billing.auto_topup.succeeded

{
  "type": "billing.auto_topup.succeeded",
  "version": "1",
  "accountId": "acc_...",
  "amountCents": 10000,
  "previousBalanceCents": 350,
  "newBalanceCents": 10350,
  "thresholdCents": 5000,
  "paymentIntentId": "pi_...",
  "firedAt": "2026-04-14T10:23:45.000Z"
}

billing.auto_topup.failed

{
  "type": "billing.auto_topup.failed",
  "version": "1",
  "accountId": "acc_...",
  "attemptedAmountCents": 10000,
  "currentBalanceCents": 350,
  "errorMessage": "card_declined",
  "paymentIntentId": null,
  "autoTopupDisabled": true,
  "firedAt": "2026-04-14T10:23:45.000Z"
}
When an auto top-up attempt fails, auto top-up is disabled to prevent retry loops. You receive this event once and then need to update your payment method to re-enable it.

Configuration API

All endpoints are under /v2/billing/notifications and require your standard x-api-key header.

Read the resolved config

GET /v2/billing/notifications/config
Returns the fully merged config: your stored overrides layered on top of the defaults. You always receive a complete shape, even if you have not configured anything yet. A brand-new account that has never touched the config sees every master at false and every channel at true. Each kind ships with a single warning tier so flipping the master on immediately fires on one sensible threshold. Add more tiers (critical, depleted, extra bands) via PATCH if you want finer granularity.
{
  "lowBalanceEnabled": false,
  "lowBalanceEmailEnabled": true,
  "lowBalanceWebhookEnabled": true,
  "lowBalanceTiers": [
    { "tier": "warning", "cents": 100000 }
  ],
  "globalHighUsageEnabled": false,
  "globalHighUsageEmailEnabled": true,
  "globalHighUsageWebhookEnabled": true,
  "globalHighUsagePeriodMinutes": 1440,
  "globalHighUsageTiers": [
    { "tier": "warning", "cents": 100000 }
  ],
  "highUsageEnabled": false,
  "highUsageEmailEnabled": true,
  "highUsageWebhookEnabled": true,
  "highUsagePeriodMinutes": 1440,
  "highUsageTiers": [
    { "tier": "warning", "cents": 100000 }
  ],
  "autoTopupNotificationsEnabled": false,
  "autoTopupEmailEnabled": true,
  "autoTopupWebhookEnabled": true
}

Update the config

PATCH /v2/billing/notifications/config
Content-Type: application/json

{
  "lowBalanceTiers": [
    { "tier": "warning", "cents": 10000 },
    { "tier": "critical", "cents": 2000 },
    { "tier": "depleted", "cents": 0 }
  ],
  "highUsagePeriodMinutes": 120,
  "highUsageTiers": [
    { "tier": "critical", "cents": 50000 },
    { "tier": "warning", "cents": 10000 }
  ],
  "lowBalanceEmailEnabled": false
}
All fields are optional. Any field you omit keeps its persisted value. You can send just {"lowBalanceEmailEnabled": false} to turn off low-balance emails without touching anything else.

List recent notification events

GET /v2/billing/notifications/recent?limit=50
Returns the most recent billing notification events for your account, ordered newest first. Each row includes the kind, identifier, original payload, and delivery flags for email and webhook channels.

Workspace overrides

If you use workspaces, you can override the high-usage rules for a specific workspace. Low-balance and auto-topup stay at the account level.
GET /v2/billing/notifications/workspaces/{workspaceId}/config
PATCH /v2/billing/notifications/workspaces/{workspaceId}/config
DELETE /v2/billing/notifications/workspaces/{workspaceId}/config
GET returns both the resolved account config and the raw workspace override row, so you can see which fields are overridden and which are inherited. PATCH upserts an override; any null field falls back to the account config at evaluation time. DELETE removes the override row (the workspace then inherits everything). Example: give workspace ws_batch a much higher high-usage floor so nightly backfills don’t page you, while keeping everything else at the account defaults:
PATCH /v2/billing/notifications/workspaces/ws_batch/config
Content-Type: application/json

{
  "highUsageTiers": [
    { "tier": "critical", "cents": 500000 },
    { "tier": "warning", "cents": 100000 }
  ]
}

Verifying webhooks

Billing webhooks use the same webhook endpoint setup as your company.updated webhooks. The signature verification flow is identical: Verify billing webhook signatures the same way you verify company data webhook signatures, then branch on the type field in the payload. See the Webhooks guide for the full verification walkthrough and retry semantics.

Idempotency

Every billing notification is deduplicated at evaluation time. If the same threshold crossing is evaluated more than once, only one customer-visible notification is recorded. High-usage notifications are deduplicated inside their rolling evaluation window, so two evaluations of the same threshold crossing do not produce duplicate customer alerts.

Rearm semantics

Threshold notifications fire once when you cross a tier, then disarm. They rearm when the condition has clearly reversed:
  • Low balance: when the balance recovers above the tier threshold.
  • High usage: when the rolling spend falls below the tier threshold.
This means a single balance drop will not spam you with repeated depleted notifications, but a refill followed by another drop can send a fresh notification. Auto-topup notifications are event-based, not threshold-based. Each attempt is evaluated independently.