Waitlist
Join a waitlist when a desired time slot is unavailable. The system automatically offers slots when they become available.
Overview
The waitlist system allows members to:
- Queue for fully-booked time slots
- Receive automatic offers when slots open (cancellations, reschedules)
- Accept offers within a configurable time window
- Track position and priority in the queue
Waitlist Entry Model
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
tenantId | string | Tenant scope |
clubId | string | Club scope |
resourceId | string | Target resource |
memberId | string | Requesting member |
desiredStart | DateTime | Desired start time |
desiredEnd | DateTime | Desired end time |
priorityScore | number | Priority ordering (higher = first offered) |
status | WaitlistStatus | Current status |
offeredAt | DateTime | When slot was offered |
offerExpiresAt | DateTime | Deadline to accept offer |
acceptedAt | DateTime | When offer was accepted |
cancelledAt | DateTime | When entry was cancelled |
Waitlist Status
| Status | Description |
|---|---|
ACTIVE | Waiting for a slot to open |
OFFERED | Slot offered, awaiting acceptance |
ACCEPTED | Offer accepted, reservation created |
EXPIRED | Offer expired, entry returned to queue or closed |
CANCELLED | Manually cancelled by member or admin |
REST API
List Waitlist Entries
GET /facility-waitlist?tenantId=1&clubId=10&resourceId=42&status=ACTIVE
Query Parameters:
tenantId(required) - Tenant scopeclubId(optional) - Club scoperesourceId(optional) - Filter by resourcememberId(optional) - Filter by memberstatus(optional) - Filter by statusdesiredFrom(optional) - Filter by desired start timedesiredTo(optional) - Filter by desired end time
Join Waitlist
POST /facility-waitlist
Content-Type: application/json
{
"tenantId": "t-1",
"clubId": "c-1",
"resourceId": "r-42",
"memberId": "m-9",
"desiredStart": "2026-01-15T10:00:00Z",
"desiredEnd": "2026-01-15T11:00:00Z"
}
Response:
{
"id": "wl-123",
"tenantId": "t-1",
"clubId": "c-1",
"resourceId": "r-42",
"memberId": "m-9",
"desiredStart": "2026-01-15T10:00:00Z",
"desiredEnd": "2026-01-15T11:00:00Z",
"priorityScore": 100,
"status": "ACTIVE",
"createdAt": "2026-01-14T08:30:00Z"
}
Cancel Waitlist Entry
POST /facility-waitlist/:id/cancel?tenantId=1&clubId=10
Content-Type: application/json
{
"reason": "No longer needed"
}
Accept Offered Slot
When a slot is offered, accept it to create a reservation:
POST /facility-waitlist/:id/accept?tenantId=1&clubId=10
Response includes the created reservation:
{
"waitlistEntry": {
"id": "wl-123",
"status": "ACCEPTED",
"acceptedAt": "2026-01-14T09:15:00Z"
},
"reservation": {
"id": "res-456",
"resourceId": "r-42",
"memberId": "m-9",
"startTime": "2026-01-15T10:00:00Z",
"endTime": "2026-01-15T11:00:00Z",
"status": "ACTIVE"
}
}
Decline Offered Slot
Decline to return to the queue or remove from waitlist:
POST /facility-waitlist/:id/decline?tenantId=1&clubId=10
Admin Operations
Offer Slot Manually
Admins can manually offer a slot:
POST /facility-waitlist/:id/offer?tenantId=1&clubId=10
Content-Type: application/json
{
"offerExpiresAt": "2026-01-14T10:00:00Z"
}
Expire Offer
Mark an offer as expired (automated by scheduler):
POST /facility-waitlist/:id/expire?tenantId=1&clubId=10
GraphQL API
Query Waitlist
query FacilityWaitlist {
facilityWaitlist(filters: {
tenantId: "t-1"
resourceId: "r-42"
status: ACTIVE
}) {
id
memberId
desiredStart
desiredEnd
priorityScore
status
createdAt
}
}
Join Waitlist
mutation JoinWaitlist {
createFacilityWaitlistEntry(data: {
tenantId: "t-1"
clubId: "c-1"
resourceId: "r-42"
memberId: "m-9"
desiredStart: "2026-01-15T10:00:00Z"
desiredEnd: "2026-01-15T11:00:00Z"
}) {
id
priorityScore
status
}
}
Accept Offer
mutation AcceptWaitlistOffer {
acceptFacilityWaitlistEntry(id: "wl-123", tenantId: "t-1", clubId: "c-1") {
waitlistEntry {
id
status
acceptedAt
}
reservation {
id
startTime
endTime
}
}
}
Auto-Offer Workflow
When a reservation is cancelled or rescheduled:
- System identifies waitlist entries matching the freed slot
- Entries are sorted by
priorityScore(highest first) - Top entry receives an offer with
offerExpiresAt(default: 1 hour) - If accepted → reservation created, entry marked
ACCEPTED - If expired → entry marked
EXPIREDor returned to queue - If declined → next entry receives offer
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Cancellation │────▶│ Find Matching │────▶│ Offer to Top │
│ or Reschedule │ │ Waitlist Entry │ │ Priority Entry │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
┌───────────────────────────────┴───────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Accepted │ │ Expired │ │ Declined │
│ │ │ │ │ │
│ Create │ │ Offer Next │ │ Offer Next │
│ Reservation│ │ or Close │ │ Entry │
└─────────────┘ └─────────────┘ └─────────────┘
Priority Scoring
Default priority calculation:
priorityScore = basePriority + memberTierBonus + earlyBirdBonus
Where:
basePriority= 100 (default)memberTierBonus= 0-50 based on membership tierearlyBirdBonus= points for joining waitlist early
Higher scores are offered first. Priority can be customized via the rules provider.
Notifications
When offers are made:
- Email: Slot availability notification with accept/decline links
- Push: Mobile push notification with deep link
- SMS: Optional SMS for high-priority offers
Configure notification preferences in member settings.