Side Events API
Retrieve side events for major web3 conferences. This read-only API provides event details including location, timing, organizers, and attendee information.
Quick Start
Get your API key
Contact platform@serotonin.co to request an API key scoped to your desired parent events.
Make your first request
curl https://api.se.ro/v1/events/ethcc/side-events?limit=10 \
-H "Authorization: Bearer YOUR_API_KEY"Parse the response
The API returns a JSON object with event data sorted by start date:
{
"success": true,
"data": {
"parentEventSlug": "ethcc",
"totalCount": 125,
"events": [...]
}
}Authentication
Include your API key in the Authorization header for all requests:
Authorization: Bearer YOUR_API_KEYAPI keys are scoped to specific parent events. A key for ETHDenver cannot access Consensus data. Contact platform@serotonin.co to request access to additional events.
Base URL
https://api.se.ro/v1All requests must use the api.se.ro subdomain. Requests to other subdomains will be rejected.
Retrieve Side Events
GET /events/{slug}/side-eventsFetch side events for a parent conference, sorted by start date.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Parent event identifier (e.g., ethcc, consensus-2025) |
limit | integer | No | Events to return. Default: 50. Max: 500. |
offset | integer | No | Events to skip for pagination. Default: 0. |
Example Request
cURL
curl https://api.se.ro/v1/events/ethcc/side-events?limit=10&offset=0 \
-H "Authorization: Bearer YOUR_API_KEY"Response
Returns a JSON object with an array of event objects sorted by start date:
{
"success": true,
"data": {
"parentEventSlug": "ethcc",
"totalCount": 125,
"limit": 10,
"offset": 0,
"events": [
{
"id": "cm4abc123xyz",
"name": "DeFi Builders Happy Hour",
"slug": "defi-builders-happy-hour",
"description": "Connect with fellow DeFi builders and discuss the latest innovations in decentralized finance.",
"url": "https://se.ro/events/defi-builders-happy-hour",
"startDate": "2025-07-08T18:00:00.000Z",
"endDate": "2025-07-08T21:00:00.000Z",
"timeZone": "Europe/Brussels",
"eventType": ["meetup", "networking"],
"topics": ["defi", "blockchain", "ethereum"],
"organizers": [
{
"type": "COMPANY",
"label": "Acme DeFi Protocol",
"isVisible": true
}
],
"venueName": null,
"location": {
"address": "123 Avenue Louise",
"city": "Brussels",
"state": null,
"country": "Belgium",
"latitude": 50.8371,
"longitude": 4.3676
},
"images": {
"avatar": "https://cdn.se.ro/events/avatar-abc123.jpg",
"banner": "https://cdn.se.ro/events/banner-abc123.jpg"
}
}
]
}
}Response Fields
Event Object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the event |
name | string | Event name |
slug | string | URL-friendly identifier |
description | string | null | Event description |
url | string | Full URL to event page on Sero |
startDate | string | ISO 8601 timestamp (UTC) |
endDate | string | ISO 8601 timestamp (UTC) |
timeZone | string | IANA timezone identifier |
eventType | string[] | Event categories (e.g., ["meetup", "networking"]) |
topics | string[] | Event topics/tags (e.g., ["web3", "blockchain"]) |
organizers | object[] | List of event organizers (see below) |
venueName | null | Reserved for future use |
location | object | Geographic details (see below) |
images | object | Event imagery (see below) |
Organizer Object
| Field | Type | Description |
|---|---|---|
type | string | Either USER or COMPANY |
label | string | Display name |
isVisible | boolean | Whether to display publicly |
Location Object
| Field | Type | Description |
|---|---|---|
address | string | null | Street address |
city | string | null | City name |
state | string | null | State or region |
country | string | null | Country name |
latitude | number | null | Geographic latitude |
longitude | number | null | Geographic longitude |
Images Object
| Field | Type | Description |
|---|---|---|
avatar | string | null | Event avatar/logo URL |
banner | string | null | Event banner URL |
Rate Limits
1000 requests per hour per API key. Exceeding this limit returns a 429 Too Many Requests response.
Check rate limit status in response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per hour (1000) |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when limit resets |
Pagination
For events with hundreds of side events, paginate through results using limit and offset:
# Fetch page 2 (events 51-100)
curl https://api.se.ro/v1/events/ethcc/side-events?limit=50&offset=50 \
-H "Authorization: Bearer YOUR_API_KEY"Calculate total pages using the totalCount field in the response:
const totalPages = Math.ceil(data.totalCount / limit);Error Handling
The API uses standard HTTP status codes:
| Code | Status | Description |
|---|---|---|
200 | OK | Request succeeded |
400 | Bad Request | Invalid parameters (e.g., invalid limit/offset) |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | API key lacks access to this event |
404 | Not Found | Parent event not found or has no side events |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server error (contact support if persistent) |
Error Response Format
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "API key does not have access to this parent event"
}
}Best Practices
Cache responses
Side event data changes infrequently. Cache responses for 5-10 minutes to reduce API calls and improve performance.
Handle rate limits
Implement retry logic with exponential backoff when you hit rate limits:
JavaScript
async function fetchWithRetry(slug, retries = 3) {
const response = await fetch(
`https://api.se.ro/v1/events/${slug}/side-events`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
if (response.status === 429 && retries > 0) {
const resetTime = response.headers.get('X-RateLimit-Reset');
const waitTime = (resetTime * 1000) - Date.now();
await new Promise(resolve => setTimeout(resolve, waitTime));
return fetchWithRetry(slug, retries - 1);
}
return response.json();
}Paginate large result sets
Request events in batches rather than fetching everything at once:
async function fetchAllEvents(slug) {
const allEvents = [];
let offset = 0;
const limit = 100;
while (true) {
const response = await fetch(
`https://api.se.ro/v1/events/${slug}/side-events?limit=${limit}&offset=${offset}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const data = await response.json();
allEvents.push(...data.data.events);
if (offset + limit >= data.data.totalCount) break;
offset += limit;
}
return allEvents;
}Additional Information
CORS Support
The API supports Cross-Origin Resource Sharing (CORS) for all origins, allowing safe browser-based requests.
Getting Help
- For all technical issues, access requests, and general questions: platform@serotonin.co
Return to the Developer Documentation for more APIs and resources.