Base: https://api.sajilosport.com/api

Courts

Base path: /api/venues/{venue}/courts and /api/courts/{court}/...

Courts belong to a Venue. Customers need court details, availability, and pricing before booking.


Endpoints

GET /api/venues/{venue}/courts

List all active courts for a venue.

Auth: Not required

Path parameter: venue — venue ID (integer)

Response 200:

{
  "data": [
    {
      "id": 1,
      "venue_id": 1,
      "name": "Court A",
      "type": "cricket",
      "sport": { "id": 5, "name": "Cricket", "slug": "cricket", "key": "cricket", "label": "Cricket" },
      "price_per_hour": "2500.00",
      "starting_price": 2500,
      "description": "5-a-side synthetic turf",
      "capacity": 10,
      "is_active": true,
      "images": [],
      "schedules": [],
      "pricing": [],
      "created_at": "2025-01-01 10:00:00"
    }
  ]
}

GET /api/courts/{court}/availability

Check available time slots for a court on a given date.

Auth: Not required

Path parameter: court — court ID

Query parameters:

ParameterTypeRequiredDescription
datedateYesYYYY-MM-DD — must be today or future

Response 200:

{
  "date": "2025-06-15",
  "slot_minutes": 60,
  "is_closed": false,
  "open_time": "06:00",
  "close_time": "22:00",
  "slots": [
    {
      "start_time": "06:00",
      "end_time": "07:00",
      "is_available": true,
      "price_per_hour": "800.00"
    },
    {
      "start_time": "07:00",
      "end_time": "08:00",
      "is_available": false,
      "price_per_hour": "800.00"
    }
  ]
}

Use this to render the time-slot picker in your booking flow. Only offer is_available: true slots for selection.

Slot length comes from the court's slot_minutes (15/30/45/60/90/120, default 60).

If is_closed is true (weekly off day), slots is empty — do not allow booking that day.

Booking create also rejects closed days, outside hours, maintenance overlap, and already-booked overlaps with HTTP 409.


GET /api/courts/{court}/pricing

Get pricing rules for a court (used to show rate cards).

Auth: Not required

Response 200:

{
  "data": [
    {
      "id": 1,
      "type": "standard",
      "day_of_week": null,
      "start_time": "06:00:00",
      "end_time": "18:00:00",
      "price_per_hour": "800.00",
      "is_active": true
    },
    {
      "id": 2,
      "type": "peak",
      "day_of_week": 6,
      "start_time": "18:00:00",
      "end_time": "22:00:00",
      "price_per_hour": "1200.00",
      "is_active": true
    }
  ]
}

Pricing rule types:

  • standard — regular rate
  • peak — higher rate (evenings / weekends)
  • off_peak — discounted rate
  • holiday — applied on holidays

day_of_week: 0 = Sunday, 1 = Monday, ... 6 = Saturday. null = applies every day.


GET /api/courts/{court}/schedule

Get operating hours per day for a court.

Auth: Not required

Response 200:

{
  "data": [
    {
      "id": 1,
      "day_of_week": 0,
      "day_name": "Sunday",
      "open_time": "06:00:00",
      "close_time": "22:00:00",
      "is_closed": false
    },
    {
      "id": 7,
      "day_of_week": 6,
      "day_name": "Saturday",
      "open_time": "06:00:00",
      "close_time": "22:00:00",
      "is_closed": false
    }
  ]
}

CourtResource — Field Reference

FieldTypeNotes
idinteger
venue_idinteger
namestringe.g. "Court A"
typestringe.g. "futsal", "basketball"
descriptionstring or null
capacityintegerMax players per team (both teams combined)
is_activebooleanOnly show active courts
imagesarrayWhen loaded
schedulesarrayWhen loaded — daily open/close times
pricingarrayWhen loaded — pricing rules
created_atdatetime string

Booking Flow — Court Selection

1. GET /api/venues/{slug}               → pick a court
2. GET /api/courts/{court}/availability?date=YYYY-MM-DD  → show slots
3. GET /api/courts/{court}/pricing      → display rate card (optional)
4. POST /api/bookings                   → create the booking