Skip to main content

Programs and Series

Programs and series are two ways MLH groups related events together.

  • A program is a long-running initiative that many events belong to over time (for example, an ongoing hackathon program).
  • A series is a set of events run together, usually within a season, that share branding and configuration.

Individual events roll up under a program or a series: an event points back to its program and series, and you can list all the events and participations that belong to a series through the nested endpoints below.

All requests are authenticated — see Authentication — and follow the shared conventions in Making requests for pagination, filtering, and expanding related data.

Programs

A program is a named, long-running MLH initiative that events belong to. Programs are read-only through the API: you can list them and fetch a single program, but you cannot create or change them here.

Endpoints

MethodPathWhat it does
GET/v4/programsList programs
GET/v4/programs/{id}Get one program

Both endpoints accept expand to include related records inline, and GET /v4/programs supports the shared pagination and filtering conventions. You can filter the list by name and slug (with operators like [eq], [contains], and [excludes]) and by created_at / updated_at (with range operators like [gt], [gte], [lt], [lte]). See Making requests for the full operator list.

Fields

A program returned by these endpoints has these fields. All are read-only.

FieldTypeNotes
idstringThe program's unique ID. Example: "prg_a1b2c3".
slugstringA URL-friendly identifier for the program. Example: "season-hackathons".
namestringThe program's display name. Example: "Season Hackathons".
created_atintegerWhen the program was created, as a Unix timestamp (seconds).
updated_atintegerWhen the program was last updated, as a Unix timestamp (seconds).

Scopes

Requests authenticate with OAuth 2.0 or a bearer JWT, as described in Authentication. Request only the scopes your integration needs — see the full list of scopes.

Program participations

To list the participations that belong to a program, use the nested collection endpoint:

MethodPathWhat it does
GET/v4/programs/{program_id}/participationsList a program's participations

The program_id path parameter is required. The endpoint is paginated (page, limit) and supports expand[]=event and expand[]=user to include the related event and user inline. Each participation carries the participant's status, name, contact details, source, and links to its user and event — the same shape documented on the Participations page.

Examples

List programs whose name contains "hack":

GET /v4/programs?name[contains]=hack&limit=50

Get one program:

GET /v4/programs/{id}

List a program's participations, expanding the user and event:

GET /v4/programs/{program_id}/participations?expand[]=user&expand[]=event

Series

A series is a group of events run together — typically within a season — that share branding and settings. Unlike programs, series support full CRUD: you can list, read, create, and update them.

Endpoints

MethodPathWhat it does
GET/v4/seriesList series
GET/v4/series/{id}Get one series
POST/v4/seriesCreate a series
PATCH / PUT/v4/series/{id}Update a series

PATCH and PUT /v4/series/{id} behave identically — both update an existing series. GET /v4/series supports the shared pagination and filtering conventions: you can filter by name and slug ([eq], [contains], [excludes]) and by starts_at, ends_at, created_at, and updated_at (range operators like [gt], [gte], [lt], [lte]). See Making requests.

Fields

These are the fields you can set when creating or updating a series, and read back on GET.

FieldRequiredWhat it does
nameOptionalThe series' display name. Example: "Fall 2026 Hackathons".
slugOptionalA URL-friendly identifier for the series. Example: "fall-2026".
website_urlOptionalThe series' public website. Example: "https://fall2026.example.com".
chat_urlOptionalA link to the series' chat (for example, Discord or Slack). Example: "https://discord.gg/example".
logo_urlOptionalA link to the series' logo image. Example: "https://cdn.example.com/logo.png".
starts_atOptionalWhen the series starts. Send as an ISO 8601 datetime string. Example: "2026-09-01T00:00:00Z".
ends_atOptionalWhen the series ends. Send as an ISO 8601 datetime string. Example: "2026-12-01T00:00:00Z".
settingsOptionalA free-form object of series-level configuration. Example: { "theme": "dark" }.
idOptionalThe series' ID. Read-only — the API assigns it.
created_atOptionalAn ISO 8601 datetime string. Normally set by the API; only send it when importing historical data.
updated_atOptionalAn ISO 8601 datetime string. Normally set by the API; only send it when importing historical data.

A series returned by GET has the same fields, with these read/write differences:

FieldTypeNotes
idstringThe series' unique ID. Read-only.
starts_atintegerStart time as a Unix timestamp (seconds) on reads.
ends_atintegerEnd time as a Unix timestamp (seconds) on reads.
created_atintegerWhen the series was created, as a Unix timestamp (seconds). Read-only.
updated_atintegerWhen the series was last updated, as a Unix timestamp (seconds). Read-only.

Note the timestamp difference between reads and writes: GET responses return starts_at, ends_at, created_at, and updated_at as Unix timestamps (integers), while the create and update request bodies accept them as ISO 8601 datetime strings.

Scopes

Requests authenticate with OAuth 2.0 or a bearer JWT, as described in Authentication. Request only the scopes your integration needs — see the full list of scopes.

Series events

To list the events that belong to a series, use the nested collection endpoint:

MethodPathWhat it does
GET/v4/series/{series_id}/eventsList a series' events

The series_id path parameter is required. The endpoint is paginated (page, limit) and supports expand[] for associations such as series, sponsors, organizers, lead_organizer, sponsorships, prize_categories, and event_application. Each event has the full event shape — see Events.

Series participations

To list the participations that belong to a series, use the nested collection endpoint:

MethodPathWhat it does
GET/v4/series/{series_id}/participationsList a series' participations

The series_id path parameter is required. The endpoint is paginated (page, limit) and supports expand[]=event and expand[]=user. Each participation carries the participant's status, name, contact details, source, and links to its user and event — the same shape documented on the Participations page.

Examples

Create a series:

POST /v4/series
Content-Type: application/json

{
"name": "Fall 2026 Hackathons",
"slug": "fall-2026",
"website_url": "https://fall2026.example.com",
"starts_at": "2026-09-01T00:00:00Z",
"ends_at": "2026-12-01T00:00:00Z"
}

Update a series:

PATCH /v4/series/{id}
Content-Type: application/json

{
"chat_url": "https://discord.gg/example"
}

List a series' events:

GET /v4/series/{series_id}/events?expand[]=organizers&limit=50

List a series' participations, expanding the user and event:

GET /v4/series/{series_id}/participations?expand[]=user&expand[]=event