Developers
Read your events and guest lists from your own tools, and get a webhook the moment guests register, cancel or check in.
Getting started
API keys and webhooks are available on accounts with developer access. Once it's on, create a key or a webhook in Settings → Developers. Keys and signing secrets are shown once, when you create them: copy them somewhere safe. Each account can have up to 5 keys and 3 webhook endpoints.
Keys give read access to the events you host or co-host and to their guests' names and emails. Use that information only to run your events, and revoke a key as soon as you stop using it.
Authentication
Send your key in the Authorization header on every request:
curl https://eventx.ca/api/v1/events \ -H "Authorization: Bearer evx_your_key"
Each key can make 120 requests per minute. Past that, you get 429 with a Retry-After header. An invalid or revoked key gets 401, and a key whose account no longer has developer access gets 403.
Endpoints
GET /api/v1/events lists the events you host or co-host, newest first (up to 500), with dates, time zone, status, location mode (in_person, online or hybrid), capacity, seats_taken (guests plus their plus-ones), price in cents and tax preset.
GET /api/v1/events/:id/guests lists one event's guests: name, email, status (going, pending, waitlist or declined), plus_ones, checked_in, checked_in_at and registered_at. An event that isn't yours gets 404.
Responses are JSON: { "data": [...] } on success, { "error": { "code": "...", "message": "..." } } otherwise. The API is read-only.
Webhooks
Add an https endpoint and we'll POST a JSON event to it for the events you host or co-host:
- guest.registered: someone registers (any status), or a pending or waitlisted guest gets a confirmed spot (
statusbecomesgoing). - guest.cancelled: a guest cancels, is removed, or is declined by a host.
- guest.checked_in: a guest is checked in at the door.
{
"id": "6f1c2a4e-…", // delivery id: use it to ignore repeats
"type": "guest.registered",
"created_at": "2026-10-20T15:04:05Z",
"data": {
"event": { "id": "…", "slug": "…", "title": "…", "starts_at": "…" },
"guest": {
"user_id": "…", "name": "Alex Tremblay", "email": "alex@example.com",
"status": "going", "plus_ones": 1,
"checked_in": false, "checked_in_at": null, "registered_at": "…"
}
}
}Every request carries EventX-Event (the type), EventX-Delivery (the delivery id) and EventX-Signature: t=<unix time>,v1=<signature>, where the signature is the hex HMAC-SHA256 of <t>.<raw body> with your endpoint's signing secret. Check it before trusting the request:
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body exactly as received (before JSON.parse).
export function verify(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // 5-minute window
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(String(parts.v1 ?? ""));
return a.length === b.length && timingSafeEqual(a, b);
}Delivery and retries
- Answer with any 2xx status within 5 seconds. Do slow work after responding.
- Redirects aren't followed, and endpoints must be public https addresses on the standard port.
- Failed deliveries are retried with growing delays (1, 2, 4… minutes) up to 8 attempts. The same event can arrive more than once and out of order: use the delivery id and timestamps.
- After 15 failures in a row, or a
410 Goneanswer, the endpoint is turned off. Turn it back on in Settings once it's fixed.
Questions
Write to hello@eventx.ca.