Skip to Content
Foru.ms logo

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

Post Events

User Events

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://api.foru.ms/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

  1. Foru.ms generates an HMAC signature using your webhook secret
  2. The signature is sent in the signature field
  3. 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.`, tags: ['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  to expose your local server:

# Start ngrok ngrok http 3000 # Use the ngrok URL when registering your webhook # https://abc123.ngrok.io/webhooks/forum

Test Events

Send a test event to verify your webhook is working:

curl -X POST https://api.foru.ms/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://api.foru.ms/v1/webhooks \ -H "x-api-key: your_api_key"

Delete a Webhook

curl -X DELETE https://api.foru.ms/v1/webhooks/webhook_abc123 \ -H "x-api-key: your_api_key"

Troubleshooting

Webhook Not Firing

  1. Check that your endpoint is publicly accessible
  2. Verify you’re subscribed to the correct events
  3. Check that the webhook is marked as active
  4. Review your server logs for errors

Signature Verification Failing

  1. Ensure you’re using the correct secret
  2. Verify you’re computing the HMAC over the exact payload structure
  3. Check that you’re comparing the signatures correctly

Timeouts

If your endpoint takes too long to respond:

  1. Move heavy processing to a background queue
  2. Respond with 200 OK immediately
  3. Process the webhook asynchronously

Next Steps

Webhooks unlock endless possibilities for automation and integration. Start building today!