Skip to main content

Leagues

A league (an event series in the API) is a season a golfer registers and pays for once. Every event linked to it draws its field from the league roster, including golfers who join after those events were created — so a Thursday-night league is set up in one place rather than event by event.

Everything on this page is public and unauthenticated. Managing a league — its roster, its teams, its linked events — is an admin API and is not part of the public surface.

List an organization's leagues

curl "https://api.front9.com/api/public/v1/orgs/{orgSlug}/event-series"

Returns leagues that are open, active or completed. Draft and private leagues are omitted; members-only leagues appear (registration is gated separately, the same way events behave).

[
{
"id": 7,
"name": "Thursday Night Simulator Scramble",
"slug": "thursday-night-simulator-scramble",
"seasonLabel": "2026 season",
"scheduleLabel": "Thursdays: 7:00-9:30",
"status": "active",
"feeMembersCents": 12000,
"feePerEntry": true,
"entrySize": 2,
"seriesImageUrl": "/media/defaults/event-series/league-1.png",
"memberCount": 20,
"linkedEventCount": 4
}
]

Two fields shape everything else:

  • entrySize1 is an individual league. 2 or more makes it a team league: golfers register as a declared pair (or foursome) that stays together all season, and the teams below apply.
  • feePerEntry — when true the fee buys a whole entry, so a pair pays once between them and the partner joins free. When false every golfer pays.

memberCount is the active roster size and linkedEventCount how many events the league feeds, so a listing page needs no second round trip. All prices are in cents.

scheduleLabel is free text for when the league plays, written by the organizer — "Thursdays: 7:00-9:30". Render it as given: it is never parsed, may say anything ("alternate Sundays, weather permitting"), and may be absent. The authoritative dates are on the linked events; this is the one-line answer to "when is this league?" for a listing or a header.

Get a single league

curl "https://api.front9.com/api/public/v1/orgs/{orgSlug}/event-series/{slug}"

Same shape, addressed by slug — this is the league's public landing page. Returns 404 for a league that is private or still in draft, so a not-found and a not-public league are indistinguishable from outside.

A league's schedule and standings

A league page usually knows one thing: the league's slug, out of its own URL. Both of the things such a page wants to show are addressable that way, so it never has to learn an internal id.

The nights, from the ordinary event list:

curl "https://api.front9.com/api/public/v1/orgs/{orgSlug}/events?filter=all&eventSeries={slug}"

eventSeries matches on the link between an event and its league — the one an admin makes when adding a night — not on a tag or a naming convention, so the schedule cannot drift from the league itself. It combines with the other filters (tag, filter, year), and a slug that names no public league is a 404.

The table:

curl "https://api.front9.com/api/public/v1/orgs/{orgSlug}/event-series/{slug}/standings"
{
"standingSeries": { "id": 5, "name": "Mixed 9-Team League", "scope": "team", "seasons": [] },
"table": { "seriesId": 5, "seriesName": "Mixed 9-Team League", "rows": [] }
}

The league carries the link to its standings table (standingSeriesId), so this resolves it for you. The series comes back alongside the table because a season-based league needs its seasons to offer a season picker, and because standingSeries.id is what every follow-up request uses — a different season (?seasonId=), or a competitor's contributions — through the ordinary standings endpoints.

A league with no standings table linked answers 200 with both fields null. The league is real, it simply hasn't been wired up, and a page can say so rather than show an error. Set standingSeriesId on the league to connect the two.

Start a registration

As with events and memberships, payment never flows through this API. The start endpoint hands you a hosted URL where Front9 collects the card.

curl -X POST \
"https://api.front9.com/api/public/v1/orgs/{orgSlug}/event-series/{id}/register/start"
{ "url": "https://registration.front9.com/?org=acme&eventSeries=7" }

Redirect the golfer to url to finish registering and pay for the season.

On a team league, pass ?eventSeriesTeam={teamId} to land the golfer on an existing team rather than starting a new one — this is what a partner following an invite link needs:

curl -X POST \
"https://api.front9.com/api/public/v1/orgs/{orgSlug}/event-series/{id}/register/start?eventSeriesTeam=12"

The parameter is passed straight through to the hosted page, so forward org, eventSeries and eventSeriesTeam through your signup flow if the golfer has to create an account on the way.

On a team league, a registrant names their partners and each is emailed a join link. Before that visitor has an account, you can read what they are joining:

curl "https://api.front9.com/api/public/v1/orgs/{orgSlug}/event-series/{id}/teams/{teamID}"
{
"id": 12,
"name": "Wolfpack",
"memberNames": ["Jamie Lee"],
"entrySize": 4,
"seatsFilled": 1,
"seatsRemaining": 3,
"complete": false
}

Deliberately narrow: names and counts only — never user ids, never the invited email addresses. It is served to whoever holds the link.

Use it to show what the visitor is joining and how many seats are open. The seats they can fill for other people is seatsRemaining - 1 — their own seat comes out of the same total.

Partner invites

When the invited golfer already has a Front9 account, their emailed link carries an inviteToken. Resolve it to render the join page:

curl "https://api.front9.com/api/public/v1/event-series-invites/{token}"
{
"eventSeries": {
"id": 7,
"slug": "thursday-night-simulator-scramble",
"name": "Thursday Night Simulator Scramble",
"orgSlug": "acme",
"orgName": "Acme GC"
},
"team": {
"id": 12,
"name": "Wolfpack",
"memberNames": ["Jamie Lee"],
"entrySize": 4,
"seatsFilled": 1,
"seatsRemaining": 3,
"complete": false
},
"inviter": { "firstName": "Jamie", "lastName": "Lee" },
"email": "partner@example.com",
"feeCents": 12000,
"accepted": false
}
  • feeCents — what this golfer owes. Unlike an event invite nobody else is covering it: a league partner pays their own season fee. The exception is a feePerEntry league where a teammate has already bought the entry, in which case it comes back 0.
  • accepted — the link outlives the invite. Once the golfer registers it keeps resolving with accepted: true, so a second click can say "you're already registered" instead of erroring. It stops resolving only if the team is deleted.
  • team — absent if the team has since been deleted.

An invited address with no Front9 account gets no token; their link carries only org, eventSeries and eventSeriesTeam, and the team endpoint above is all you need to render it.

404 if the token is unknown.

Leagues feed the ordinary event endpoints — a league night is a normal event, so its field, tee sheet, leaderboard and live streams are the same endpoints as any other. See Real-time updates and the API reference.