Commit 3fe6c37b authored by Mahmoud Aglan's avatar Mahmoud Aglan

Add OpenAPI 3.1 documentation — full Mobile API spec (59 endpoints)

Complete OpenAPI 3.1.0 YAML specification covering all mobile API endpoints:
- 15 tags (Auth, Dashboard, Participants, Notifications, Shop, Payments, etc.)
- 10 reusable schemas (User, Participant, Invoice, Session, Attendance, etc.)
- Request/response bodies for every endpoint
- Error responses, validation errors, rate limit documentation
- Bearer token auth scheme documented
- 2401 lines of production-ready API docs
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 8e5171fa
openapi: 3.1.0
info:
title: El Captain Sports Management — Mobile API
version: '1.0'
description: |
RESTful API for the El Captain mobile app (Flutter).
Serves guardians/parents to track children's progress, pay invoices, receive notifications.
## Authentication
All protected endpoints require a Bearer token obtained via OTP verification.
Header: `Authorization: Bearer {token}`
## Money
All monetary values are integers representing **piasters** (1 EGP = 100 piasters).
Display-formatted values are provided alongside as `*_display` fields.
## Language
Arabic is the primary language. All `name_ar` fields are required; `name` (English) is optional.
## Rate Limits
- General: 60 requests/minute
- Auth: 10 requests/minute
- OTP: 3 requests/minute
- Payments: 5 requests/minute
contact:
name: El Captain Dev Team
email: dev@al-arcade.com
servers:
- url: https://el-captain.caprover.al-arcade.com/api/v1
description: Production
- url: http://localhost:8000/api/v1
description: Local development
tags:
- name: Health
description: System health and configuration
- name: Auth
description: OTP-based authentication
- name: Academy
description: Public academy content (no auth required)
- name: Dashboard
description: Single-call home screen
- name: Profile
description: User profile management
- name: Participants
description: Child data (schedule, attendance, invoices, enrollments)
- name: Notifications
description: In-app notifications and preferences
- name: Shop
description: Products and orders
- name: Payments
description: Online payment via Paymob
- name: Events
description: Academy events and registration
- name: ServiceRequests
description: Freeze/transfer/cancellation approval workflow
- name: Push
description: Push notification analytics and broadcast
- name: Devices
description: FCM device token management
- name: Messages
description: Guardian-academy messaging
security:
- BearerAuth: []
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: Sanctum Token
schemas:
Error:
type: object
properties:
error:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable Arabic message
required: [error, message]
ValidationError:
type: object
properties:
message:
type: string
errors:
type: object
additionalProperties:
type: array
items:
type: string
PaginationMeta:
type: object
properties:
current_page:
type: integer
last_page:
type: integer
per_page:
type: integer
total:
type: integer
User:
type: object
properties:
id:
type: integer
name_ar:
type: string
name:
type: string
nullable: true
email:
type: string
nullable: true
phone:
type: string
academy_id:
type: integer
status:
type: string
enum: [active, inactive, suspended, pending]
Participant:
type: object
properties:
uuid:
type: string
format: uuid
name_ar:
type: string
name:
type: string
nullable: true
photo_url:
type: string
nullable: true
status:
type: string
enum: [registered, active, frozen, suspended, inactive, graduated, transferred, withdrawn, blacklisted]
gender:
type: string
enum: [male, female]
date_of_birth:
type: string
format: date
nullable: true
active_enrollments:
type: array
items:
$ref: '#/components/schemas/Enrollment'
Session:
type: object
properties:
id:
type: integer
session_date:
type: string
format: date
start_time:
type: string
end_time:
type: string
status:
type: string
enum: [scheduled, in_progress, completed, cancelled, rescheduled]
group_name:
type: string
program_name:
type: string
nullable: true
facility_name:
type: string
nullable: true
Attendance:
type: object
properties:
id:
type: integer
date:
type: string
format: date
status:
type: string
enum: [expected, present, late, excused, absent, no_show, left_early, partial, cancelled, exempt]
check_in_time:
type: string
nullable: true
late_minutes:
type: integer
nullable: true
session:
$ref: '#/components/schemas/Session'
Invoice:
type: object
properties:
uuid:
type: string
format: uuid
number:
type: string
status:
type: string
enum: [draft, pending, sent, paid, partially_paid, overdue, cancelled, refunded]
total_amount:
type: integer
description: Total in piasters
due_amount:
type: integer
description: Remaining balance in piasters
due_date:
type: string
format: date
nullable: true
items:
type: array
items:
type: object
properties:
description:
type: string
quantity:
type: integer
unit_price:
type: integer
line_total:
type: integer
created_at:
type: string
format: date-time
Enrollment:
type: object
properties:
id:
type: integer
status:
type: string
enum: [pending, active, completed, cancelled, expired, waitlisted]
enrolled_at:
type: string
format: date
group:
type: object
properties:
id:
type: integer
name_ar:
type: string
program:
type: object
properties:
name_ar:
type: string
activity:
type: object
properties:
name_ar:
type: string
Notification:
type: object
properties:
id:
type: integer
event_type:
type: string
title:
type: string
body:
type: string
is_read:
type: boolean
read_at:
type: string
format: date-time
nullable: true
sent_at:
type: string
format: date-time
nullable: true
created_at:
type: string
format: date-time
metadata:
type: object
Announcement:
type: object
properties:
uuid:
type: string
format: uuid
title:
type: string
body:
type: string
target_type:
type: string
enum: [all, group, branch, program]
status:
type: string
enum: [pending, scheduled, sending, sent, failed]
sent_count:
type: integer
failed_count:
type: integer
scheduled_at:
type: string
format: date-time
nullable: true
sent_at:
type: string
format: date-time
nullable: true
created_at:
type: string
format: date-time
responses:
Unauthorized:
description: Missing or invalid authentication token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: unauthenticated
message: غير مصرح
Forbidden:
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: forbidden
message: غير مصرح لك بالوصول لهذا المشترك
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ValidationFailed:
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
TooManyRequests:
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: too_many_attempts
message: يرجى الانتظار قبل المحاولة مرة أخرى
paths:
/health:
get:
tags: [Health]
summary: Health check
security: []
responses:
'200':
description: API is healthy
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: ok
version:
type: string
example: '1.0'
timestamp:
type: string
format: date-time
/app/config:
get:
tags: [Health]
summary: App configuration (theme, features, maintenance)
security: []
responses:
'200':
description: Configuration for the mobile app
content:
application/json:
schema:
type: object
properties:
academy:
type: object
properties:
name:
type: string
name_ar:
type: string
logo_url:
type: string
nullable: true
phone:
type: string
email:
type: string
theme:
type: object
properties:
primary_color:
type: string
example: '#1e40af'
accent_color:
type: string
example: '#f59e0b'
features:
type: object
properties:
shop:
type: boolean
events:
type: boolean
chat:
type: boolean
online_payment:
type: boolean
app:
type: object
properties:
min_version:
type: string
example: '1.0.0'
maintenance_mode:
type: boolean
maintenance_message:
type: string
'404':
$ref: '#/components/responses/NotFound'
/branches:
get:
tags: [Academy]
summary: List academy branches (for branch locator)
security: []
responses:
'200':
description: Active branches
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
name_ar:
type: string
name:
type: string
nullable: true
address:
type: string
nullable: true
phone:
type: string
nullable: true
latitude:
type: number
nullable: true
longitude:
type: number
nullable: true
operating_hours:
type: object
nullable: true
/auth/otp/request:
post:
tags: [Auth]
summary: Request OTP code via SMS
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [phone]
properties:
phone:
type: string
description: Egyptian phone number
example: '+201012345678'
responses:
'200':
description: OTP sent successfully
content:
application/json:
schema:
type: object
properties:
sent:
type: boolean
mode:
type: string
enum: [demo, sms]
expires_in:
type: integer
description: Seconds until OTP expires
example: 300
'404':
description: Phone not registered
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: phone_not_found
message: هذا الرقم غير مسجل في النظام
'422':
$ref: '#/components/responses/ValidationFailed'
'429':
$ref: '#/components/responses/TooManyRequests'
/auth/otp/verify:
post:
tags: [Auth]
summary: Verify OTP and get auth token
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [phone, otp]
properties:
phone:
type: string
example: '+201012345678'
otp:
type: string
minLength: 6
maxLength: 6
example: '123456'
responses:
'200':
description: Authentication successful
content:
application/json:
schema:
type: object
properties:
token:
type: string
description: Bearer token for subsequent requests
user:
$ref: '#/components/schemas/User'
participants:
type: array
items:
$ref: '#/components/schemas/Participant'
'401':
description: Invalid OTP
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: invalid_otp
message: رمز التحقق غير صحيح
'404':
$ref: '#/components/responses/NotFound'
/auth/logout:
post:
tags: [Auth]
summary: Logout and revoke token
responses:
'200':
description: Logged out
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: تم تسجيل الخروج بنجاح
/auth/me:
get:
tags: [Auth]
summary: Get current user and linked participants
responses:
'200':
description: Current user data
content:
application/json:
schema:
type: object
properties:
user:
$ref: '#/components/schemas/User'
participants:
type: array
items:
$ref: '#/components/schemas/Participant'
/academy/news:
get:
tags: [Academy]
summary: Published news articles
security: []
responses:
'200':
description: Paginated news
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
title:
type: string
excerpt:
type: string
nullable: true
category:
type: string
nullable: true
image_url:
type: string
nullable: true
published_at:
type: string
format: date-time
is_featured:
type: boolean
meta:
$ref: '#/components/schemas/PaginationMeta'
/academy/news/{uuid}:
get:
tags: [Academy]
summary: Single news article
security: []
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Full article
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: integer
uuid:
type: string
title:
type: string
body:
type: string
category:
type: string
image_url:
type: string
nullable: true
published_at:
type: string
format: date-time
'404':
$ref: '#/components/responses/NotFound'
/academy/programs:
get:
tags: [Academy]
summary: Active training programs
security: []
responses:
'200':
description: Program list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
name_ar:
type: string
name:
type: string
nullable: true
description_ar:
type: string
nullable: true
activity:
type: object
properties:
id:
type: integer
name_ar:
type: string
category:
type: string
age_min:
type: integer
nullable: true
age_max:
type: integer
nullable: true
gender:
type: string
nullable: true
enum: [male, female, null]
/academy/events:
get:
tags: [Academy]
summary: Upcoming published events
security: []
responses:
'200':
description: Paginated events
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
title:
type: string
description:
type: string
nullable: true
type:
type: string
starts_at:
type: string
format: date-time
ends_at:
type: string
format: date-time
nullable: true
location_name:
type: string
nullable: true
cover_url:
type: string
nullable: true
max_capacity:
type: integer
nullable: true
registrations_count:
type: integer
is_registration_open:
type: boolean
spots_remaining:
type: integer
nullable: true
meta:
$ref: '#/components/schemas/PaginationMeta'
/academy/events/{uuid}:
get:
tags: [Academy]
summary: Event detail
security: []
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Full event detail
'404':
$ref: '#/components/responses/NotFound'
/dashboard:
get:
tags: [Dashboard]
summary: Single-call home screen data
description: Returns all children summaries, today's sessions, totals, and announcements in one call.
responses:
'200':
description: Dashboard data
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
children:
type: array
items:
type: object
properties:
uuid:
type: string
name_ar:
type: string
photo_url:
type: string
nullable: true
status:
type: string
outstanding_balance:
type: integer
outstanding_display:
type: string
next_session:
type: object
nullable: true
properties:
date:
type: string
format: date
start_time:
type: string
group_name:
type: string
totals:
type: object
properties:
outstanding_balance:
type: integer
outstanding_display:
type: string
children_count:
type: integer
today_sessions:
type: integer
unread_messages:
type: integer
unread_notifications:
type: integer
recent_evaluations:
type: integer
today_sessions:
type: array
items:
$ref: '#/components/schemas/Session'
announcement:
type: object
nullable: true
properties:
text:
type: string
link:
type: string
nullable: true
type:
type: string
/profile:
get:
tags: [Profile]
summary: Get user profile
responses:
'200':
description: Profile data
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
name_ar:
type: string
name:
type: string
nullable: true
email:
type: string
nullable: true
phone:
type: string
phone_secondary:
type: string
nullable: true
address:
type: string
nullable: true
city:
type: string
nullable: true
emergency_contact_name:
type: string
nullable: true
emergency_contact_phone:
type: string
nullable: true
medical_notes:
type: string
nullable: true
photo_url:
type: string
nullable: true
patch:
tags: [Profile]
summary: Update profile fields
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
phone_secondary:
type: string
address:
type: string
city:
type: string
emergency_contact_name:
type: string
emergency_contact_phone:
type: string
medical_notes:
type: string
responses:
'200':
description: Updated
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
'422':
$ref: '#/components/responses/ValidationFailed'
/profile/photo:
post:
tags: [Profile]
summary: Upload profile or participant photo
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [photo]
properties:
photo:
type: string
format: binary
description: JPEG or PNG, max 5MB
type:
type: string
enum: [profile, participant]
default: profile
participant_uuid:
type: string
description: Required when type=participant
responses:
'200':
description: Photo uploaded
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
photo_url:
type: string
'422':
$ref: '#/components/responses/ValidationFailed'
/devices/register:
post:
tags: [Devices]
summary: Register FCM device token
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [token, platform]
properties:
token:
type: string
description: FCM device token
platform:
type: string
enum: [android, ios]
device_name:
type: string
app_version:
type: string
responses:
'200':
description: Registered
content:
application/json:
schema:
type: object
properties:
registered:
type: boolean
/devices/refresh:
patch:
tags: [Devices]
summary: Refresh expired FCM token
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [old_token, new_token]
properties:
old_token:
type: string
new_token:
type: string
responses:
'200':
description: Refreshed
content:
application/json:
schema:
type: object
properties:
refreshed:
type: boolean
'404':
$ref: '#/components/responses/NotFound'
/devices/{token}:
delete:
tags: [Devices]
summary: Unregister device token (on logout)
parameters:
- name: token
in: path
required: true
schema:
type: string
responses:
'200':
description: Deleted
content:
application/json:
schema:
type: object
properties:
deleted:
type: boolean
/guardian/children:
get:
tags: [Participants]
summary: List all linked participants (children)
responses:
'200':
description: Participant list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Participant'
/participants/{uuid}:
get:
tags: [Participants]
summary: Participant full profile
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Participant data
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Participant'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/participants/{uuid}/summary:
get:
tags: [Participants]
summary: Quick stats summary
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Summary stats
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
participant_uuid:
type: string
name_ar:
type: string
photo_url:
type: string
nullable: true
status:
type: string
active_enrollments:
type: integer
attendance_rate:
type: number
format: float
outstanding_balance:
type: integer
next_session:
$ref: '#/components/schemas/Session'
/participants/{uuid}/schedule:
get:
tags: [Participants]
summary: Upcoming sessions (next 7 days)
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Session list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Session'
/participants/{uuid}/attendance:
get:
tags: [Participants]
summary: Attendance history with rate
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Attendance records
content:
application/json:
schema:
type: object
properties:
rate:
type: number
format: float
description: Attendance rate percentage
data:
type: array
items:
$ref: '#/components/schemas/Attendance'
meta:
$ref: '#/components/schemas/PaginationMeta'
/participants/{uuid}/invoices:
get:
tags: [Participants]
summary: Invoice history
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Paginated invoices
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Invoice'
meta:
$ref: '#/components/schemas/PaginationMeta'
/participants/{uuid}/enrollments:
get:
tags: [Participants]
summary: Active enrollments with group/program details
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Enrollment list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Enrollment'
/participants/{uuid}/documents:
get:
tags: [Participants]
summary: Documents with expiry summary
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Documents
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
title:
type: string
type:
type: string
file_url:
type: string
expires_at:
type: string
format: date
nullable: true
status:
type: string
enum: [valid, expiring_soon, expired]
expiry_summary:
type: object
properties:
expired:
type: integer
expiring_soon:
type: integer
valid:
type: integer
/participants/{uuid}/wallet:
get:
tags: [Participants]
summary: Wallet balance
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Wallet data
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
balance:
type: integer
available_balance:
type: integer
frozen_amount:
type: integer
status:
type: string
display:
type: string
/participants/{uuid}/wallet/transactions:
get:
tags: [Participants]
summary: Wallet transaction history
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Paginated transactions
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
type:
type: string
amount:
type: integer
description:
type: string
created_at:
type: string
format: date-time
meta:
$ref: '#/components/schemas/PaginationMeta'
/participants/{uuid}/installments:
get:
tags: [Participants]
summary: Payment plans and installments
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Plans with installment breakdown
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
plan_id:
type: integer
total_amount:
type: integer
paid_amount:
type: integer
remaining:
type: integer
installments:
type: array
items:
type: object
properties:
id:
type: integer
amount:
type: integer
due_date:
type: string
format: date
status:
type: string
paid_at:
type: string
format: date-time
nullable: true
/participants/{uuid}/evaluations:
get:
tags: [Participants]
summary: Shared evaluations list
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Evaluation list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
title:
type: string
type:
type: string
shared_at:
type: string
format: date-time
overall_score:
type: number
/participants/{uuid}/evaluations/{evaluationUuid}:
get:
tags: [Participants]
summary: Full evaluation with criteria scores
parameters:
- name: uuid
in: path
required: true
schema:
type: string
- name: evaluationUuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Evaluation detail
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: integer
uuid:
type: string
title:
type: string
type:
type: string
period:
type: string
nullable: true
shared_at:
type: string
format: date-time
overall_score:
type: number
criteria:
type: array
items:
type: object
properties:
name:
type: string
score:
type: number
max_score:
type: number
percentage:
type: number
notes:
type: string
nullable: true
notes:
type: string
nullable: true
recommendations:
type: string
nullable: true
/notifications:
get:
tags: [Notifications]
summary: Notification inbox
responses:
'200':
description: Paginated notifications with unread count
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Notification'
unread_count:
type: integer
meta:
$ref: '#/components/schemas/PaginationMeta'
/notifications/{id}/read:
patch:
tags: [Notifications]
summary: Mark single notification as read
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Marked
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
/notifications/read-all:
post:
tags: [Notifications]
summary: Mark all notifications as read
responses:
'200':
description: All marked
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
/notifications/preferences:
get:
tags: [Notifications]
summary: Get notification channel preferences
responses:
'200':
description: Preferences
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
event_type:
type: string
channel_email:
type: boolean
channel_sms:
type: boolean
channel_push:
type: boolean
digest_mode:
type: boolean
post:
tags: [Notifications]
summary: Update notification preferences
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [preferences]
properties:
preferences:
type: array
items:
type: object
required: [event_type]
properties:
event_type:
type: string
channel_push:
type: boolean
channel_email:
type: boolean
channel_sms:
type: boolean
responses:
'200':
description: Updated
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
/products:
get:
tags: [Shop]
summary: Available products
responses:
'200':
description: Product list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
name_ar:
type: string
name:
type: string
nullable: true
description_ar:
type: string
nullable: true
price:
type: integer
description: Price in piasters
image_url:
type: string
nullable: true
in_stock:
type: boolean
category:
type: string
nullable: true
/orders/create:
post:
tags: [Shop]
summary: Purchase a product
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [participant_uuid, product_id, payment_method]
properties:
participant_uuid:
type: string
product_id:
type: integer
quantity:
type: integer
default: 1
payment_method:
type: string
enum: [wallet, online]
notes:
type: string
responses:
'200':
description: Order created
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
order:
type: object
payment_url:
type: string
nullable: true
description: Present when payment_method=online
'422':
$ref: '#/components/responses/ValidationFailed'
/orders:
get:
tags: [Shop]
summary: Order history
responses:
'200':
description: Paginated orders
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
uuid:
type: string
product:
type: object
quantity:
type: integer
total:
type: integer
status:
type: string
created_at:
type: string
format: date-time
meta:
$ref: '#/components/schemas/PaginationMeta'
/payments/initiate:
post:
tags: [Payments]
summary: Initiate online payment for invoice
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [invoice_uuid]
properties:
invoice_uuid:
type: string
format: uuid
responses:
'200':
description: Payment initiated
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
payment_url:
type: string
description: Paymob iframe URL
payment_uuid:
type: string
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationFailed'
'503':
description: Payment gateway not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/payments/callback:
post:
tags: [Payments]
summary: Paymob webhook callback
description: Server-to-server callback from Paymob. Do not call from mobile app.
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: Processed
content:
application/json:
schema:
type: object
properties:
processed:
type: boolean
/invoices/{uuid}:
get:
tags: [Payments]
summary: Invoice detail with items and payments
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Full invoice
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Invoice'
'404':
$ref: '#/components/responses/NotFound'
/payments/{uuid}/receipt:
get:
tags: [Payments]
summary: Payment receipt
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Receipt data
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
payment_uuid:
type: string
amount:
type: integer
method:
type: string
reference:
type: string
nullable: true
paid_at:
type: string
format: date-time
invoice:
$ref: '#/components/schemas/Invoice'
/events/{uuid}/register:
post:
tags: [Events]
summary: Register for an event
parameters:
- name: uuid
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [participant_uuid]
properties:
participant_uuid:
type: string
notes:
type: string
responses:
'200':
description: Registered
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
registration:
type: object
'422':
$ref: '#/components/responses/ValidationFailed'
/events/my-registrations:
get:
tags: [Events]
summary: My event registrations
responses:
'200':
description: Registration list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
event:
type: object
participant:
type: object
status:
type: string
registered_at:
type: string
format: date-time
/service-requests:
post:
tags: [ServiceRequests]
summary: Submit a service request (freeze, transfer, etc.)
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [participant_uuid, type, reason]
properties:
participant_uuid:
type: string
type:
type: string
enum: [freeze, unfreeze, transfer, cancellation, other]
reason:
type: string
minLength: 10
metadata:
type: object
description: Extra details (e.g. transfer destination)
responses:
'201':
description: Request submitted
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
request:
type: object
properties:
uuid:
type: string
status:
type: string
type:
type: string
'409':
description: Duplicate pending request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
$ref: '#/components/responses/ValidationFailed'
get:
tags: [ServiceRequests]
summary: List my service requests
responses:
'200':
description: Request list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
uuid:
type: string
type:
type: string
status:
type: string
enum: [pending, approved, rejected, cancelled]
reason:
type: string
admin_notes:
type: string
nullable: true
created_at:
type: string
format: date-time
handled_at:
type: string
format: date-time
nullable: true
/service-requests/{uuid}/cancel:
post:
tags: [ServiceRequests]
summary: Cancel a pending service request
parameters:
- name: uuid
in: path
required: true
schema:
type: string
responses:
'200':
description: Cancelled
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
'422':
description: Cannot cancel (not pending)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/absences/report:
post:
tags: [Participants]
summary: Pre-report upcoming absence
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [participant_uuid, session_id, reason]
properties:
participant_uuid:
type: string
session_id:
type: integer
reason:
type: string
responses:
'200':
description: Reported
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
'422':
$ref: '#/components/responses/ValidationFailed'
/messages/send:
post:
tags: [Messages]
summary: Send message to academy
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [subject, body]
properties:
subject:
type: string
body:
type: string
category:
type: string
responses:
'201':
description: Sent
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: object
properties:
id:
type: integer
'422':
$ref: '#/components/responses/ValidationFailed'
/messages:
get:
tags: [Messages]
summary: Message history
responses:
'200':
description: Paginated messages
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: integer
subject:
type: string
body:
type: string
reply:
type: string
nullable: true
is_read:
type: boolean
created_at:
type: string
format: date-time
meta:
$ref: '#/components/schemas/PaginationMeta'
/push/track:
post:
tags: [Push]
summary: Track push notification delivery/interaction
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [events]
properties:
events:
type: array
minItems: 1
maxItems: 50
items:
type: object
required: [event_type, action]
properties:
notification_id:
type: string
event_type:
type: string
action:
type: string
enum: [delivered, opened, dismissed, action_clicked]
metadata:
type: object
responses:
'200':
description: Tracked
content:
application/json:
schema:
type: object
properties:
tracked:
type: integer
/push/badge:
get:
tags: [Push]
summary: Get unread notification badge count
responses:
'200':
description: Badge count
content:
application/json:
schema:
type: object
properties:
badge_count:
type: integer
/push/heartbeat:
post:
tags: [Push]
summary: Report device activity (keeps token fresh)
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [token]
properties:
token:
type: string
description: FCM device token
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
/broadcast/send:
post:
tags: [Push]
summary: Send push announcement (admin only)
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title, body, target_type]
properties:
title:
type: string
maxLength: 200
body:
type: string
maxLength: 1000
target_type:
type: string
enum: [all, group, branch, program]
target_ids:
type: array
items:
type: integer
description: Required unless target_type=all
push_data:
type: object
scheduled_at:
type: string
format: date-time
description: Schedule for future delivery
responses:
'200':
description: Sent immediately
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
announcement:
$ref: '#/components/schemas/Announcement'
'201':
description: Scheduled
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
announcement:
$ref: '#/components/schemas/Announcement'
'422':
$ref: '#/components/responses/ValidationFailed'
/broadcast/history:
get:
tags: [Push]
summary: Broadcast announcement history
responses:
'200':
description: Paginated announcements
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Announcement'
meta:
$ref: '#/components/schemas/PaginationMeta'
/deeplinks/routes:
get:
tags: [Push]
summary: Deep-link routing map for push notifications
description: |
Returns route templates used by the mobile app to navigate to the correct screen
when a push notification is tapped. Template variables (e.g. `{participant_uuid}`)
are replaced with values from the push payload `data` object.
responses:
'200':
description: Route map
content:
application/json:
schema:
type: object
properties:
routes:
type: object
additionalProperties:
type: string
example:
enrollment: /participants/{participant_uuid}/enrollments
invoice: /participants/{participant_uuid}/invoices/{invoice_uuid}
attendance: /participants/{participant_uuid}/attendance
session_cancelled: /participants/{participant_uuid}/schedule
service_request_resolved: /service-requests
announcement: /notifications
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment