Billing Webhooks
Receive webhook notifications for SALZ billing events -- usage thresholds, plan changes, and payment status updates.
SALZ can send webhook notifications to your application when billing events occur. This lets you react to usage changes, plan upgrades, and payment issues without polling the API.
Available Events
| Event | Description |
|---|---|
usage.threshold.80 | Account has used 80% of monthly quota |
usage.threshold.100 | Account has reached 100% of monthly quota |
plan.upgraded | Account upgraded to a higher tier |
plan.downgraded | Account downgraded to a lower tier |
payment.succeeded | Monthly payment was processed successfully |
payment.failed | Payment attempt failed |
Setting Up Webhooks
Billing webhooks are available on the Pro and Enterprise plans.
- Go to your SALZ dashboard.
- Navigate to Settings > Webhooks.
- Enter your webhook endpoint URL (must be HTTPS).
- Select the events you want to receive.
- Save your configuration.
SALZ will send a test event to verify your endpoint is reachable.
Webhook Payload
All webhook events follow the same JSON structure:
{
"event": "usage.threshold.80",
"timestamp": "2025-03-15T14:30:00Z",
"data": {
"account_id": "acc_abc123",
"current_usage": 4000,
"monthly_limit": 5000,
"plan": "pro",
"billing_period_end": "2025-04-14T00:00:00Z"
}
}
Handling Webhooks
Your endpoint should return a 200 status code within 10 seconds to acknowledge receipt. If SALZ does not receive a 200, it will retry the webhook up to 3 times with exponential backoff (1 minute, 5 minutes, 30 minutes).
Example: Node.js / Express
app.post('/webhooks/salz', express.json(), (req, res) => {
const { event, data } = req.body;
switch (event) {
case 'usage.threshold.80':
console.log(`Account ${data.account_id} at 80% usage`);
// Send internal alert or notify your users
break;
case 'usage.threshold.100':
console.log(`Account ${data.account_id} hit quota limit`);
// Prompt user to upgrade
break;
case 'payment.failed':
console.log(`Payment failed for ${data.account_id}`);
// Notify your billing team
break;
}
res.status(200).json({ received: true });
});
Example: Next.js API Route
export async function POST(request) {
const body = await request.json();
const { event, data } = body;
if (event === 'usage.threshold.100') {
// Handle quota exhaustion
await notifyAdmin(data.account_id);
}
return Response.json({ received: true });
}
Verifying Webhooks
Each webhook request includes a X-Salz-Signature header containing an HMAC-SHA256 signature of the request body. Verify this signature to confirm the webhook came from SALZ and was not tampered with.
import crypto from 'crypto';
function verifyWebhookSignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Your webhook signing secret is available in Settings > Webhooks in the dashboard.
Best Practices
- Always verify signatures. Do not trust incoming webhooks without checking the HMAC signature.
- Respond quickly. Return
200before doing heavy processing. Queue the event for async handling if needed. - Handle duplicates. Retries can cause duplicate deliveries. Use the event timestamp and account ID to deduplicate.
- Use HTTPS. Webhook endpoints must use HTTPS to protect the payload in transit.
- Log everything. Store raw webhook payloads for debugging and audit purposes.