Skip to main content

Promo Codes

MLH promo codes let sponsors and event organizers hand out perks — free credits, discounts, or access links — to participants. Three resources work together:

  • A promo code pool groups related codes and holds the settings they share: who the codes come from (an MLH sponsorship or an event), how many times each person can redeem, when they expire, and where the codes are distributed.
  • A promo code is an individual code that belongs to a pool. It carries the actual code string, its own redemption limit, and whether it's active.
  • A promo code redemption records one user using one code — a read-only audit trail of who redeemed what, and when.

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

Promo Code Pools

A pool is the container you create first; every promo code points back to a pool through its promo_code_pool_id.

Endpoints

MethodPathWhat it does
GET/v4/promo_code_poolsList promo code pools
GET/v4/promo_code_pools/{id}Get one promo code pool
POST/v4/promo_code_poolsCreate a promo code pool
PATCH / PUT/v4/promo_code_pools/{id}Update a promo code pool
DELETE/v4/promo_code_pools/{id}Delete a promo code pool
GET/v4/promo_code_pools/newGet a blank set of pool attributes
GET/v4/promo_code_pools/{id}/editGet an existing pool's attributes, prefilled

The new and {id}/edit endpoints are form helpers. They don't create or change anything — they return a plain attributes object you can use to build a create or edit form. new returns a blank template of the fields you can set; {id}/edit returns the same shape prefilled with an existing pool's values.

Fields

Set these in the request body on create and update. On reads, created_at, updated_at, and expires_at come back as Unix timestamps (integers, seconds); in the request body, datetimes are sent as ISO 8601 strings.

FieldRequiredWhat it does
labelOptionalA short human-readable name for the pool. Example: "GHW 2026 Credits".
descriptionOptionalA longer description of what the codes are for. Example: "$50 in cloud credits for GHW participants".
code_typeOptionalHow codes in the pool are shaped. One of individualized (a unique code per person) or shared (one code many people use). Example: "individualized".
access_typeOptionalHow participants get a code. One of automatic (handed out by the system) or manual (distributed by hand). Example: "automatic".
mlh_sponsorship_idOptionalThe ID of the MLH sponsorship this pool belongs to. Example: "mspon_a1b2c3". See MLH Sponsorships.
event_idOptionalThe ID of the event this pool is tied to. Example: "evt_x9y8z7". See Events.
per_user_limitOptionalHow many times a single user may redeem from this pool. Example: 1.
link_expiration_daysOptionalHow many days a generated redemption link stays valid. Example: 7.
redemption_urlOptionalThe URL a participant is sent to in order to redeem. Example: "https://sponsor.example.com/redeem".
restrictionsOptionalFree-form text describing any limits on who can use the codes. Example: "US students only".
distribution_channelsOptionalAn array of channels the codes are distributed through. Example: ["email", "dashboard"].
activeOptionalWhether the pool is currently active. Example: true.
expires_atOptionalWhen the pool expires. ISO 8601 string on write; Unix timestamp on read. Example: "2026-12-31T23:59:59Z".
idOptionalThe pool's unique ID. Read-only; set by the API.
created_atOptionalWhen the pool was created. Read-only on responses (Unix timestamp).
updated_atOptionalWhen the pool was last updated. Read-only on responses (Unix timestamp).

List results can be filtered by code_type, access_type, active, mlh_sponsorship, event, created_at, updated_at, and expires_at, and expanded with expand. See Making requests.

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.

Example

Create a pool:

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

{
"label": "GHW 2026 Credits",
"description": "$50 in cloud credits for GHW participants",
"code_type": "individualized",
"access_type": "automatic",
"mlh_sponsorship_id": "mspon_a1b2c3",
"per_user_limit": 1,
"active": true,
"expires_at": "2026-12-31T23:59:59Z"
}

Promo Codes

A promo code is an individual code inside a pool. Create the pool first, then create codes that reference it.

Endpoints

MethodPathWhat it does
GET/v4/promo_codesList promo codes
GET/v4/promo_codes/{id}Get one promo code
POST/v4/promo_codesCreate a promo code
PATCH / PUT/v4/promo_codes/{id}Update a promo code

Fields

Set these in the request body on create and update. On reads, created_at, updated_at, and expires_at come back as Unix timestamps (integers, seconds); in the request body, datetimes are sent as ISO 8601 strings.

FieldRequiredWhat it does
codeOptionalThe code string a participant enters or follows. Example: "MLH-GHW-A1B2C3".
promo_code_pool_idOptionalThe ID of the pool this code belongs to. Example: "pcp_a1b2c3".
redemption_limitOptionalThe maximum number of times this specific code can be redeemed. Example: 100.
activeOptionalWhether the code can currently be redeemed. Example: true.
expires_atOptionalWhen this code stops working. ISO 8601 string on write; Unix timestamp on read. Example: "2026-12-31T23:59:59Z".
mlh_sponsorshipOptionalThe ID of the associated MLH sponsorship. Example: "mspon_a1b2c3". See MLH Sponsorships.
eventsOptionalAn array of event IDs the code applies to. Example: ["evt_x9y8z7"]. See Events.
idOptionalThe code's unique ID. Read-only; set by the API.
created_atOptionalWhen the code was created. Read-only on responses (Unix timestamp).
updated_atOptionalWhen the code was last updated. Read-only on responses (Unix timestamp).

When you read a code, promo_code_pool_id is the pool's ID; promo_code_pool holds the expanded pool when you request it. List results can be filtered by code, redemption_limit, active, created_at, updated_at, and expires_at. Use expand[] to inline related records — the expandable associations are promo_code_pool, mlh_sponsorship, and events:

GET /v4/promo_codes/{id}?expand[]=promo_code_pool&expand[]=events

See Making requests for how expand works across the API.

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.

Example

Create a code in a pool:

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

{
"code": "MLH-GHW-A1B2C3",
"promo_code_pool_id": "pcp_a1b2c3",
"redemption_limit": 100,
"active": true,
"expires_at": "2026-12-31T23:59:59Z"
}

Promo Code Redemptions

A redemption records one user redeeming one promo code. This resource is read-only — redemptions are created by the redemption flow, not through the API. You can list them and get one by ID.

Endpoints

MethodPathWhat it does
GET/v4/promo_code_redemptionsList promo code redemptions
GET/v4/promo_code_redemptions/{id}Get one promo code redemption

Fields

All fields are read-only. created_at, updated_at, and redeemed_at are returned as Unix timestamps (integers, seconds).

FieldTypeNotes
idstringThe redemption's unique ID.
promo_code_idstringThe ID of the promo code that was redeemed.
user_idstringThe ID of the user who redeemed it.
event_idstringThe ID of the event the redemption happened at, if any. See Events.
redeemed_atintegerWhen the code was redeemed, as a Unix timestamp (seconds).
created_atintegerWhen the redemption record was created, as a Unix timestamp (seconds).
updated_atintegerWhen the redemption record was last updated, as a Unix timestamp (seconds).

List results can be filtered by promo_code, user, event, and redeemed_at, and expanded with expand. See Making requests.

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.