Back to SDK Docs

Webhooks

Real-time event notifications for your backend

HTTPS OnlyHMAC-SHA256 SignaturesAutomatic Retries

Overview

Webhooks allow your server to receive real-time notifications when events occur in Funstack. Configure webhook endpoints in your Creator Dashboard to start receiving events.

Available Events

Subscribe to specific events or use * to receive all events.

player.created New player registered
player.login Player logged in
xp.earned Player earned XP
xp.spent Player spent XP
achievement.unlocked Achievement unlocked
item.purchased Item purchased from store
item.transferred Item transferred between players
ad.completed Rewarded ad completed
ad.failed Rewarded ad failed
wallet.connected Wallet connected to account
level.up Player leveled up

Payload Format

All webhook payloads follow a consistent JSON structure with event type, timestamp, data, and signature.

Example Payload (xp.earned)
{
  "id": "evt_1234567890",
  "type": "xp.earned",
  "created": 1704672000,
  "data": {
    "playerId": "player_abc123",
    "amount": 100,
    "source": "ad_reward",
    "newBalance": 1500,
    "metadata": {
      "adPlacement": "level_complete",
      "gameSession": "session_xyz"
    }
  },
  "signature": "sha256=abc123..."
}

Verifying Signatures

Always verify webhook signatures to ensure requests are from Funstack. The signature is included in the X-XP-Signature header.

Signature Verification (Node.js)
import crypto from 'crypto';

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expectedSignature}`)
  );
}

// Express.js example
app.post('/webhooks/xp-platform', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-xp-signature'] as string;
  const payload = req.body.toString();
  
  if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET!)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const event = JSON.parse(payload);
  
  switch (event.type) {
    case 'xp.earned':
      handleXPEarned(event.data);
      break;
    case 'achievement.unlocked':
      handleAchievement(event.data);
      break;
    // ... handle other events
  }
  
  res.status(200).json({ received: true });
});

Security Best Practices

  • • Always verify signatures before processing events
  • • Use HTTPS endpoints only
  • • Respond quickly (within 5 seconds) to avoid timeouts
  • • Process events asynchronously if they require heavy computation

Retry Policy

Failed webhook deliveries are automatically retried with exponential backoff.

Retry Schedule
// Webhook retry schedule:
// - Attempt 1: Immediate
// - Attempt 2: 5 minutes
// - Attempt 3: 30 minutes
// - Attempt 4: 2 hours
// - Attempt 5: 24 hours

// Response codes:
// - 2xx: Success, no retry
// - 4xx: Client error, no retry (except 429)
// - 429: Rate limited, retry with backoff
// - 5xx: Server error, retry