Webhooks

Receive real-time notifications when events happen on the Velora platform.

Building a desktop app or stream tool?

The Events API provides real-time event streaming via WebSocket or SSE—no server required. Perfect for Streamer.bot, OBS plugins, and desktop applications.

Learn about the Events API →

Overview

Webhooks allow your application to receive real-time HTTP notifications when events occur. Instead of polling for changes, you can subscribe to specific events and we'll send them to your endpoint.

  • Real-time event delivery
  • Secure signature verification
  • Automatic retries on failure
  • Delivery history and debugging

Creating a Webhook

You can create webhooks in the Developer Dashboard or via the API:

Via Dashboard

  1. Go to your application in the Developer Dashboard
  2. Navigate to the "Webhooks" tab
  3. Click "Add Webhook"
  4. Enter your endpoint URL and select events
  5. Save and copy your webhook secret

Via API

curl -X POST https://api.velora.tv/api/developer/apps/{clientId}/webhooks \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/velora",
    "events": ["stream.online", "stream.offline", "channel.follow"]
  }'

Available Events

Stream Events

EventDescription
stream.onlineA stream goes live
stream.offlineA stream ends
stream.updateStream title or category changes

Channel Events

EventDescription
channel.followSomeone follows a channel
channel.subscribeNew or renewed subscription
channel.updateChannel information updated

User Events

EventDescription
user.authorization.grantUser authorizes your app
user.authorization.revokeUser revokes authorization

Webhook Payload

Each webhook delivery sends a POST request with a JSON payload:

{
  "id": "evt_abc123",
  "type": "stream.online",
  "timestamp": "2026-01-18T15:30:00Z",
  "data": {
    "streamId": "stream_xyz",
    "userId": "user_123",
    "username": "coolstreamer",
    "title": "Playing Velora Games!",
    "startedAt": "2026-01-18T15:30:00Z"
  }
}

Verifying Signatures

Every webhook request includes a signature header for verification. Always verify the signature to ensure the request came from Velora.

Security: Never process webhook payloads without verifying the signature first.

Headers

HeaderDescription
X-Velora-SignatureHMAC-SHA256 signature
X-Velora-TimestampUnix timestamp of the request
X-Velora-EventEvent type (e.g., stream.online)

Verification Example (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(payload, timestamp, signature, secret) {
  // The signature is prefixed with "sha256=" - strip it
  const sig = signature.replace('sha256=', '');

  // The signature is computed over: timestamp.payload
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${payload}`)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(sig),
    Buffer.from(expected)
  );
}

// Express middleware example
app.post('/webhooks/velora', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-velora-signature'];
  const timestamp = req.headers['x-velora-timestamp'];
  const payload = req.body.toString();

  // Verify the signature using timestamp + payload
  if (!verifyWebhookSignature(payload, timestamp, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Optional: Reject old timestamps to prevent replay attacks
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - parseInt(timestamp)) > 300) { // 5 minute tolerance
    return res.status(401).send('Timestamp too old');
  }

  // Process the webhook
  const event = JSON.parse(payload);
  console.log('Received event:', event.type);

  res.status(200).send('OK');
});

Retry Policy

If your endpoint doesn't respond with a 2xx status code within 10 seconds, we'll retry the delivery:

  • 1.Immediate retry after failure
  • 2.Retry after 1 minute
  • 3.Retry after 5 minutes
  • 4.Retry after 30 minutes
  • 5.Final retry after 2 hours

After 5 failed attempts, the webhook will be disabled automatically. You can re-enable it from the dashboard.

Best Practices

  • Respond quickly

    Return a 200 response immediately, then process asynchronously

  • Handle duplicates

    Use the event ID for idempotency - we may send the same event twice

  • Verify signatures

    Always verify the X-Velora-Signature header

  • Use HTTPS

    Webhook endpoints must use HTTPS

Next Steps