Fan SDK
Drop in. Fan graph included.
The official TypeScript/JavaScript SDK for revolution.fan. Works in browser, SSR, React Native, and Node.js. One import gives you verified fan identity, $FAN balance, attendance history, and real-time event context.
Not yet published
The SDKs are not on npm or PyPI yet. The source is in the monorepo (packages/sdk, sdks/python) and you can build and link it locally, but a registry install will 404. The reference below describes the real, current method surface, no placeholder endpoints. Email sdk@revolution.fan if you want early access.
Installation
# Not published to npm yet, build from the monorepo:
git clone https://github.com/tokenevents/revolution-fan
cd revolution-fan/packages/sdk && npm install && npm run build
# When it ships, the package name will be:
# npm install @revolution-fan/sdkInitialisation
import { Revolution } from '@revolution-fan/sdk';
const rev = new Revolution({
apiKey: 'rev_live_xxxx', // required, get yours at revolution.fan/developers
baseUrl: 'https://api.revolution.fan/api/v1', // default shown
defaultRegion: 'atx', // optional, pre-fills region on all queries
timeout: 10_000, // optional, ms (default 10 000)
authScheme: 'bearer', // optional, see Auth docs
});Events
Discover, search, and retrieve live events. Available on all key tiers.
List events
const { items, total, hasMore } = await rev.events.list({
region: 'atx', // required, region slug
dateFrom: '2026-05-01', // ISO date
dateTo: '2026-05-31',
genre: 'hip-hop', // optional filter
featured: true, // only featured events
page: 1,
pageSize: 20,
});Get a single event
const event = await rev.events.get('khruangbin-stubbs-2026-05-14');
console.log(event.title); // "Khruangbin at Stubb's"
console.log(event.date); // "2026-05-14T21:00:00-05:00"
console.log(event.venue.name); // "Stubb's Outdoor Amphitheater"
console.log(event.ticketUrl); // "https://..."
console.log(event.imageUrl); // hero imageToday & tomorrow feed
const region = await rev.regions.nearest(lat, lng);
const { today, tomorrow } = await rev.events.todayTomorrow(region.slug);Create an open event
Any authenticated user can create a public event in seconds, no venue account required. Ideal for conference side events, community meetups, birthday parties, and anything in between. Every attendee who scans in still earns $FAN and gets a verified attendance record.
// POST /api/v1/events/quick, requires a valid user Bearer token
const { event } = await rev.events.create({
title: 'DeFi Happy Hour @ Consensus', // required
startTime: '2026-05-23T18:00:00-05:00', // required (ISO 8601)
endTime: '2026-05-23T21:00:00-05:00', // optional
locationText: 'The Rusty Nail, Austin TX', // free-text, or "Online"
description: 'Side event for Consensus attendees. Drinks on us.',
isFree: true, // default true
ticketPrice: undefined, // number (USD) when isFree=false
imageUrl: 'https://...', // optional hero image
});
console.log(event.slug); // auto-generated from title + date
console.log(event.eventType); // "open_event"
// redirect user to: /events/{event.slug}Venues & Artists
// Venue profile + upcoming shows
const venue = await rev.venues.get('stubbs-austin');
const shows = await rev.venues.events('stubbs-austin', 10);
// Artist profile + upcoming dates
const artist = await rev.artists.get('khruangbin');
const tour = await rev.artists.events('khruangbin', 20);Marketplace
Manage recurring data subscriptions. Requires a Marketplace key (mk_live_…) with authScheme: 'marketplace'. One-off queries are Python-only today, see the Python section below.
const rev = new Revolution({ apiKey: 'mk_live_xxxx', authScheme: 'marketplace' });
// What would a subscription cost?
const quote = await rev.marketplace.estimate({
dataProviderId: 'dp_123',
dataType: 'fan_demographics',
billingPeriod: 'monthly',
});
// Create it, then manage it
const sub = await rev.marketplace.create({
dataProviderId: 'dp_123',
dataType: 'fan_demographics',
billingPeriod: 'monthly',
});
const { items } = await rev.marketplace.list({ page: 1, pageSize: 20 });
await rev.marketplace.cancel(sub.id);Attendance
Venue check-in and attendance proofs. Requires a Scanner key.
const rev = new Revolution({ apiKey: 'scan_xxxx', authScheme: 'scanner' });
// Check a fan in
const result = await rev.attendance.checkin({
rfidTag: 'TAG_ABC123',
eventId: 1042,
venueName: "Stubb's Bar-B-Q",
checkInAt: new Date().toISOString(),
});
// Look up an existing proof
const proof = await rev.attendance.verify('proof_xyz789');Embed Widget
Drop a self-contained event listing into any HTML page, no framework required.
<!-- Add to any website -->
<div id="events"></div>
<script src="https://cdn.revolution.fan/sdk/embed.js"></script>
<script>
RevolutionEmbed.mount('#events', {
apiKey: 'rev_live_xxxx',
region: 'atx',
theme: 'dark',
maxEvents: 6,
onTicketClick: (event) => {
// Handle ticket purchase in your own UI
},
});
</script>Error Handling
import { RevolutionError } from '@revolution-fan/sdk';
try {
const event = await rev.events.get('non-existent-slug');
} catch (err) {
if (err instanceof RevolutionError) {
console.log(err.status); // 404
console.log(err.code); // 'EVENT_NOT_FOUND'
console.log(err.message); // human-readable
}
}Python SDK
The official Python client for revolution.fan. Designed for data science workflows, analytics pipelines, and backend services. Works with Pandas, Jupyter, and any Python 3.8+ environment.
Installation
# Not on PyPI yet, install from the monorepo:
git clone https://github.com/tokenevents/revolution-fan
pip install -e revolution-fan/sdks/pythonInitialisation
The Python client covers the Data Marketplace only, there is no events, venues, or artists namespace on it. Use the TypeScript SDK or the REST API for those.
from revolution_fan import MarketplaceClient
client = MarketplaceClient(
api_key="mk_live_xxxx", # or set REVOLUTION_FAN_API_KEY
base_url="https://api.revolution.fan/api/v1/marketplace",
timeout=30,
)Data Marketplace
# Browse what's licensable
catalog = client.get_catalog()
# Preview, free, returns the match count and the price
preview = client.preview_query(
filters=[
{"key": "top_genres", "operator": "contains", "value": "hip-hop"},
{"key": "concerts_attended_12m", "operator": "gte", "value": "3"},
{"key": "city", "operator": "eq", "value": "Los Angeles"},
],
attributes=["top_genres", "events_attended_rfan", "average_ticket_spend"],
query_type="aggregated",
)
print(preview.result_count) # fans matched
print(preview.price_usd) # what executing it will cost
# Execute, charges your account. query_id is an int.
result = client.execute_query(preview.query_id, delivery_format="json")
print(result.data)Sandbox Mode
# Synthetic data, no API key, nothing charged.
from revolution_fan import SandboxClient
client = SandboxClient()
preview = client.preview_query(
filters=[{"key": "top_genres", "operator": "contains", "value": "hip-hop"}],
attributes=["top_genres", "spend_band"],
query_type="aggregated",
)
# Safe to use in notebooks and CIJupyter Notebooks
Four sample notebooks are included in the repo under notebooks/ covering genre affinity segmentation, concert attendance lookalike modelling, cross-vertical fan profiles, and esports sponsor targeting.
# Clone and run locally
git clone https://github.com/tokenevents/revolution-fan
cd revolution-fan/notebooks
jupyter notebookError Handling (Python)
from revolution_fan import MarketplaceError, AuthError, RateLimitError
try:
result = client.execute_query(1234)
except AuthError:
print("Invalid or expired API key")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except MarketplaceError as e:
print(f"API error: {e}")