Webhooks

Receive real-time notifications about events in your Caring CourseForge account

docsapi

Webhooks allow you to receive real-time HTTP notifications when events occur in your account, eliminating the need for polling.

Available Events

Course Events

  • course.created - New course created
  • course.updated - Course details modified
  • course.published - Course published/unpublished
  • course.deleted - Course deleted

Student Events

  • student.enrolled - Student enrolled in course
  • student.completed_lesson - Student completed a lesson
  • student.completed_course - Student completed entire course
  • student.unenrolled - Student unenrolled from course

Module Events

  • module.created - New module added
  • module.updated - Module modified
  • module.deleted - Module removed

Lesson Events

  • lesson.created - New lesson added
  • lesson.updated - Lesson modified
  • lesson.deleted - Lesson removed

Assessment Events

  • quiz.submitted - Student submitted quiz
  • quiz.graded - Quiz graded (auto or manual)

Setting Up Webhooks

1. Create a Webhook Endpoint

Your endpoint must:

  • Accept POST requests
  • Respond with 200 OK within 5 seconds
  • Handle duplicate events (idempotent)

Example endpoint (Node.js/Express):

app.post('/webhooks/courseforge', (req, res) => {
  const event = req.body

  // Verify signature (recommended)
  if (!verifySignature(req)) {
    return res.status(401).send('Invalid signature')
  }

  // Process event
  console.log('Received event:', event.type)

  // Respond quickly
  res.status(200).json({ received: true })

  // Process async
  processEvent(event).catch(console.error)
})

2. Register Webhook

Register your webhook URL in the CourseForge dashboard:

  1. Go to SettingsWebhooks
  2. Click Add Webhook
  3. Enter your endpoint URL
  4. Select events to subscribe to
  5. Click Create

You'll receive a webhook secret - save this securely.

Webhook Payload

All webhook requests include:

{
  "id": "evt_abc123",
  "type": "course.created",
  "created": "2025-01-15T10:30:00Z",
  "data": {
    "course": {
      "id": "course_123",
      "name": "Introduction to Python",
      "authorId": "user_456"
    }
  },
  "account": {
    "id": "user_456",
    "email": "user@example.com"
  }
}

Verifying Signatures

Verify webhook authenticity using the signature header:

const crypto = require('crypto')

function verifySignature(req) {
  const signature = req.headers['x-courseforge-signature']
  const payload = JSON.stringify(req.body)
  const secret = process.env.WEBHOOK_SECRET

  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  )
}

Retry Logic

If your endpoint fails (non-200 response), CourseForge will retry:

  • 1st retry: After 1 minute
  • 2nd retry: After 5 minutes
  • 3rd retry: After 30 minutes
  • 4th retry: After 2 hours
  • 5th retry: After 6 hours

After 5 failures, the webhook is automatically disabled.

Best Practices

Respond Quickly

  • Return 200 OK immediately
  • Process events asynchronously
  • Use a message queue for complex processing

Handle Duplicates

  • Store processed event IDs
  • Check before processing
  • Make operations idempotent

Monitor Webhooks

  • Log all received events
  • Set up error alerts
  • Track processing times

Security

  • Always verify signatures
  • Use HTTPS endpoints only
  • Validate event data
  • Rate limit your endpoint

Testing Webhooks

Local Testing with ngrok

# Install ngrok
npm install -g ngrok

# Start your local server
node server.js

# Create tunnel
ngrok http 3000

# Use the ngrok URL in webhook settings
https://abc123.ngrok.io/webhooks/courseforge

Manual Testing

Send test events from the dashboard:

  1. Go to SettingsWebhooks
  2. Click on your webhook
  3. Click Send Test Event
  4. Select event type
  5. View delivery logs

Troubleshooting

Webhook Not Receiving Events

  • Check your endpoint is publicly accessible
  • Verify the URL is correct (including https://)
  • Check firewall/security rules
  • View webhook logs in dashboard

Events Timing Out

  • Respond within 5 seconds
  • Move slow processing to background jobs
  • Use a message queue

Duplicate Events

  • This is normal - design for idempotency
  • Track processed event IDs
  • Use database constraints

Rate Limits

Webhooks are not subject to API rate limits, but your endpoint should handle:

  • Burst traffic (many events at once)
  • Retry attempts
  • Reasonable response times

Example: Process Course Created

async function processEvent(event) {
  if (event.type === 'course.created') {
    const course = event.data.course

    // Send welcome email
    await sendEmail({
      to: event.account.email,
      subject: `Course "${course.name}" Created`,
      body: 'Your course is ready!'
    })

    // Log to analytics
    await analytics.track('course_created', {
      courseId: course.id,
      userId: event.account.id
    })

    // Trigger automation
    await automation.run('new-course', course)
  }
}

Topics

available eventscourse eventsstudent eventsassessment eventssystem eventscreating a webhooksetup stepswebhook payloadstandard payload structureverifying webhook signatures