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" }
  }]
}