Bookings
Base path: /api/bookings
All booking endpoints require authentication.
Booking Statuses
| Status | Description |
|---|---|
pending | Created but not yet paid |
confirmed | Payment received |
playing | Session in progress (set by staff) |
completed | Session finished |
cancelled | Cancelled by customer or staff |
no_show | Customer did not show up |
Booking Types
| Type | Description |
|---|---|
online | Booked through the mobile app |
offline | Booked in person by staff |
walkin | Walk-in session registered by staff |
Endpoints
GET /api/bookings [Auth required]
List all bookings for the authenticated user.
Response 200:
{
"data": [
{
"id": 42,
"booking_number": "BK-2025-0042",
"type": "online",
"status": "confirmed",
"date": "2025-06-15",
"start_time": "08:00",
"end_time": "09:00",
"duration_hours": "1.00",
"base_amount": "800.00",
"discount_amount": "100.00",
"total_amount": "700.00",
"paid_amount": "700.00",
"balance_due": "0.00",
"is_paid": true,
"extras_total": null,
"customer_name": "Jane Doe",
"customer_phone": "9800000000",
"notes": null,
"cancel_reason": null,
"cancelled_at": null,
"court_id": 1,
"court": { "id": 1, "name": "Court A", ... },
"user": { ... },
"payments": [],
"charges": [],
"coupon_usage": null,
"review": null,
"created_at": "2025-06-10 09:00:00"
}
]
}POST /api/bookings [Auth required]
Create a new online booking.
Request body:
{
"court_id": 1,
"date": "2025-06-15",
"start_time": "08:00",
"end_time": "09:00",
"coupon_code": "SUMMER20",
"notes": "Extra balls needed",
"payment_method": "esewa"
}| Field | Type | Required | Description |
|---|---|---|---|
court_id | integer | Yes | ID of the court to book |
date | date | Yes | YYYY-MM-DD, must be today or future |
start_time | time | Yes | HH:mm (24-hour) |
end_time | time | Yes | HH:mm, must be after start_time |
coupon_code | string | No | Discount coupon code |
notes | string | No | Optional note for staff |
payment_method | string | No | esewa, khalti, fonepay, wallet, cash |
Response 201:
{
"data": { ...BookingResource... }
}Response 409 — slot taken:
{ "message": "The court is not available for the selected time slot." }GET /api/bookings/{booking} [Auth required]
Get details of a specific booking. Only the booking owner can access it.
Response 200:
{
"data": { ...BookingResource with court, user, payments, charges... }
}PATCH /api/bookings/{booking}/cancel [Auth required]
Cancel a booking.
Request body:
{
"reason": "Change of plans"
}| Field | Type | Required | Description |
|---|---|---|---|
reason | string | No | Cancellation reason |
Response 200:
{
"data": { ...BookingResource with status: "cancelled"... }
}Response 403 — cannot cancel (wrong ownership or booking already completed):
{ "message": "This action is unauthorized." }BookingResource — Field Reference
| Field | Type | Notes |
|---|---|---|
id | integer | |
booking_number | string | Human-readable reference e.g. BK-2025-0042 |
type | string | online, offline, walkin |
status | string | See statuses table above |
date | date string | YYYY-MM-DD |
start_time | string | HH:mm |
end_time | string | HH:mm |
duration_hours | decimal string | e.g. "1.50" |
base_amount | decimal string | Price before discount |
discount_amount | decimal string | Discount applied |
total_amount | decimal string | Amount due |
paid_amount | decimal string | Amount already paid |
balance_due | decimal string | Remaining amount owed |
is_paid | boolean | true when fully paid |
extras_total | decimal or null | Sum of session charges (drinks, equipment, etc.) |
customer_name | string | |
customer_phone | string or null | |
notes | string or null | |
cancel_reason | string or null | |
cancelled_at | datetime or null | |
court_id | integer | |
court | object | Loaded on show |
user | object | Loaded on show |
payments | array | Payment history |
charges | array | Extra session charges |
coupon_usage | object or null | Coupon that was applied |
review | object or null | Review left for this booking |
created_at | datetime string |
End-to-End Booking Flow
1. GET /api/venues/nearby?lat=...&lng=... → pick venue
2. GET /api/courts/{court}/availability?date=... → pick slot
3. POST /api/coupons/validate → (optional) apply coupon
4. POST /api/bookings → create booking
5. POST /api/payments/initiate → initiate payment
6. (user pays via gateway)
7. POST /api/payments/{gateway}/callback → gateway posts back
8. GET /api/bookings/{id} → show confirmation