
# Billing webhooks

Billing events describe posted credit changes. API-key events provide a security audit signal but never expose the secret key.

## Events and payloads

| Event | When it fires | Recommended handling |
|---|---|---|
| `credits.deducted` | Billable verification usage is posted. | Reconcile by `verificationId`. |
| `credits.low` | Balance crosses the configured threshold. | Notify billing owners once per logical event ID. |
| `credits.topped_up` | A top-up posts successfully. | Reconcile the new balance. |
| `credits.granted` | Promotional credit is granted. | Record the grant and expiry policy. |
| `credits.promo_expired` | Unused promotional credit expires. | Reconcile the reduction without treating it as usage. |
| `api_key.created` | A key is created. | Audit the name, environment, type and prefix. |
| `api_key.revoked` | A key is revoked. | Remove dependent access and investigate unexpected revocation. |

```json
{
  "version": "2026-08-11",
  "id": "evt_credit_deducted_01",
  "type": "credits.deducted",
  "createdAt": "2026-08-15T18:00:00.000Z",
  "deliveryId": "del_credit_deducted_01",
  "data": { "verificationId": "ver_01", "amount": "0.2000", "currency": "USD" }
}
```

```json
[
  { "type": "credits.low", "data": { "orgId": "org_01", "balance": "20.0000", "threshold": "25.0000", "currency": "USD" } },
  { "type": "credits.topped_up", "data": { "orgId": "org_01", "amount": "500.0000", "balanceAfter": "1020.0000", "currency": "USD" } },
  { "type": "credits.granted", "data": { "orgId": "org_01", "amount": "50.0000", "balanceAfter": "1070.0000", "currency": "USD", "grantId": "grt_01" } },
  { "type": "credits.promo_expired", "data": { "orgId": "org_01", "amount": "10.0000", "balanceAfter": "1060.0000", "currency": "USD", "grantId": "grt_01" } },
  { "type": "api_key.created", "data": { "apiKeyId": "key_01", "name": "Production server", "environment": "PRODUCTION", "keyType": "SECRET", "keyPrefix": "sk_live_8p4" } },
  { "type": "api_key.revoked", "data": { "apiKeyId": "key_01", "name": "Production server", "environment": "PRODUCTION" } }
]
```

## Field reference

| Field | Type | Nullable | Meaning |
|---|---|---:|---|
| `orgId`, `verificationId`, `grantId`, `apiKeyId` | string | Event-dependent | Related organisation, usage, grant and key IDs. |
| `amount`, `balance`, `balanceAfter`, `threshold` | string | Event-dependent | Fixed-scale decimal currency amounts with four fractional digits. Parse with a decimal library; do not use binary floating-point for ledger arithmetic. |
| `currency` | string | No for credit events | ISO 4217 currency code such as `USD`. |
| `name` | string | No for key events | Customer-visible key name. |
| `environment` | string | No for key events | `SANDBOX` or `PRODUCTION`. |
| `keyType` | string | No on creation | Public key classification, for example `SECRET` or `PUBLISHABLE`. |
| `keyPrefix` | string | No on creation | Non-secret prefix for identifying the key. The full secret is never delivered. |

Use billing ledger and API-key read endpoints for authoritative current state. Financial side effects must be idempotent by envelope `id`, while reconciliation should also use the referenced verification, grant or top-up record.
