Key Information/WebhooksNew

Webhooks

Subscribe to real-time events instead of polling. Get instant notifications when matches start, end, or when specific events occur.

Instant Updates

Get notified within milliseconds of events occurring

Reduce API Calls

No more polling - save your rate limit for other requests

Secure

HMAC signatures verify webhook authenticity

Registering a Webhook

Register a webhook endpoint to receive events:

curl -X POST "https://api.citoapi.com/v1/webhooks" \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhook",
    "events": ["match.started", "match.ended", "player.elimination"],
    "description": "Match notifications for Discord bot"
  }'
{
  "id": "wh_abc123",
  "url": "https://yourapp.com/webhook",
  "events": ["match.started", "match.ended", "player.elimination"],
  "secret": "whsec_xyz789...",
  "status": "active",
  "created_at": "2026-01-15T10:00:00Z"
}

Important: Save the secret value. You'll need it to verify webhook signatures.

Available Events

EventDescription
match.startedFired when a competitive match begins
match.endedFired when a match concludes with final scores
match.updatedFired on significant score changes during live matches
player.eliminationFired when a player is eliminated (Fortnite)
player.killFired on player kills with attacker/victim info
tournament.startedFired when a tournament begins
tournament.endedFired when a tournament concludes
round.endedFired at the end of each round (Valorant, CS)

Handling Webhooks

Create an endpoint to receive webhook events:

// Express.js example
const crypto = require('crypto');

app.post('/webhook', (req, res) => {
  // Verify signature
  const signature = req.headers['x-cito-signature'];
  const expectedSig = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (signature !== expectedSig) {
    return res.status(401).send('Invalid signature');
  }

  // Handle the event
  const { event, data } = req.body;

  switch (event) {
    case 'match.started':
      console.log(`Match started: ${data.tournament}`);
      // Notify Discord, update database, etc.
      break;

    case 'match.ended':
      console.log(`Match ended. Winner: ${data.winner}`);
      break;

    case 'player.elimination':
      console.log(`${data.eliminator} eliminated ${data.eliminated}`);
      break;
  }

  res.sendStatus(200);
});

Webhook Payload

All webhooks follow the same structure:

{
  "id": "evt_123abc",
  "event": "match.started",
  "created_at": "2026-01-15T18:00:00Z",
  "data": {
    "match_id": "match_12345",
    "game": "fortnite",
    "tournament": "FNCS Grand Finals",
    "region": "NA-EAST",
    "players_count": 100
  }
}

Retry Policy

If your endpoint returns a non-2xx status code, we'll retry with exponential backoff:

  • 1st retry: 1 minute
  • 2nd retry: 5 minutes
  • 3rd retry: 30 minutes
  • 4th retry: 2 hours
  • 5th retry: 24 hours (final attempt)

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