Using Webhooks for Real-Time Credit Updates
How to leverage webhooks to keep your application in sync with credit transactions and purchases.
By cred.diy Team

Webhooks are the backbone of real-time integrations. Instead of constantly polling for updates, webhooks push events to your application the moment they happen. This guide covers everything you need to know about implementing webhooks with cred.diy.
What Are Webhooks?
Webhooks are HTTP callbacks that notify your application when events occur. When a user purchases credits, for example, cred.diy sends a POST request to your specified URL with details about the purchase.
Benefits of Webhooks
- Real-time updates: No polling delays
- Efficient: Only receive relevant events
- Reliable: Built-in retry mechanisms
- Decoupled: Your app doesn't need to track state
Available Webhook Events
cred.diy sends webhooks for these events:
| Event | Description |
|---|---|
credits.issued | Credits were issued to a user |
credits.deducted | Credits were deducted from a user |
credits.low | User balance fell below threshold |
purchase.completed | Credit purchase was successful |
purchase.failed | Credit purchase failed |
referral.completed | Referral reward was issued |
Setting Up Webhooks
Step 1: Create an Endpoint
// Express.js example
app.post('/webhooks/cred', express.raw({ type: 'application/json' }), (req, res) => {
const payload = req.body;
const signature = req.headers['x-cred-signature'];
// Process the webhook
handleWebhook(payload, signature);
// Always respond quickly
res.status(200).send('OK');
});
Step 2: Register in Dashboard
- Go to Webhooks in your dashboard
- Click Add Endpoint
- Enter your URL:
https://yourapp.com/webhooks/cred - Select events to subscribe to
- Copy the signing secret
Step 3: Verify Signatures
Always verify webhook signatures to ensure authenticity:
const crypto = require('crypto');
const verifySignature = (payload, signature, secret) => {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
};
app.post('/webhooks/cred', (req, res) => {
const signature = req.headers['x-cred-signature'];
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process verified webhook
processWebhook(req.body);
res.status(200).send('OK');
});
Handling Different Events
Credits Issued
const handleCreditsIssued = async (event) => {
const { user_id, amount, new_balance, reason } = event;
// Update local cache
await cache.set(`balance:${user_id}`, new_balance);
// Send notification
await sendPushNotification(user_id, {
title: 'Credits Received!',
body: `You received ${amount} credits. New balance: ${new_balance}`
});
// Update analytics
await analytics.track('credits_received', { user_id, amount });
};
Purchase Completed
const handlePurchaseCompleted = async (event) => {
const { user_id, amount, price_paid, pricing_tier } = event;
// Send receipt email
await sendEmail(user_id, 'receipt', {
credits: amount,
amount_paid: price_paid,
tier_name: pricing_tier.name
});
// Log for accounting
await recordRevenue({
user_id,
amount: price_paid,
type: 'credit_purchase'
});
};
Low Balance Warning
const handleLowBalance = async (event) => {
const { user_id, current_balance, threshold } = event;
// Send warning email
await sendEmail(user_id, 'low_balance', {
balance: current_balance,
refill_link: `https://yourapp.com/buy-credits`
});
// Show in-app notification
await createNotification(user_id, {
type: 'warning',
message: 'Your credit balance is running low!'
});
};
Best Practices
1. Respond Quickly
Return 200 immediately, process asynchronously:
app.post('/webhooks/cred', (req, res) => {
// Acknowledge immediately
res.status(200).send('OK');
// Process in background
processWebhookAsync(req.body).catch(console.error);
});
2. Handle Duplicates
Webhooks may be sent multiple times:
const processWebhook = async (event) => {
const eventId = event.id;
// Check if already processed
const processed = await redis.get(`webhook:${eventId}`);
if (processed) return;
// Process the event
await handleEvent(event);
// Mark as processed (expire after 24 hours)
await redis.setex(`webhook:${eventId}`, 86400, 'true');
};
3. Handle Failures Gracefully
Implement exponential backoff for your own retries:
const processWithRetry = async (event, attempt = 1) => {
try {
await handleEvent(event);
} catch (error) {
if (attempt < 5) {
const delay = Math.pow(2, attempt) * 1000;
await sleep(delay);
return processWithRetry(event, attempt + 1);
}
throw error;
}
};
4. Log Everything
const processWebhook = async (event) => {
console.log('Webhook received:', {
type: event.type,
id: event.id,
timestamp: new Date().toISOString()
});
try {
await handleEvent(event);
console.log('Webhook processed successfully:', event.id);
} catch (error) {
console.error('Webhook processing failed:', {
eventId: event.id,
error: error.message
});
throw error;
}
};
Testing Webhooks
Use the Dashboard
cred.diy provides a webhook testing tool:
- Go to Webhooks > Test
- Select an event type
- Click Send Test Event
- Check your endpoint logs
Local Development
Use ngrok for local testing:
ngrok http 3000
# Use the ngrok URL in your webhook settings
Troubleshooting
Webhook Not Received
- Verify the URL is publicly accessible
- Check firewall rules
- Confirm the endpoint returns 200
- Review the delivery logs in dashboard
Invalid Signature
- Ensure you're using the raw body for verification
- Check that the secret matches your dashboard
- Verify no middleware is modifying the body
Conclusion
Webhooks transform your application from a polling-based system to a reactive, real-time platform. By implementing proper webhook handling, you'll provide a better user experience and maintain accurate credit balances.
Configure your webhooks in the dashboard.

Building AI-Powered Apps with Credit Metering
How to implement per-request credit billing for AI features like image generation, chat completions, and embeddings.

Implementing Usage-Based Pricing with cred.diy
A step-by-step guide to integrating credit-based pricing into your application using our REST API and webhooks.