Real-Time Webhooks Guide
Webhooks are one of the most powerful features in the Foru.ms API. They allow your application to receive real-time notifications when events occur in your forum, enabling you to build sophisticated automations, analytics, and integrations.
What Are Webhooks?
A webhook is an HTTP callback that sends data to a URL you specify when certain events occur. Instead of constantly polling the API to check for changes, webhooks push updates to you instantly.
Think of webhooks as a "reverse API" - instead of you requesting data from Foru.ms, we send data to you when something happens.
Available Events
Foru.ms supports webhooks for the following events:
Thread Events
thread.created- A new thread is createdthread.updated- A thread is edited or its status changesthread.deleted- A thread is deleted
Post Events
post.created- A new post (reply) is createdpost.updated- A post is editedpost.deleted- A post is deleted
User Events
user.registered- A new user registersuser.updated- A user profile is updated
Setting Up Webhooks
1. Create a Webhook Endpoint
First, create an endpoint in your application that can receive POST requests:
// Express.js example
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhooks/forum', (req, res) => {
const { event, data, timestamp, signature } = req.body;
// Verify the signature (see security section)
if (!verifySignature(req.body, signature)) {
return res.status(401).send('Invalid signature');
}
// Handle the event
console.log(`Received ${event} event:`, data);
// Process based on event type
switch(event) {
case 'thread.created':
handleNewThread(data);
break;
case 'post.created':
handleNewPost(data);
break;
// ... other events
}
// Always respond with 200 OK
res.sendStatus(200);
});
app.listen(3000);2. Register the Webhook via API
Use the Foru.ms API to register your webhook:
curl -X POST https://foru.ms/api/v1/webhooks \
-H "x-api-key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/forum",
"events": ["thread.created", "post.created"],
"secret": "your_webhook_secret"
}'Response:
{
"id": "webhook_abc123",
"url": "https://your-server.com/webhooks/forum",
"events": ["thread.created", "post.created"],
"active": true,
"secret": "your_webhook_secret",
"createdAt": "2024-12-14T00:00:00Z"
}Webhook Payload Structure
Every webhook request includes the following fields:
{
"event": "thread.created",
"timestamp": "2024-12-14T12:00:00Z",
"data": {
"id": "thread_123",
"title": "New Discussion Topic",
"body": "Thread content here...",
"user": {
"id": "user_456",
"username": "john_doe",
"displayName": "John Doe"
},
"tags": [
{"id": "tag_1", "name": "General"}
],
"createdAt": "2024-12-14T12:00:00Z"
},
"signature": "sha256=abc123..."
}The data field contains the full object that triggered the event (thread, post, or user).
Security: Signature Verification
Always verify webhook signatures to ensure requests are genuinely from Foru.ms.
How It Works
- Foru.ms generates an HMAC signature using your webhook secret
- The signature is sent in the
signaturefield - You verify the signature by computing it yourself and comparing
Verification Code
function verifySignature(payload, receivedSignature) {
const secret = process.env.WEBHOOK_SECRET;
// Create HMAC using the payload data
const payloadString = JSON.stringify({
event: payload.event,
timestamp: payload.timestamp,
data: payload.data
});
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payloadString)
.digest('hex');
// Compare signatures (use timing-safe comparison)
return crypto.timingSafeEqual(
Buffer.from(receivedSignature.replace('sha256=', '')),
Buffer.from(expectedSignature)
);
}Important: Never skip signature verification in production. Without it, anyone could send fake webhook requests to your endpoint.
Use Cases
1. AI-Powered Content Moderation
Automatically analyze new posts with your own AI model:
async function handleNewPost(data) {
// Send post content to your AI moderation service
const analysis = await moderationAPI.analyze(data.body);
if (analysis.flagged) {
// Automatically flag or delete the post
await forumAPI.deletePost(data.id);
// Notify moderators
await slack.send(`⚠️ Post flagged and removed: ${data.body.substring(0, 100)}`);
}
}2. Custom Analytics
Track engagement metrics in your data warehouse:
async function handleNewThread(data) {
await analytics.track({
event: 'thread_created',
userId: data.user.id,
properties: {
threadId: data.id,
title: data.title,
tags: data.tags.map(t => t.name),
timestamp: data.createdAt
}
});
}3. Cross-Platform Notifications
Share new threads to social media automatically:
async function handleNewThread(data) {
// Only share threads with specific tags
if (data.tags.some(tag => tag.name === 'Announcement')) {
await twitter.tweet(
`📢 New announcement: ${data.title}\n\nRead more: https://forum.example.com/thread/${data.slug}`
);
}
}4. User Onboarding
Welcome new users with automated messages:
async function handleUserRegistered(data) {
// Send welcome email
await email.send({
to: data.email,
subject: 'Welcome to our community!',
template: 'welcome',
data: { username: data.username }
});
// Create a welcome thread
await forumAPI.createThread({
title: `Welcome ${data.displayName}!`,
body: `Please introduce yourself to the community.`,
tagIds: ['welcome']
});
}Best Practices
1. Respond Quickly
Always respond with 200 OK as quickly as possible. If you need to do heavy processing, queue the work:
app.post('/webhooks/forum', async (req, res) => {
// Verify signature
if (!verifySignature(req.body, req.body.signature)) {
return res.status(401).send('Invalid signature');
}
// Queue the work
await queue.add('process-webhook', req.body);
// Respond immediately
res.sendStatus(200);
});2. Handle Retries
If your endpoint is down, Foru.ms will retry the webhook with exponential backoff. Make your handlers idempotent:
async function handleNewThread(data) {
// Check if we've already processed this thread
const exists = await db.threads.findOne({ id: data.id });
if (exists) {
console.log('Thread already processed, skipping');
return;
}
// Process the thread
await processThread(data);
// Mark as processed
await db.threads.insert({ id: data.id, processedAt: new Date() });
}3. Monitor Your Webhooks
Log webhook events and monitor for failures:
app.post('/webhooks/forum', async (req, res) => {
try {
await processWebhook(req.body);
// Log success
logger.info('Webhook processed', {
event: req.body.event,
id: req.body.data.id
});
res.sendStatus(200);
} catch (error) {
// Log error
logger.error('Webhook failed', {
event: req.body.event,
error: error.message
});
// Still respond with 200 to prevent retries for permanent failures
res.sendStatus(200);
}
});4. Filter Events
Only subscribe to events you actually need. This reduces noise and improves performance.
Testing Webhooks
Local Development
Use a tool like ngrok (opens in a new tab) to expose your local server:
# Start ngrok
ngrok http 3000
# Use the ngrok URL when registering your webhook
# https://abc123.ngrok.io/webhooks/forumTest Events
Send a test event to verify your webhook is working:
curl -X POST https://foru.ms/api/v1/integrations/test \
-H "x-api-key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"integrationId": "webhook_abc123"
}'Managing Webhooks
List All Webhooks
curl https://foru.ms/api/v1/webhooks \
-H "x-api-key: your_api_key"Delete a Webhook
curl -X DELETE https://foru.ms/api/v1/webhooks/webhook_abc123 \
-H "x-api-key: your_api_key"Troubleshooting
Webhook Not Firing
- Check that your endpoint is publicly accessible
- Verify you're subscribed to the correct events
- Check that the webhook is marked as
active - Review your server logs for errors
Signature Verification Failing
- Ensure you're using the correct secret
- Verify you're computing the HMAC over the exact payload structure
- Check that you're comparing the signatures correctly
Timeouts
If your endpoint takes too long to respond:
- Move heavy processing to a background queue
- Respond with
200 OKimmediately - Process the webhook asynchronously
Next Steps
- Read the API Reference for complete webhook documentation
- Explore Slack & Discord Integration for pre-built integrations
- Check out our GitHub examples (opens in a new tab) for sample webhook handlers
Webhooks unlock endless possibilities for automation and integration. Start building today!