Events API

Every public Hack Club event, as JSON, free to use. No key needed, and you can call it from a browser on any site.

Try it

Events

GET /api/v1/events

Upcoming events, soonest first, 50 at a time. Options, all optional:

  • when – upcoming (the default), past (newest first) or all
  • tags – only events with any of these tags, comma-separated, like ama,workshop
  • featured – true for the featured section of the home page, false for community events
  • ama – true for AMAs only
  • language – a language code, like en or es
  • from, to – only events starting in this range, like 2026-10-01
  • limit – how many per page, up to 200
  • page – which page, starting at 1
{
  "version": "v1",
  "page": 1,
  "pages": 3,
  "total": 112,
  "events": [ … ]
}

One event

GET /api/v1/events/{id or slug}

The slug is the end of the event page's address, so /e/code-in-the-dark is /api/v1/events/code-in-the-dark.

{ "version": "v1", "event": { … } }

Tags

GET /api/v1/tags

Every tag in use, most used first: { "version": "v1", "tags": [{ "tag": "ama", "count": 42 }] }

The event object

{
  "id": "8a20db4e-35e8-47a3-a075-d392173a86d9",
  "slug": "code-in-the-dark",
  "url": "https://events.hackclub.com/e/code-in-the-dark/",
  "title": "Code in the Dark",
  "description": "On a live call, we're going to…",
  "start": "2026-10-09T17:00:00.000Z",
  "end": "2026-10-09T18:00:00.000Z",
  "status": "upcoming",
  "kind": "workshop",
  "tags": ["workshop", "beginner-friendly"],
  "featured": true,
  "language": "en",
  "host": {
    "name": "ada",
    "avatar": "https://…",
    "url": "https://events.hackclub.com/hosts/U0ADA12345"
  },
  "location": { "label": "#code-in-the-dark", "url": "https://hackclub.slack.com/…" },
  "rsvps": 24,
  "rsvpUrl": null,
  "image": "https://events.hackclub.com/api/og/?…",
  "youtube": null,
  "ama": false,
  "seriesId": null
}
  • Times are UTC, in ISO 8601.
  • description is Markdown.
  • host.name is the host's Slack display name, or their Slack ID if they haven't set one.
  • status is upcoming, live or ended. Cancelled events are left out.
  • rsvps counts people who RSVPed here. rsvpUrl is set when the organizer collects RSVPs somewhere else instead.
  • location is null when the event has no place set yet.
  • image is the event's link preview image, 1200 × 630.
  • seriesId is shared by every date of a repeating event.

Calendar feed

GET /api/calendar.ics

Every upcoming event as a calendar you can subscribe to in Google Calendar, Apple Calendar or Outlook. Add ?tags=ama to only get some.

Errors

Errors come back with a matching HTTP status and a body like this:

{ "error": { "code": "bad_date", "message": "`from` and `to` have to be dates, like 2026-10-01." } }

Caching

Responses can be cached for a minute. Please don't poll more often than that.

Older endpoints

These still work, so nothing built on them breaks, but new code should use /api/v1. They return everything in one go, in the older format below, and take ?tags=.

{
  "id": "8a20db4e-35e8-47a3-a075-d392173a86d9",
  "slug": "code-in-the-dark",
  "title": "Code in the Dark",
  "desc": "On a live call, we're going to…",
  "leader": "ada",
  "cal": "https://www.google.com/calendar/render?action=TEMPLATE&…",
  "start": "2026-10-09T17:00:00.000Z",
  "end": "2026-10-09T18:00:00.000Z",
  "youtube": null,
  "ama": false,
  "amaId": "",
  "amaAvatar": "",
  "avatar": "https://…",
  "tags": ["workshop"],
  "featured": true
}