# API Reference Base URL is the deployed backend host. Recommended production backend host: - Railway service URL for this repository Current public model-service host (used by backend when `MODEL_INFERENCE_PROVIDER=remote`): - `https://pant0x-ealpr-ocr.hf.space` ## Authentication Model Most business endpoints require: - `Authorization: Bearer ` - For device integrations, backend can also accept: - `Authorization: Bearer ` - Enabled when `BARRIER_API_TOKEN` or `BARRIER_API_TOKENS` is configured. Auth behavior is controlled by backend env config. ### Backend auth endpoints 1. `POST /auth/register` - JSON body: - `first_name` (recommended) - `last_name` (recommended) - `username` (required) - `phone` or `phone_number` (required) - `password` (required) - `email` (optional) - `nid` or `national_id` (optional) - legacy fallback: `full_name` or `name` (optional) - optional vehicle payload fields: - `plate_letters_ar`, `plate_numbers_ar` - `plate_letters_en`, `plate_numbers_en` - `car_model`, `car_color` - or nested under `vehicle` object - Returns user object + session tokens. - `user.full_name` is derived from `first_name + last_name`. - Register contract is idempotent for OTP-created users: if OTP verify already created/authenticated a user for the same email, register finalizes profile/password instead of failing on duplicate email for the same account. 2. `POST /auth/login` - JSON body: - `identifier` (username OR phone OR email OR nid) - `password` - Also accepts direct keys (`username`, `phone`, `email`, `nid`) instead of `identifier`. - Returns user object + session tokens. 3. `POST /auth/otp/request` - JSON body: - `purpose` (`register`, `vehicle_verify`, `profile_update`) - `channel` (`email` or `phone`) - contact value (`email` or `phone`) unless inferable from authenticated profile - optional `redirect_to` for email OTP link flows - Sends OTP via Supabase auth. - For `purpose=register|signup`, backend forces `create_user=true` to ensure new emails/phones can receive OTP for account creation. - For non-register purposes, `create_user` from client is still honored. - If OTP signup is disabled in provider config for register flow, API returns a clear contract error: `OTP signup is disabled in backend auth configuration (otp_disabled). purpose=register cannot proceed with OTP until OTP signups are enabled.` 4. `POST /auth/otp/verify` - JSON body: - `channel` (`email` or `phone`) - `otp_token` - contact value (`email` or `phone`) - optional `verify_type` - Verifies OTP and returns auth session payload. ## Endpoint Catalog ### Authentication 1. `POST /auth/register` 2. `POST /auth/login` 3. `POST /auth/otp/request` 4. `POST /auth/otp/verify` 5. `POST /auth/forgot-password` - JSON body: - `identifier` (username OR phone OR email OR nid) - optional `redirect_to` URL (HTTPS or app deep-link scheme) - Backend always forwards a reset redirect URL to Supabase: - payload `redirect_to` if provided, otherwise - `PASSWORD_RESET_REDIRECT_URL` env, otherwise - `/auth/reset-password-page` 6. `POST /auth/reset-password` - JSON body: - `access_token` - `new_password` 7. `POST /auth/reset-password/resolve-token` - JSON body: - one of: `access_token`, `token_hash`, `code` - optional: `type` (defaults to `recovery`), `email` - Resolves Supabase recovery links that provide `token_hash`/`code` into a usable access token. 8. `GET /auth/reset-password-page` - Hosted reset page that reads token from the recovery link, submits to `/auth/reset-password`, then shows a success view and auto-opens the app deep link. 9. `GET /auth/reset-password-bridge` - Bridge page that opens mobile deep link reset flow (`ainelaql://auth/reset`) and provides browser fallback. ### User profile 1. `PUT /profile/update` - JSON body (any subset): - `first_name` - `last_name` - `full_name` - `phone` or `phone_number` - `email` - Updates profile metadata and mirrors auth metadata. - `full_name` is always normalized from `first_name + last_name` (legacy `full_name` input is still accepted and split into parts). ### Vehicles (multi-vehicle CRUD) 1. `POST /vehicles/add` 2. `GET /vehicles/my` - Optional query: `include_inactive=true|false` 3. `PUT /vehicles/{id}` 4. `DELETE /vehicles/{id}` 5. `POST /vehicles/verify` - OTP-backed ownership verification for a vehicle. ### Notifications 1. `POST /notifications/fcm-token` - Stores or updates FCM token for the authenticated user. 2. `GET /notifications/my` - Returns latest notification events for the authenticated user. - Notification events are server-generated (service role). - Authenticated users can only update their own `read_at` state; they cannot create, delete, or edit notification content. ### Health and diagnostics 1. `GET /` - Lightweight service entry endpoint. - Returns links to docs and health endpoints. 2. `GET /health` - Service health, inference provider wiring, and pricing config snapshot. 3. `GET /supabase/health` - Supabase readiness checks (tables, buckets, auth wiring). 4. `GET /models` - Inference provider details and local model info when local loading is enabled. ### Inference and session events 1. `POST /predict` - Input: `multipart/form-data` - Required: `image` - Optional: `event_type`, `parking_location`, `camera_source` - Auth: - Supabase user token (mobile/web/staff clients), or - barrier token (camera/barrier devices) - Returns AI output + pricing + gate decision + persistence metadata. 2. `POST /model/infer` - Input: `multipart/form-data` - Required: `image` - Intended for backend-to-backend model inference calls. - Requires `MODEL_SERVICE_ENABLE_LOCAL_ENDPOINT=true` in the model runtime. - If `MODEL_SERVICE_SHARED_SECRET` is configured, caller must send the configured header. ### Operations feeds 1. `GET /events/entered-cars` 2. `GET /events/leaving-cars-within-5-minutes` 3. `GET /events/left-cars` 4. `GET /events/inside-cars` 5. `GET /parking/history` Common optional query params: - `limit` - `for_user_id` (global-scope roles: `admin`, `security`, `barrier`) ### Location pricing and occupancy 1. `GET /parking/locations` - Returns pricing defaults + garage occupancy + per-location pricing/occupancy blocks. - Occupancy includes breakdown fields: - `inside_from_registered_sessions` - `inside_from_inferred_unmatched` 2. `GET /parking/occupancy` - Returns occupancy-focused response for dashboards. - Uses same occupancy breakdown fields under each location. ### Payments and gate flow 1. `POST /payments/paymob/create` 2. `POST /payments/paymob/webhook` 3. `POST /payments/manual/cash-confirm` 4. `POST /gate/decision` `POST /gate/decision` can be called by: - session owner - staff roles (`admin`, `security`) - `barrier` role token ### Maintenance 1. `POST /admin/maintenance/weekly-refresh` ## Key Response Blocks (Flutter-critical) From `/predict` and feed/history responses, consume: 1. `plate_info` and normalized `plate` sections 2. `app_registration` 3. `payment_status` 4. `pricing` 5. `gate_decision` 6. `left_within_5_minutes` 7. image fields under `user_page` and `admin_page` 8. Supabase persistence IDs/paths under `supabase` 9. `inference_provider` (`local` or `remote`) For `GET /events/inside-cars` and `GET /parking/history`, some items can include: 1. `inferred_unmatched=true` 2. `plate` object (`key`, `arabic`, `english`) 3. `event_count` These rows are inferred from unmatched OCR event streams (events that are not linked to a registered vehicle/session). ## Status and Error Behavior - `400`: validation/input formatting issues - `401`: missing/invalid auth token - `403`: role/scope violations - `404`: missing session/resource - `502/503`: upstream or integration failures (Supabase/Paymob/service config) ## Testing Minimum 1. `GET /health` 2. `GET /supabase/health` 3. `POST /predict` for entry 4. `POST /predict` for exit 5. `GET /parking/locations` 6. `GET /parking/occupancy`