API Design
Two route families serving three clients. Web admin uses server-rendered pages with session auth; mobile apps consume JSON:API REST endpoints with JWT auth.
Two Route Families
Web Routes — /admin/*
Server-rendered pages for the admin dashboard. Session/cookie authentication. Admin and field manager roles only.
API Routes — /api/v1/*
JSON:API REST endpoints returning structured JSON. JWT authentication. Used by the Flutter mobile apps (FM app + customer app).
JSON:API Conventions
| Feature | Query Parameter | Example |
|---|---|---|
| Pagination | ?page[number] & ?page[size] |
?page[number]=1&page[size]=25 (max 100) |
| Filtering | ?filter[field]=value |
?filter[status]=confirmed&filter[dateFrom]=2026-03-01 |
| Sorting | ?sort=field (prefix - for desc) |
?sort=-date,startTime |
| Includes | ?include=relation |
?include=field,creator (eager-load relationships) |
| Sparse Fieldsets | ?fields[type]=field1,field2 |
?fields[bookings]=date,status,price |
Key Mobile API Endpoints
Auth
POST
/api/v1/auth/otp/send
Request OTP code
POST
/api/v1/auth/otp/verify
Verify OTP code
POST
/api/v1/auth/pin/create
Create PIN for returning user
POST
/api/v1/auth/pin/verify
Verify PIN login
Fields & Schedule
GET
/api/v1/fields
List fields (FM: scoped to assigned)
GET
/api/v1/fields/:id
Field details
GET
/api/v1/schedule/slots?field={id}&date={YYYY-MM-DD}
Available slots
Bookings
POST
/api/v1/bookings/hold
Hold a slot (5 min)
POST
/api/v1/bookings
Create booking
GET
/api/v1/bookings
List bookings
GET
/api/v1/bookings/:id
Booking details
PATCH
/api/v1/bookings/:id
Update booking
DELETE
/api/v1/bookings/:id
Cancel booking
Payments
POST
/api/v1/payments
Record payment
GET
/api/v1/payments
Payment history
Contracts
GET
/api/v1/contracts
List contracts
GET
/api/v1/contracts/:id
Contract details
Other
GET
/api/v1/customer-contacts?phone=0512345678
Customer lookup
POST
/webhooks/whatsapp/messages
WAHA incoming
POST
/webhooks/whatsapp/status
WAHA delivery status
Role-Based Access Control
| Role | Scope | Can Do |
|---|---|---|
| admin | All data | Everything — CRUD all entities, manage users, view analytics |
| executive | All data (read-only) | View dashboards, reports, analytics. No create/edit |
| field_manager | Assigned fields only | Create/manage bookings, record payments, view schedule for their fields |
| customer | Own data only | Browse fields, create bookings, view own booking history |
FM scoping is middleware-enforced: Field managers are scoped to specific fields via middleware. Every query must filter by assigned fields. This is middleware-enforced, not UI-hidden.
Error Response Format
All API errors follow the JSON:API error format. Every error includes a machine-readable code, a human-readable title and detail, and optionally a source pointer to the offending field.
{
"errors": [{
"status": "422",
"code": "BOOKING_CONFLICT",
"title": "Slot Unavailable",
"detail": "Field Al-Nakheel Court 1 is already booked on 2026-03-15 from 18:00 to 19:00",
"source": { "pointer": "/data/attributes/startTime" }
}]
}