eventx✦

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 (status becomes going).
  • 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 Gone answer, the endpoint is turned off. Turn it back on in Settings once it's fixed.

Questions

Write to hello@eventx.ca.