Skip to main content

Availability Check

Query available facility resources for a specific time window.

Last updated: 2026-01-26 Where to find it: Facilities API > Availability Who can use it: Developers, integrators Prerequisites: API credentials Help link: /availability

Purpose

The availability check allows you to find resources that are:

  • Active (not soft-deleted)
  • Not currently assigned during the requested time window
  • Within operating hours
  • Not in a blackout window
  • Not reserved by an active facility reservation
  • Of a specific type (optional)

Request

REST API

POST /facility-resources/availability
Content-Type: application/json

{
"tenantId": 1,
"clubId": 10,
"type": "SIMULATOR",
"start": "2025-01-15T10:00:00Z",
"end": "2025-01-15T12:00:00Z"
}

GraphQL API

mutation FacilityAvailability {
facilityAvailability(request: {
tenantId: 1
clubId: 10
type: SIMULATOR
start: "2025-01-15T10:00:00Z"
end: "2025-01-15T12:00:00Z"
}) {
resourceId
name
type
available
}
}

Request Parameters

FieldTypeRequiredDescription
tenantIdnumberYesTenant scope
clubIdnumberNoClub scope
typeResourceTypeNoFilter by resource type
startDateTimeYesStart of time window
endDateTimeYesEnd of time window

Response

[
{
"resourceId": 5,
"name": "Simulator Bay 1",
"type": "SIMULATOR",
"available": true
},
{
"resourceId": 6,
"name": "Simulator Bay 2",
"type": "SIMULATOR",
"available": true
}
]

Validation

The service validates:

  • start must be before end
  • Time window must be in the future (configurable)
  • type must be a valid ResourceType
{
"statusCode": 400,
"message": "start must be before end",
"error": "Bad Request"
}

Availability Logic

A resource is considered available if:

  1. active = true (not soft-deleted)
  2. maintenanceRequired = false (optional, configurable)
  3. No overlapping ResourceUsage records exist where:
    • assignedAt < requestedEnd
    • releasedAt IS NULL OR releasedAt > requestedStart
  4. No overlapping MaintenanceLog records exist in the window
  5. The request falls within FacilityHours (when hours are defined)
  6. No overlapping FacilityBlackout entries apply (resource/type/club/tenant)
  7. No overlapping active FacilityReservation entries exist
SELECT fr.*
FROM facility_resources fr
WHERE fr.tenant_id = $tenantId
AND fr.active = true
AND fr.type = $type
AND NOT EXISTS (
SELECT 1 FROM resource_usage ru
WHERE ru.resource_id = fr.id
AND ru.assigned_at < $end
AND (ru.released_at IS NULL OR ru.released_at > $start)
)

Reservations, blackouts, and operating hours are enforced in the service layer and are not shown in the SQL above.

Use Cases

1. Booking Flow

Check available simulators before creating a booking:

# Step 1: Check availability
POST /facility-resources/availability
{ "tenantId": 1, "type": "SIMULATOR", "start": "...", "end": "..." }

# Step 2: Create booking with selected resource
POST /bookings
{ "resourceId": 5, ... }

# Step 3: Record resource usage
POST /resource-usage
{ "resourceId": 5, "bookingId": 123, "assignedAt": "..." }

2. Maintenance Planning

Find available time slots for maintenance:

POST /facility-resources/availability
{
"tenantId": 1,
"type": "DRIVING_RANGE",
"start": "2025-01-20T06:00:00Z",
"end": "2025-01-20T10:00:00Z"
}

3. Capacity Dashboard

Check current availability across all resource types:

const types = ['SIMULATOR', 'GOLF_CART', 'DRIVING_RANGE'];
const now = new Date();
const endOfDay = /* ... */;

const availability = await Promise.all(
types.map(type =>
fetch('/api/facility-resources/availability', {
method: 'POST',
body: JSON.stringify({ tenantId, type, start: now, end: endOfDay })
})
)
);

Expected outcome

  • Available resources are returned for a time window.
  • Maintenance, blackouts, and reservations are respected.
  • Booking flow integrates with availability checks.