Getting started guide for the sesh REST API and webhooks.
The sesh API enables you to programmatically access your Discord server's events, polls, and time finders, and integrate with external systems through webhooks. You can retrieve data, manage webhook subscriptions, and receive real-time notifications when events occur in your server.
Getting Started
- Ensure your server has sesh Pro enabled
- Go to the sesh Dashboard
- Navigate to your server's settings
- Generate an API token in the API section
- Store your token securely - it will only be shown once
Base URL: All
API requests should be made to
https://sesh.fyi/api/v1/
All API requests must include your
API token in the
Authorization header
using the Bearer scheme.
Token Format
API tokens follow this format:
sesh_g{guild_id}_{random_string}
For example:
sesh_g123456789012345678_abc123def456...
Example Request
curl -H "Authorization: Bearer sesh_g123456789_abc123..." \
https://sesh.fyi/api/v1/events
Security: Keep your API token secret. Do not expose it in client-side code, public repositories, or share it with others. If your token is compromised, regenerate it immediately from the dashboard.
For a complete list of endpoints, request parameters, and response schemas, see the full API reference.
The examples below provide a condensed starter guide to help you get up and running quickly.
Fetching Events with curl
# List upcoming events
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/events?start_after=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
# Get a specific event
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/events/1234567890123456789"
# Get RSVPs for an event (paginated)
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/events/1234567890123456789/rsvps?limit=50&offset=0"
# Filter RSVPs by option emoji
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/events/1234567890123456789/rsvps?option=✅"
Fetching Polls with curl
# List all polls
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/polls"
# Get a specific poll
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/polls/1234567890123456789"
# Get votes for a poll (paginated)
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/polls/1234567890123456789/votes?limit=50&offset=0"
# Filter votes by option index
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/polls/1234567890123456789/votes?option=0"
Creating Polls with curl
# Create a basic poll
curl -X POST https://sesh.fyi/api/v1/polls \
-H "Authorization: Bearer $SESH_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "What game should we play?",
"options": ["Minecraft", "Valorant", "Among Us"],
"channel_id": "123456789012345678"
}'
# Create a Time poll (options are ISO 8601 timestamps)
curl -X POST https://sesh.fyi/api/v1/polls \
-H "Authorization: Bearer $SESH_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "When should we meet?",
"options": ["2024-01-20T15:00:00.000Z", "2024-01-21T18:00:00.000Z"],
"channel_id": "123456789012345678",
"poll_type": "Time"
}'
# Create an anonymous poll (hides voter names)
curl -X POST https://sesh.fyi/api/v1/polls \
-H "Authorization: Bearer $SESH_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Anonymous feedback poll",
"options": ["Great", "Good", "Needs improvement"],
"channel_id": "123456789012345678",
"is_anonymous": true
}'
# Create a poll with role restrictions (Premium)
curl -X POST https://sesh.fyi/api/v1/polls \
-H "Authorization: Bearer $SESH_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Members-only vote",
"options": ["Option A", "Option B"],
"channel_id": "123456789012345678",
"eligible_role_ids": ["111111111111111111", "222222222222222222"]
}'
# Create a poll with mentions
curl -X POST https://sesh.fyi/api/v1/polls \
-H "Authorization: Bearer $SESH_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Team vote",
"options": ["Yes", "No"],
"channel_id": "123456789012345678",
"role_mention_ids": ["333333333333333333"],
"user_mention_ids": ["444444444444444444"]
}'
Fetching Time Finders with curl
# List all time finders
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/timefinders"
# Get a specific time finder
curl -H "Authorization: Bearer $SESH_API_TOKEN" \
"https://sesh.fyi/api/v1/timefinders/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Creating a Webhook with curl
curl -X POST https://sesh.fyi/api/v1/webhooks \
-H "Authorization: Bearer $SESH_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/sesh",
"event_types": ["event.created", "event.updated", "event.rsvp.added"],
"description": "Main webhook"
}'
Node.js: Verifying Webhook Signatures
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
// Parse the signature header (format: sha256=...)
if (!signature.startsWith('sha256=')) {
return false;
}
const providedSig = signature.slice(7); // Remove 'sha256=' prefix
// Compute expected signature
const expectedSig = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
// Constant-time comparison
return crypto.timingSafeEqual(
Buffer.from(providedSig),
Buffer.from(expectedSig)
);
}
// Express.js example
app.post('/webhooks/sesh', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-sesh-signature'];
const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
console.log('Received webhook:', event.type);
// Process the webhook asynchronously
processWebhook(event).catch(console.error);
// Return 200 immediately
res.status(200).send('OK');
});
Webhooks allow you to receive real-time HTTP notifications when events occur in your Discord server. Instead of polling the API, your server receives a POST request whenever something happens.
HTTPS Required: Webhook URLs must use HTTPS for security.
Event Types
Subscribe to any combination of these 19 event types:
Event EventsFor webhook management endpoints (create, update, delete, view deliveries), see the Webhooks API Reference.
Payload Format
All webhook payloads follow this structure:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "event.created",
"timestamp": "2024-01-15T19:00:00.000Z",
"guild_id": "791937460056752128",
"data": {
"id": "1234567890123456789",
"name": "Weekly Game Night",
"description": "Join us for games!",
"start_time": "2024-01-20T19:00:00.000Z",
"end_time": "2024-01-20T22:00:00.000Z",
"timezone": "America/New_York",
"channel_id": "123456789012345678",
"author_id": "987654321098765432",
"is_recurring": false,
"recurring_parent_id": null,
"rsvp_options": [
{ "emoji": "\u2705", "name": "Going", "count": 0 },
{ "emoji": "\u274C", "name": "Not Going", "count": 0 },
{ "emoji": "\u2753", "name": "Maybe", "count": 0 }
]
}
}
| Field | Description |
|---|---|
id |
Unique identifier for this delivery (useful for deduplication) |
type |
The event type that triggered this webhook |
timestamp
|
When the event occurred (ISO 8601 format) |
guild_id
|
The Discord guild (server) ID where the event occurred |
data |
The full object related to the event |
Signature Verification
Every webhook request includes an
X-Sesh-Signature header
containing an HMAC-SHA256 signature.
You should verify this signature to
ensure the request came from
sesh.
The signature is computed as:
HMAC-SHA256(webhook_secret, request_body)
The header format is:
X-Sesh-Signature: sha256=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8f9
To verify:
-
Extract the hex signature after
sha256=from the header - Compute the HMAC-SHA256 of the raw request body using your webhook secret
- Compare your computed signature (as hex) with the header value
- Use constant-time comparison to prevent timing attacks
Retry Schedule
If your endpoint returns a non-2xx status code or times out, sesh will retry the delivery with exponential backoff:
| Attempt | Delay After Failure |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 12 hours |
After 5 failed retries, the delivery
is marked as failed. You can view
delivery history via the
/webhooks/:id/deliveries
endpoint.
Tip: Return a 2xx response as quickly as possible. Process webhook data asynchronously to avoid timeouts.
To ensure fair usage and protect the API from abuse, rate limits are enforced on all endpoints.
| Operation Type | Sustained Rate | Burst Rate |
|---|---|---|
| Read operations (GET) | 300 requests/minute | 30 requests/second |
| Write operations (POST, PATCH, DELETE) | 60 requests/minute | 10 requests/second |
Rate Limit Headers
Each response includes headers to help you track your rate limit status:
| Header | Description |
|---|---|
X-RateLimit-Limit
|
Maximum requests allowed in the current window |
X-RateLimit-Remaining
|
Requests remaining in the current window |
X-RateLimit-Reset
|
Seconds until the rate limit resets |
When you exceed the rate limit, the
API returns a
429 Too Many Requests
response. Wait until the reset time
before making additional requests.