Event Stream
The live-event API layer.
The Event Stream pipes real-time event data — check-ins, drop claims, autograph requests, artist posts, venue triggers — into your stack. Build reactive experiences that fire the moment a fan walks through the door.
Q3 2026 beta — the Event Stream is in private beta. Join the waitlist via the developers portal. REST endpoints and webhook delivery are available now.
WebSocket Stream
Connect to the Event Stream to receive a real-time feed of all events for a venue or artist. Requires a Pro or Enterprise key.
javascript
// Browser / Node.js
const ws = new WebSocket(
'wss://signal.revolution.fan/v1/stream?apiKey=rev_live_xxxx'
);
ws.onopen = () => {
// Subscribe to a venue's event stream
ws.send(JSON.stringify({
action: 'subscribe',
channel: 'venue',
id: 'stubbs-austin',
}));
// Or subscribe to an artist
ws.send(JSON.stringify({
action: 'subscribe',
channel: 'artist',
id: 'khruangbin',
}));
};
ws.onmessage = (msg) => {
const event = JSON.parse(msg.data);
console.log(event.type); // 'fan_checkin'
console.log(event.payload); // { fan_id, event_id, gate, ts }
};SDK helper
typescript
// Using the SDK — auto-reconnects, typed events
const stream = rev.signal.connect({ venue: 'stubbs-austin' });
stream.on('fan_checkin', (e) => {
console.log(`Fan ${e.fanId} just walked in at gate ${e.gate}`);
});
stream.on('drop_published', (e) => {
console.log(`New drop: ${e.title} — $${e.priceUsd}`);
});
stream.on('attendance_milestone', (e) => {
console.log(`${e.count} fans in — venue is ${Math.round(e.count / e.capacity * 100)}% full`);
});
// Disconnect cleanly
stream.disconnect();Event Types
Every message on the stream has a type field and a typed payload.
TypeTriggerKey payload fields
fan_checkinFan scans QR at doorfan_id, event_id, gate, tsdrop_publishedArtist publishes a dropartist_id, drop_id, title, price_usd, quantitydrop_claimedFan claims a drop itemfan_id, drop_id, order_id, tsautograph_requestedFan requests autographfan_id, artist_id, order_id, deliveryshoutout_requestedFan requests shoutout videofan_id, artist_id, order_id, instructionssignal_postedArtist posts to Crew feedartist_id, signal_id, type, bodyvenue_openedVenue marks doors as openvenue_id, event_id, capacity, tsattendance_milestoneAttendance hits a thresholdevent_id, count, threshold, tsREST Polling (Available Now)
If WebSocket isn't suitable for your stack, poll the Event Stream REST endpoints. Available on all key tiers.
bash
# Recent check-ins for an event
GET /api/v1/signal/events/{event_id}/checkins?since=2026-05-14T21:00:00Z
# Active drops for an artist
GET /api/v1/signal/artists/{artist_id}/drops?status=active
# Venue live status
GET /api/v1/signal/venues/{venue_id}/livetypescript
// SDK equivalent
const checkins = await rev.signal.checkins({
eventId: 1042,
since: new Date('2026-05-14T21:00:00-05:00'),
});
const drops = await rev.signal.drops({ artistId: 'khruangbin', status: 'active' });
const live = await rev.signal.venueStatus('stubbs-austin');Webhooks
Register a HTTPS endpoint to receive Event Stream events as POST requests. Useful for server-side integrations, CRM sync, and Slack alerts.
typescript
// Register a webhook
const hook = await rev.developers.createWebhook({
url: 'https://yourapp.com/webhooks/signal',
events: ['fan_checkin', 'drop_claimed', 'autograph_requested'],
venueId: 'stubbs-austin', // scope to a venue, or omit for all
secret: 'whsec_xxxx', // used to verify HMAC signature
});Verifying webhook signatures
typescript
import crypto from 'crypto';
export function verifySignature(
payload: string,
signature: string,
secret: string,
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expected}`),
);
}Webhook payload shape
json
{
"id": "evt_01HX7ZQK4ABCDEFGH",
"type": "fan_checkin",
"created": 1745123456789,
"payload": {
"fan_id": "fan_0xc3f…",
"event_id": "evt_928xA",
"gate": "MAIN",
"ts": 1745123456789
}
}