> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nudj.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementation Guide

> Step-by-step guide to implement webhook handling with code examples in multiple languages

## Overview

This guide walks you through implementing webhook endpoints to receive real-time notifications from the Nudj platform. You'll learn how to configure webhooks, handle incoming requests, and implement best practices for production systems.

## Prerequisites

<CardGroup cols={2}>
  <Card title="Admin API Access" icon="key">
    You need Admin API credentials to configure webhooks
  </Card>

  <Card title="HTTPS Endpoint" icon="shield">
    Webhook URLs must use HTTPS in production
  </Card>

  <Card title="Event Processing" icon="gear">
    A system to handle and process incoming events
  </Card>

  <Card title="Authentication" icon="lock">
    Mechanism to verify webhook authenticity
  </Card>
</CardGroup>

## Step 1: Configure Your Webhook

First, use the Admin API to configure your webhook endpoint:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT "https://{subdomain}.nudj.cx/api/v2/admin/webhooks/configs" \
    -H "Content-Type: application/json" \
    -H "x-api-token: YOUR_ADMIN_API_TOKEN" \
    -d '[
      {
        "events": [
          "challenge-completion",
          "achievement-completion",
          "reward-claim"
        ],
        "url": "https://your-app.com/webhooks/nudj",
        "httpMethod": "POST",
        "isEnabled": true,
        "maxRetries": 3,
        "headers": {
          "Authorization": "Bearer your-webhook-secret",
          "X-Webhook-Source": "nudj-platform"
        }
      }
    ]'
  ```

  ```javascript JavaScript (Node.js) theme={null}
  const response = await fetch(`https://${subdomain}.nudj.cx/api/v2/admin/webhooks/configs`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'x-api-token': process.env.NUDJ_ADMIN_API_TOKEN
    },
    body: JSON.stringify([
      {
        events: [
          'challenge-completion',
          'achievement-completion', 
          'reward-claim'
        ],
        url: 'https://your-app.com/webhooks/nudj',
        httpMethod: 'POST',
        isEnabled: true,
        maxRetries: 3,
        headers: {
          'Authorization': `Bearer ${process.env.WEBHOOK_SECRET}`,
          'X-Webhook-Source': 'nudj-platform'
        }
      }
    ])
  });
  ```

  ```python Python theme={null}
  import requests
  import os

  response = requests.put(
      f"https://{subdomain}.nudj.cx/api/v2/admin/webhooks/configs",
      headers={
          "Content-Type": "application/json",
          "x-api-token": os.getenv("NUDJ_ADMIN_API_TOKEN")
      },
      json=[
          {
              "events": [
                  "challenge-completion",
                  "achievement-completion",
                  "reward-claim"
              ],
              "url": "https://your-app.com/webhooks/nudj",
              "httpMethod": "POST",
              "isEnabled": True,
              "maxRetries": 3,
              "headers": {
                  "Authorization": f"Bearer {os.getenv('WEBHOOK_SECRET')}",
                  "X-Webhook-Source": "nudj-platform"
              }
          }
      ]
  )
  ```
</CodeGroup>

## Step 2: Implement Webhook Endpoint

Create an endpoint to receive and process webhook events:

<CodeGroup>
  ```javascript Node.js (Express) theme={null}
  const express = require('express');
  const crypto = require('crypto');
  const app = express();

  // Middleware to parse JSON with raw body for signature verification
  app.use('/webhooks', express.json({
    verify: (req, res, buf, encoding) => {
      req.rawBody = buf;
    }
  }));

  // Webhook endpoint
  app.post('/webhooks/nudj', async (req, res) => {
    try {
      // Verify the webhook is from Nudj
      if (!verifyWebhookSignature(req)) {
        return res.status(401).send('Unauthorized');
      }

      const event = req.body;
      console.log('Received webhook:', event.eventSubCategory);

      // Process the event
      await processWebhookEvent(event);

      // Always respond with 200 for successful processing
      res.status(200).send('OK');
    } catch (error) {
      console.error('Webhook processing error:', error);
      res.status(500).send('Internal Server Error');
    }
  });

  function verifyWebhookSignature(req) {
    const expectedAuth = `Bearer ${process.env.WEBHOOK_SECRET}`;
    const receivedAuth = req.get('Authorization');
    const webhookSource = req.get('X-Webhook-Source');
    
    return receivedAuth === expectedAuth && webhookSource === 'nudj-platform';
  }

  async function processWebhookEvent(event) {
    switch (event.eventSubCategory) {
      case 'challenge-completion':
        await handleChallengeCompletion(event);
        break;
      case 'achievement-completion':
        await handleAchievementCompletion(event);
        break;
      case 'reward-claim':
        await handleRewardClaim(event);
        break;
      default:
        console.log('Unhandled event type:', event.eventSubCategory);
    }
  }

  async function handleChallengeCompletion(event) {
    const { userId, eventSourceId, payload } = event;
    
    // Example: Send congratulatory email
    await sendEmail(userId, {
      subject: 'Challenge Completed!',
      template: 'challenge-completion',
      data: {
        challengeName: payload.challengeName,
        pointsEarned: payload.pointsEarned
      }
    });
    
    // Example: Update external system
    await updateExternalProfile(userId, {
      lastChallengeCompleted: eventSourceId,
      totalChallengesCompleted: await getChallengeCount(userId) + 1
    });
  }

  app.listen(3000, () => {
    console.log('Webhook server listening on port 3000');
  });
  ```

  ```python Python (Flask) theme={null}
  from flask import Flask, request, jsonify
  import os
  import hashlib
  import hmac
  import json

  app = Flask(__name__)

  @app.route('/webhooks/nudj', methods=['POST'])
  def handle_webhook():
      try:
          # Verify the webhook is from Nudj
          if not verify_webhook_signature(request):
              return jsonify({'error': 'Unauthorized'}), 401

          event = request.json
          print(f"Received webhook: {event.get('eventSubCategory')}")

          # Process the event
          process_webhook_event(event)

          return jsonify({'status': 'success'}), 200
      except Exception as e:
          print(f"Webhook processing error: {e}")
          return jsonify({'error': 'Internal Server Error'}), 500

  def verify_webhook_signature(request):
      expected_auth = f"Bearer {os.getenv('WEBHOOK_SECRET')}"
      received_auth = request.headers.get('Authorization')
      webhook_source = request.headers.get('X-Webhook-Source')
      
      return (received_auth == expected_auth and 
              webhook_source == 'nudj-platform')

  def process_webhook_event(event):
      event_type = event.get('eventSubCategory')
      
      handlers = {
          'challenge-completion': handle_challenge_completion,
          'achievement-completion': handle_achievement_completion,
          'reward-claim': handle_reward_claim
      }
      
      handler = handlers.get(event_type)
      if handler:
          handler(event)
      else:
          print(f"Unhandled event type: {event_type}")

  def handle_challenge_completion(event):
      user_id = event.get('userId')
      payload = event.get('payload', {})
      
      # Example: Send congratulatory message
      send_notification(user_id, {
          'type': 'challenge_completed',
          'message': f"Congratulations! You completed {payload.get('challengeName')}",
          'points_earned': payload.get('pointsEarned')
      })
      
      # Example: Update user stats
      update_user_stats(user_id, 'challenges_completed', 1)

  def handle_achievement_completion(event):
      # Implementation for achievement completion
      pass

  def handle_reward_claim(event):
      # Implementation for reward claim
      pass

  if __name__ == '__main__':
      app.run(host='0.0.0.0', port=5000)
  ```

  ```ruby Ruby (Sinatra) theme={null}
  require 'sinatra'
  require 'json'

  set :port, 4567

  post '/webhooks/nudj' do
    begin
      # Verify the webhook is from Nudj
      unless verify_webhook_signature(request)
        halt 401, 'Unauthorized'
      end

      # Parse the JSON payload
      event = JSON.parse(request.body.read)
      puts "Received webhook: #{event['eventSubCategory']}"

      # Process the event
      process_webhook_event(event)

      status 200
      body 'OK'
    rescue => e
      puts "Webhook processing error: #{e.message}"
      status 500
      body 'Internal Server Error'
    end
  end

  def verify_webhook_signature(request)
    expected_auth = "Bearer #{ENV['WEBHOOK_SECRET']}"
    received_auth = request.env['HTTP_AUTHORIZATION']
    webhook_source = request.env['HTTP_X_WEBHOOK_SOURCE']
    
    received_auth == expected_auth && webhook_source == 'nudj-platform'
  end

  def process_webhook_event(event)
    case event['eventSubCategory']
    when 'challenge-completion'
      handle_challenge_completion(event)
    when 'achievement-completion'
      handle_achievement_completion(event)
    when 'reward-claim'
      handle_reward_claim(event)
    else
      puts "Unhandled event type: #{event['eventSubCategory']}"
    end
  end

  def handle_challenge_completion(event)
    user_id = event['userId']
    payload = event['payload']
    
    # Example: Send notification
    send_notification(user_id, {
      type: 'challenge_completed',
      message: "You completed #{payload['challengeName']}!",
      points_earned: payload['pointsEarned']
    })
  end
  ```

  ```php PHP theme={null}
  <?php
  error_reporting(E_ALL);
  ini_set('display_errors', 1);

  // Get the raw POST data
  $input = file_get_contents('php://input');
  $event = json_decode($input, true);

  // Verify webhook signature
  if (!verifyWebhookSignature()) {
      http_response_code(401);
      die('Unauthorized');
  }

  try {
      echo "Received webhook: " . $event['eventSubCategory'] . "\n";
      
      // Process the event
      processWebhookEvent($event);
      
      http_response_code(200);
      echo 'OK';
  } catch (Exception $e) {
      error_log("Webhook processing error: " . $e->getMessage());
      http_response_code(500);
      echo 'Internal Server Error';
  }

  function verifyWebhookSignature() {
      $expectedAuth = 'Bearer ' . $_ENV['WEBHOOK_SECRET'];
      $receivedAuth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
      $webhookSource = $_SERVER['HTTP_X_WEBHOOK_SOURCE'] ?? '';
      
      return $receivedAuth === $expectedAuth && $webhookSource === 'nudj-platform';
  }

  function processWebhookEvent($event) {
      switch ($event['eventSubCategory']) {
          case 'challenge-completion':
              handleChallengeCompletion($event);
              break;
          case 'achievement-completion':
              handleAchievementCompletion($event);
              break;
          case 'reward-claim':
              handleRewardClaim($event);
              break;
          default:
              error_log('Unhandled event type: ' . $event['eventSubCategory']);
      }
  }

  function handleChallengeCompletion($event) {
      $userId = $event['userId'];
      $payload = $event['payload'];
      
      // Example: Log the completion
      error_log("User {$userId} completed challenge: " . $payload['challengeName']);
      
      // Example: Send notification
      sendNotification($userId, [
          'type' => 'challenge_completed',
          'message' => "Congratulations! You completed {$payload['challengeName']}",
          'points_earned' => $payload['pointsEarned']
      ]);
  }

  function sendNotification($userId, $data) {
      // Implementation for sending notifications
      error_log("Sending notification to user {$userId}: " . json_encode($data));
  }
  ?>
  ```

  ```go Go (Gin) theme={null}
  package main

  import (
      "encoding/json"
      "fmt"
      "log"
      "net/http"
      "os"

      "github.com/gin-gonic/gin"
  )

  type WebhookEvent struct {
      ID               string      `json:"id"`
      EventCategory    string      `json:"eventCategory"`
      EventSubCategory string      `json:"eventSubCategory"`
      OrganisationID   string      `json:"organisationId"`
      CommunityID      string      `json:"communityId"`
      UserID           string      `json:"userId"`
      EventSourceID    string      `json:"eventSourceId"`
      Payload          interface{} `json:"payload"`
      Tags             []string    `json:"tags"`
      CreatedAt        string      `json:"createdAt"`
  }

  func main() {
      r := gin.Default()
      
      r.POST("/webhooks/nudj", handleWebhook)
      
      log.Println("Webhook server starting on :8080")
      r.Run(":8080")
  }

  func handleWebhook(c *gin.Context) {
      // Verify webhook signature
      if !verifyWebhookSignature(c) {
          c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
          return
      }

      var event WebhookEvent
      if err := c.ShouldBindJSON(&event); err != nil {
          log.Printf("Error parsing webhook: %v", err)
          c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"})
          return
      }

      log.Printf("Received webhook: %s", event.EventSubCategory)

      // Process the event
      if err := processWebhookEvent(event); err != nil {
          log.Printf("Error processing webhook: %v", err)
          c.JSON(http.StatusInternalServerError, gin.H{"error": "Processing failed"})
          return
      }

      c.JSON(http.StatusOK, gin.H{"status": "success"})
  }

  func verifyWebhookSignature(c *gin.Context) bool {
      expectedAuth := fmt.Sprintf("Bearer %s", os.Getenv("WEBHOOK_SECRET"))
      receivedAuth := c.GetHeader("Authorization")
      webhookSource := c.GetHeader("X-Webhook-Source")
      
      return receivedAuth == expectedAuth && webhookSource == "nudj-platform"
  }

  func processWebhookEvent(event WebhookEvent) error {
      switch event.EventSubCategory {
      case "challenge-completion":
          return handleChallengeCompletion(event)
      case "achievement-completion":
          return handleAchievementCompletion(event)
      case "reward-claim":
          return handleRewardClaim(event)
      default:
          log.Printf("Unhandled event type: %s", event.EventSubCategory)
          return nil
      }
  }

  func handleChallengeCompletion(event WebhookEvent) error {
      payload, _ := json.Marshal(event.Payload)
      log.Printf("User %s completed a challenge: %s", event.UserID, string(payload))
      
      // Add your business logic here
      // - Send notifications
      // - Update external systems
      // - Trigger other processes
      
      return nil
  }

  func handleAchievementCompletion(event WebhookEvent) error {
      // Implementation for achievement completion
      return nil
  }

  func handleRewardClaim(event WebhookEvent) error {
      // Implementation for reward claim
      return nil
  }
  ```
</CodeGroup>

## Step 3: Implement Event Handlers

Create specific handlers for different event types:

<CodeGroup>
  ```javascript Challenge Completion Handler theme={null}
  async function handleChallengeCompletion(event) {
    const { userId, communityId, eventSourceId, payload } = event;
    const challengeId = eventSourceId;
    
    try {
      // 1. Award bonus points for fast completion
      if (payload.timeToComplete < 3600) { // Less than 1 hour
        await awardBonusPoints(userId, 50, 'Fast challenge completion');
      }
      
      // 2. Update user statistics
      await updateUserStats(userId, {
        challengesCompleted: 1,
        totalPointsEarned: payload.pointsEarned,
        totalXpEarned: payload.xpEarned
      });
      
      // 3. Check for achievement eligibility
      const challengeCount = await getUserChallengeCount(userId);
      if (challengeCount === 10) {
        await triggerAchievement(userId, 'challenge-master');
      }
      
      // 4. Send personalized notification
      await sendNotification(userId, {
        type: 'challenge_completed',
        title: 'Challenge Complete!',
        message: `Great job completing "${payload.challengeName}"!`,
        data: {
          pointsEarned: payload.pointsEarned,
          xpEarned: payload.xpEarned,
          completionTime: formatDuration(payload.timeToComplete)
        }
      });
      
      // 5. Update leaderboards
      await updateLeaderboard(communityId, userId, {
        challengesCompleted: 1,
        pointsEarned: payload.pointsEarned
      });
      
    } catch (error) {
      console.error(`Error handling challenge completion for user ${userId}:`, error);
      throw error;
    }
  }
  ```

  ```javascript Reward Claim Handler theme={null}
  async function handleRewardClaim(event) {
    const { userId, eventSourceId, payload } = event;
    const rewardId = eventSourceId;
    
    try {
      // 1. Log the reward claim for analytics
      await logEvent('reward_claimed', {
        userId,
        rewardId,
        rewardName: payload.rewardName,
        rewardType: payload.rewardType,
        timestamp: event.createdAt
      });
      
      // 2. Handle different reward types
      switch (payload.rewardType) {
        case 'asset':
          await handleAssetReward(userId, rewardId, payload);
          break;
        case 'entry':
          await handleEntryReward(userId, rewardId, payload);
          break;
        default:
          console.warn('Unknown reward type:', payload.rewardType);
      }
      
      // 3. Send confirmation notification
      await sendNotification(userId, {
        type: 'reward_claimed',
        title: 'Reward Claimed!',
        message: `You've successfully claimed: ${payload.rewardName}`,
        data: payload
      });
      
      // 4. Update user profile with reward
      await updateUserProfile(userId, {
        rewardsClaimed: 1,
        lastRewardClaimed: {
          id: rewardId,
          name: payload.rewardName,
          claimedAt: event.createdAt
        }
      });
      
    } catch (error) {
      console.error(`Error handling reward claim for user ${userId}:`, error);
      throw error;
    }
  }

  async function handleAssetReward(userId, rewardId, payload) {
    // Asset rewards are permanent items (badges, titles, etc.)
    await addUserAsset(userId, {
      rewardId,
      name: payload.rewardName,
      type: 'reward_asset',
      acquiredAt: new Date().toISOString()
    });
  }

  async function handleEntryReward(userId, rewardId, payload) {
    // Entry rewards are chances to win (lottery entries, etc.)
    await addUserEntry(userId, {
      rewardId,
      name: payload.rewardName,
      type: 'reward_entry',
      enteredAt: new Date().toISOString()
    });
  }
  ```

  ```javascript Variable Captured Handler theme={null}
  async function handleVariableCaptured(event) {
    const { userId, payload } = event;
    
    try {
      // 1. Store the captured variable
      await storeUserVariable(userId, {
        variableId: payload.variableId,
        variableName: payload.variableName,
        value: payload.value,
        capturedAt: payload.capturedAt
      });
      
      // 2. Trigger personalization logic
      await updateUserPersonalization(userId, {
        [payload.variableName]: payload.value
      });
      
      // 3. Check for completion of user profile
      const profileCompletion = await calculateProfileCompletion(userId);
      if (profileCompletion === 100) {
        await triggerAchievement(userId, 'profile-complete');
      }
      
      // 4. Update segmentation
      await updateUserSegmentation(userId, {
        variableName: payload.variableName,
        value: payload.value
      });
      
    } catch (error) {
      console.error(`Error handling variable capture for user ${userId}:`, error);
      throw error;
    }
  }
  ```
</CodeGroup>

## Step 4: Error Handling and Retry Logic

Implement robust error handling to ensure reliable webhook processing:

<CodeGroup>
  ```javascript Error Handling theme={null}
  const MAX_RETRIES = 3;
  const RETRY_DELAY = 1000; // 1 second

  async function processWebhookEvent(event) {
    let attempt = 1;
    
    while (attempt <= MAX_RETRIES) {
      try {
        await processEvent(event);
        return; // Success, exit retry loop
      } catch (error) {
        console.error(`Attempt ${attempt} failed:`, error);
        
        if (attempt === MAX_RETRIES) {
          // Final attempt failed, handle accordingly
          await handleFinalFailure(event, error);
          throw error;
        }
        
        // Wait before retrying
        await sleep(RETRY_DELAY * attempt);
        attempt++;
      }
    }
  }

  async function handleFinalFailure(event, error) {
    // Log to error monitoring service
    console.error('Webhook processing failed after all retries:', {
      eventId: event.id,
      eventType: event.eventSubCategory,
      error: error.message,
      stack: error.stack
    });
    
    // Store in dead letter queue for manual review
    await storeInDeadLetterQueue(event, error);
    
    // Alert operations team
    await sendAlert('webhook-processing-failed', {
      eventId: event.id,
      eventType: event.eventSubCategory,
      error: error.message
    });
  }

  function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
  ```

  ```javascript Idempotency theme={null}
  // Store processed webhook IDs to prevent duplicate processing
  const processedWebhooks = new Set();

  app.post('/webhooks/nudj', async (req, res) => {
    try {
      const event = req.body;
      const webhookId = event.id;
      
      // Check if we've already processed this webhook
      if (processedWebhooks.has(webhookId)) {
        console.log(`Webhook ${webhookId} already processed, ignoring`);
        return res.status(200).send('OK');
      }
      
      // Verify the webhook
      if (!verifyWebhookSignature(req)) {
        return res.status(401).send('Unauthorized');
      }
      
      // Process the event
      await processWebhookEvent(event);
      
      // Mark as processed
      processedWebhooks.add(webhookId);
      
      res.status(200).send('OK');
    } catch (error) {
      console.error('Webhook processing error:', error);
      res.status(500).send('Internal Server Error');
    }
  });
  ```
</CodeGroup>

## Step 5: Testing Your Implementation

Test your webhook implementation thoroughly:

<CodeGroup>
  ```javascript Testing Script theme={null}
  const axios = require('axios');

  // Test webhook endpoint locally
  async function testWebhook() {
    const testPayload = {
      id: 'test-webhook-' + Date.now(),
      eventCategory: 'challenge',
      eventSubCategory: 'challenge-completion',
      organisationId: '60f7b8c8e7d4a2b1c9e3f4a1',
      communityId: '60f7b8c8e7d4a2b1c9e3f4a2',
      userId: '60f7b8c8e7d4a2b1c9e3f4a3',
      eventSourceId: '60f7b8c8e7d4a2b1c9e3f4a4',
      payload: {
        challengeId: '60f7b8c8e7d4a2b1c9e3f4a4',
        challengeName: 'Test Challenge',
        completedAt: new Date().toISOString(),
        timeToComplete: 1800,
        pointsEarned: 100,
        xpEarned: 50
      },
      createdAt: new Date().toISOString()
    };

    try {
      const response = await axios.post('http://localhost:3000/webhooks/nudj', testPayload, {
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${process.env.WEBHOOK_SECRET}`,
          'X-Webhook-Source': 'nudj-platform'
        }
      });
      
      console.log('Test webhook successful:', response.status);
    } catch (error) {
      console.error('Test webhook failed:', error.message);
    }
  }

  testWebhook();
  ```

  ```bash Testing with ngrok theme={null}
  # Install ngrok for local testing
  npm install -g ngrok

  # Start your local webhook server
  node webhook-server.js &

  # Expose local server via ngrok
  ngrok http 3000

  # Use the ngrok URL in your webhook configuration
  # Example: https://abc123.ngrok.io/webhooks/nudj
  ```
</CodeGroup>

## Step 6: Production Deployment

### Security Checklist

<AccordionGroup>
  <Accordion title="HTTPS Configuration">
    * Use valid SSL certificates
    * Enable HSTS headers
    * Disable HTTP fallback
    * Use strong cipher suites
  </Accordion>

  <Accordion title="Authentication & Authorization">
    * Verify webhook signatures
    * Use environment variables for secrets
    * Implement rate limiting
    * Add IP allowlisting if needed
  </Accordion>

  <Accordion title="Error Handling">
    * Implement retry logic
    * Use dead letter queues
    * Add comprehensive logging
    * Set up monitoring and alerts
  </Accordion>

  <Accordion title="Performance">
    * Process webhooks asynchronously
    * Implement connection pooling
    * Add caching where appropriate
    * Monitor response times
  </Accordion>
</AccordionGroup>

### Monitoring and Logging

<CodeGroup>
  ```javascript Structured Logging theme={null}
  const winston = require('winston');

  const logger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(
      winston.format.timestamp(),
      winston.format.errors({ stack: true }),
      winston.format.json()
    ),
    defaultMeta: { service: 'webhook-handler' },
    transports: [
      new winston.transports.File({ filename: 'error.log', level: 'error' }),
      new winston.transports.File({ filename: 'combined.log' }),
      new winston.transports.Console({
        format: winston.format.simple()
      })
    ]
  });

  app.post('/webhooks/nudj', async (req, res) => {
    const startTime = Date.now();
    const event = req.body;
    
    logger.info('Webhook received', {
      webhookId: event.id,
      eventType: event.eventSubCategory,
      userId: event.userId,
      timestamp: event.createdAt
    });
    
    try {
      await processWebhookEvent(event);
      
      logger.info('Webhook processed successfully', {
        webhookId: event.id,
        processingTime: Date.now() - startTime
      });
      
      res.status(200).send('OK');
    } catch (error) {
      logger.error('Webhook processing failed', {
        webhookId: event.id,
        error: error.message,
        stack: error.stack,
        processingTime: Date.now() - startTime
      });
      
      res.status(500).send('Internal Server Error');
    }
  });
  ```

  ```javascript Health Checks theme={null}
  app.get('/health', (req, res) => {
    res.status(200).json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      version: process.env.APP_VERSION || '1.0.0'
    });
  });

  app.get('/webhooks/health', (req, res) => {
    // Check if webhook processing is healthy
    const isHealthy = checkWebhookHealth();
    
    res.status(isHealthy ? 200 : 503).json({
      status: isHealthy ? 'healthy' : 'unhealthy',
      webhookProcessor: isHealthy,
      lastProcessedWebhook: getLastProcessedWebhookTime(),
      timestamp: new Date().toISOString()
    });
  });
  ```
</CodeGroup>

## Common Integration Patterns

### Real-time Notifications

<CodeGroup>
  ```javascript Push Notifications theme={null}
  async function sendPushNotification(userId, event) {
    const userDevices = await getUserDevices(userId);
    
    const notification = {
      title: getNotificationTitle(event),
      body: getNotificationMessage(event),
      data: {
        eventType: event.eventSubCategory,
        eventId: event.id,
        deepLink: generateDeepLink(event)
      }
    };
    
    for (const device of userDevices) {
      await pushService.send(device.token, notification);
    }
  }

  function getNotificationTitle(event) {
    const titles = {
      'challenge-completion': 'Challenge Complete! 🏆',
      'achievement-completion': 'Achievement Unlocked! 🎉',
      'reward-claim': 'Reward Claimed! 🎁',
      'streak-extended': 'Streak Extended! 🔥'
    };
    
    return titles[event.eventSubCategory] || 'Nudj Notification';
  }
  ```
</CodeGroup>

### Email Marketing Integration

<CodeGroup>
  ```javascript Email Campaigns theme={null}
  async function triggerEmailCampaign(event) {
    const user = await getUser(event.userId);
    
    const campaignData = {
      email: user.email,
      templateId: getEmailTemplate(event.eventSubCategory),
      personalizations: [{
        email: user.email,
        dynamic_template_data: {
          firstName: user.firstName,
          eventData: event.payload,
          communityName: await getCommunityName(event.communityId)
        }
      }]
    };
    
    await emailService.send(campaignData);
  }

  function getEmailTemplate(eventType) {
    const templates = {
      'challenge-completion': 'challenge_completed_v2',
      'achievement-completion': 'achievement_unlocked_v2',
      'reward-claim': 'reward_claimed_v1'
    };
    
    return templates[eventType] || 'generic_notification_v1';
  }
  ```
</CodeGroup>

### Analytics Integration

<CodeGroup>
  ```javascript Analytics Tracking theme={null}
  async function trackAnalyticsEvent(event) {
    const analyticsEvent = {
      userId: event.userId,
      eventName: `nudj_${event.eventSubCategory}`,
      properties: {
        organisationId: event.organisationId,
        communityId: event.communityId,
        eventSourceId: event.eventSourceId,
        timestamp: event.createdAt,
        ...event.payload
      }
    };
    
    // Send to multiple analytics platforms
    await Promise.all([
      analytics.track(analyticsEvent),
      mixpanel.track(analyticsEvent.userId, analyticsEvent.eventName, analyticsEvent.properties),
      amplitude.logEvent(analyticsEvent)
    ]);
  }
  ```
</CodeGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Response Quickly" icon="clock">
    Return HTTP 200 within 10 seconds. Process heavy workloads asynchronously.
  </Card>

  <Card title="Handle Duplicates" icon="copy">
    Use webhook IDs to implement idempotent processing and prevent duplicate handling.
  </Card>

  <Card title="Validate Payloads" icon="check">
    Always verify webhook authenticity and validate payload structure before processing.
  </Card>

  <Card title="Monitor Performance" icon="chart-line">
    Track processing times, error rates, and webhook delivery success rates.
  </Card>

  <Card title="Implement Retries" icon="refresh">
    Handle transient failures gracefully with exponential backoff retry logic.
  </Card>

  <Card title="Log Everything" icon="file-text">
    Maintain detailed logs for debugging and monitoring webhook processing.
  </Card>
</CardGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Event Catalog" icon="list" href="/developer/webhooks/event-catalog">
    See every available webhook event and its specific payload.
  </Card>

  <Card title="Testing Guide" icon="vial" href="/developer/webhooks/testing">
    Learn how to trigger test events to verify your endpoint.
  </Card>
</CardGroup>
