The Public API gives organization admins direct HTTP access to your organization's live data — pull it into any website, app, bot, or automation that can make an HTTP request. It's a Business plan feature.

The key is scoped to your organization — all endpoints operate on that group automatically. Base URL: https://api.ludoya.com/public/v1. Auth header: X-Api-Key: YOUR_KEY. Rate limit: 100 requests/minute.

What You Can Access

  • Locations — your group's available venues and their spots; used as input when creating events
  • Events (read) — upcoming and past events with title, description, date/time, timezone, capacity, participant count, and status
  • Events (write) — create and update events via POST and PUT, with full control over location, capacity, permissions, visibility, and image
  • Members — member list with user profiles and roles (Owner, Admin, Member), paginated
  • Collection — game collection with filtering by ownership, name, player count, and list; sortable and paginated; each game includes BGG metadata
  • Stats — play statistics for any time period: totals, averages, top players with wins and scores, per-player-count breakdowns, per-location, and per-game
  • Campaigns (read) — list the group's campaigns with member and session counts; retrieve full campaign detail including members, past sessions, and scheduled events
  • Campaigns (write) — create campaigns for the group and update their name, description, status, and visibility

Endpoints

GET /locations

Returns the group's available locations. Each location has an id, name, optional address, capacity, an isDefault flag, and a spots array (each spot has its own id, name, and capacity). Use location and spot IDs when creating events.


GET /events

Returns future and past events in separate paginated lists.

Param Type Default Description
onlyFuture boolean true Set false to also return past events

Each event includes: type (MEETUP or PLANNED_PLAY), title, description, startsAt, endsAt, timeZone, imageUrl, capacity, participantCount, canceled, teacher (user object or null), master (user object or null). User objects contain id, username, name, avatarUrl.


POST /events

Creates an event in the group. Required fields: type and title. If locationId is omitted, the group's default location is used; if none exists, returns 400.

Optional fields include: description, locationId, spotId, gameId, parentEventId (for sub-events), startsAt, endsAt, restrictedAttendance, capacity, minParticipants, estimatedDurationMinutes, allowReservations, takeGamesPermission, organizePlaysPermission, teacherUserId, masterUserId, visibility, image.

The image field accepts either {"base64": "data:image/jpeg;base64,..."} or {"url": "https://..."}. Max 5 MB.

Returns {"id": "string"} with status 201.


PUT /events/{eventId}

Updates an existing event. Same body shape as POST — only include the fields you want to change. The caller must be the event organizer (the group account). Returns 202 with empty body.


GET /members

Returns a paginated member list.

Param Type Default
pagination.size int 50
pagination.offset int 0

Each member includes: id, username, name, avatarUrl, role (OWNER, ADMIN, or MEMBER).


GET /collection

Returns your game collection with filtering, sorting, and pagination.

Param Type Default Description
filter string Semicolon-separated key=value pairs. Keys: ownership (OWNED, PREVIOUSLY_OWNED, PREORDERED, WISHLISTED), played (boolean), listId, nameFilter, playerCountFilterType (OFFICIAL, GOOD, BEST), playerCountFilter (number)
groupExpansions boolean true Group expansions under their base game
sort string Format: property,direction — e.g. name,asc
pagination string Format: size,pageIndex — e.g. 20,0

Response: totalGames, totalExpansions, games[] — each with: id, slug, name, imageUrl, isExpansion, yearPublished, minPlayerCount, maxPlayerCount.


GET /stats

Returns play statistics for a configurable time window.

Param Type Default Description
period string ALL_TIME Format: PERIOD,date,index. Values: ALL_TIME, ONE_YEAR, ONE_MONTH, THIRTY_DAYS, SEVEN_DAYS, ONE_DAY, CUSTOM. The index shifts the window back (0 = current, 1 = previous). Custom: CUSTOM,startDate,0,endDate

Response includes:

  • Summary — total plays, total/average play time, unique game, player, and location counts
  • By player — per-person plays, wins, average and best score
  • By player count — breakdown of 2-player, 3-player, 4-player games, etc.
  • By location — play count and unique games per venue
  • By game — play count, total/average play time, and unique players per title

GET /campaigns

Returns a paginated list of campaigns belonging to the group.

Param Type Default Description
status string Filter by status: ACTIVE, COMPLETED, or ARCHIVED
pagination.size int 50 Items per page
pagination.offset int 0 Offset

Each campaign includes: id, game (id, name, imageUrl), name, image, status, visibility, createdAt, updatedAt, memberCount, sessionCount.


GET /campaigns/{campaignId}

Returns the full detail of a campaign belonging to the group.

Response includes: All list fields, plus template, description, globalNotes, globalState, members[] (each with user, role, characterNotes, characterState), sessions[], and events[].


POST /campaigns

Creates a campaign for the group. Required fields: gameId and name. Visibility defaults to group-members-only (ONLY_GROUP) if omitted.

Optional fields: templateId, description, visibility (PUBLIC, ONLY_GROUP, ONLY_FRIENDS, or PRIVATE).

Returns {"id": "string"} with status 201.


PUT /campaigns/{campaignId}

Updates an existing campaign. All fields are optional — only include what you want to change.

Optional fields: name, description, status (ACTIVE, COMPLETED, ARCHIVED), visibility.

Returns 202 with empty body.


Error Codes

Status When
400 Validation failure (missing required field, no location found, invalid image)
401 Missing or invalid API key
403 Action not permitted or group not on Business plan
404 Resource not found
429 Rate limit exceeded

Getting Started

1. Generate an API Key

  1. Go to your organization's profile page
  2. Tap the menu () → Public API
  3. Tap Generate key
  4. Copy your key immediately — it is shown only once and cannot be retrieved again

The key is tied to your organization. Keep it secret: anyone with the key can read and write all of the data above.

2. Revoke or Regenerate

To revoke an existing key, go back to the Public API page and tap Revoke. Confirm the dialog. Any system using the old key will immediately start receiving 401 errors. To issue a new key, tap Generate key again.


See also:

  • Organizations — organization accounts and premium features
  • Premium — Business plan pricing
  • Integrations — other ways to connect Ludoya with external tools