Files
ljwx-children/openapi-left-behind-children.yaml
brunoandClaude Sonnet 4.5 9b7a0f6ec2 test: add comprehensive risk assessments API test suite (Issue #37)
Created complete test coverage for risk assessment endpoints:
- 25 test cases covering all 3 endpoints
- POST /risk-assessments (11 tests)
- GET /risk-assessments (5 tests)
- GET /risk-assessments/{id} (5 tests)
- Edge cases and error handling (4 tests)

Test features:
✅ Access control (guardian, psychologist, administrator)
✅ Ollama integration (mocked with AsyncMock)
✅ Fallback mechanisms
✅ Pagination and filtering
✅ Error handling and edge cases
✅ Data validation

Dependencies and fixes:
- Updated httpx (0.26.0 → 0.27.2) for pytest-httpx compatibility
- Fixed JWT imports (import jwt → from jose import jwt)
- Fixed Pydantic v2 field_validator syntax
- Fixed model import conflicts (removed duplicate User model)
- Updated backend/models/__init__.py to import left_behind_children models
- Added missing auth exports (blacklist_token, is_token_blacklisted, can_access_risk_assessment)

Known issue (⚠️ BLOCKING):
- SQLite UUID type incompatibility preventing tests from running
- Error: SQLiteTypeCompiler can't render UUID type
- Need to implement UUID-to-String adapter for SQLite in tests
- All 25 tests fail at setup phase

Files created/modified:
- tests/unit/test_api_risk_assessments.py (NEW - 700+ lines)
- requirements.txt (updated httpx, commented safety)
- backend/auth/__init__.py (added exports)
- backend/auth/utils.py (fixed JWT import)
- backend/auth/dependencies.py (fixed JWT import)
- backend/api/data.py (fixed Pydantic validator)
- backend/models/__init__.py (switched to left_behind_children models)

Next steps:
1. Fix UUID/SQLite compatibility (use String(36) or UUID adapter)
2. Run tests successfully
3. Achieve >95% coverage target

Progress: Issue #37 - 70% complete (tests written, need execution)

Related: #38, #39, #40, #41, #42

🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2026-01-01 14:23:55 +08:00

1500 lines
40 KiB
YAML

openapi: 3.0.3
info:
title: Left-behind Children Psychological Risk Detection Platform API
version: 1.0.0
description: |
API for early detection and prevention of psychological risks in left-behind children.
**Key Features:**
- Multi-modal data collection (voice, text, behavioral)
- AI-powered risk assessment (90%+ accuracy)
- Resource library (20,000+ materials)
- Communication & collaboration tools
- Role-based access control (6 roles)
**Security:** All endpoints require authentication unless marked as public.
All PII is encrypted (AES-256 at rest, TLS 1.3 in transit).
**Rate Limiting:** 1000 requests/hour per user, 10000 requests/hour per organization.
**Support:** Technical support available 24/7 via crisis hotline integration.
contact:
name: Platform API Support
email: [email protected]
url: https://left-behind-children.org/api-docs
license:
name: Proprietary
url: https://left-behind-children.org/license
servers:
- url: https://api.left-behind-children.org/v1
description: Production server
- url: https://api-staging.left-behind-children.org/v1
description: Staging server
- url: http://localhost:8000/v1
description: Local development server
tags:
- name: Authentication
description: User authentication and authorization
- name: Users
description: User management (children, guardians, psychologists, etc.)
- name: Risk Assessment
description: Psychological risk scoring and early warnings
- name: Data Collection
description: Multi-modal data ingestion (voice, text, behavioral)
- name: Resources
description: Intervention resource library
- name: Communication
description: Chat, video calls, consultations
- name: Analytics
description: Dashboards and reports
- name: Health
description: System health and monitoring
security:
- BearerAuth: []
paths:
# ============================================
# HEALTH & MONITORING
# ============================================
/health:
get:
tags:
- Health
summary: Health check endpoint
description: Returns system health status (CPU, memory, database, dependencies)
operationId: getHealth
security: [] # Public endpoint
responses:
'200':
description: System is healthy
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
example:
status: healthy
timestamp: "2025-12-31T12:00:00Z"
checks:
database: healthy
redis: healthy
speech_api: healthy
nlp_api: healthy
'503':
description: System is unhealthy
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
/health/ready:
get:
tags:
- Health
summary: Readiness check
description: Check if system is ready to accept traffic
operationId: getReadiness
security: []
responses:
'200':
description: System is ready
content:
application/json:
schema:
$ref: '#/components/schemas/ReadinessResponse'
'503':
description: System is not ready
/metrics:
get:
tags:
- Health
summary: Prometheus metrics
description: Returns Prometheus-compatible metrics
operationId: getMetrics
security: []
responses:
'200':
description: Metrics in Prometheus format
content:
text/plain:
example: |
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",endpoint="/health",status="200"} 1234
# ============================================
# AUTHENTICATION
# ============================================
/auth/register:
post:
tags:
- Authentication
summary: Register new user
description: |
Register a new user account.
- Children under 14 require parental consent (consent_token)
- Phone number verification via SMS OTP
operationId: registerUser
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserRegistration'
example:
phone: "+8613800138000"
password: "SecurePassword123!"
role: child
name: "小明"
age: 12
consent_token: "parent-consent-abc123"
responses:
'201':
description: User registered successfully
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: Phone number already registered
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/auth/login:
post:
tags:
- Authentication
summary: User login
description: Authenticate user and return JWT token (7-day validity)
operationId: loginUser
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
example:
phone: "+8613800138000"
password: "SecurePassword123!"
responses:
'200':
description: Login successful
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
example:
access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
token_type: "bearer"
expires_in: 604800
user:
id: "user-123"
phone: "+8613800138000"
name: "小明"
role: child
age: 12
created_at: "2025-01-01T00:00:00Z"
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/auth/logout:
post:
tags:
- Authentication
summary: User logout
description: Invalidate JWT token
operationId: logoutUser
responses:
'204':
description: Logout successful
'401':
$ref: '#/components/responses/Unauthorized'
/auth/refresh:
post:
tags:
- Authentication
summary: Refresh access token
description: Get a new access token using refresh token
operationId: refreshToken
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
refresh_token:
type: string
required:
- refresh_token
responses:
'200':
description: Token refreshed
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
'401':
$ref: '#/components/responses/Unauthorized'
# ============================================
# USER MANAGEMENT
# ============================================
/users/me:
get:
tags:
- Users
summary: Get current user profile
description: Retrieve authenticated user's profile
operationId: getCurrentUser
responses:
'200':
description: User profile retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'401':
$ref: '#/components/responses/Unauthorized'
patch:
tags:
- Users
summary: Update current user profile
description: Update authenticated user's profile (partial update)
operationId: updateCurrentUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserUpdateRequest'
responses:
'200':
description: User profile updated
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/users/{user_id}:
get:
tags:
- Users
summary: Get user by ID
description: |
Retrieve user profile by ID.
Access control:
- Child: Can only view own profile
- Guardian/Parent: Can view assigned children
- Psychologist: Can view assigned cases
- Administrator: Can view all users
operationId: getUserById
parameters:
- name: user_id
in: path
required: true
schema:
type: string
description: User ID (UUID)
responses:
'200':
description: User profile retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
# ============================================
# RISK ASSESSMENT
# ============================================
/risk-assessments:
post:
tags:
- Risk Assessment
summary: Create risk assessment
description: |
Trigger risk assessment for a user based on collected data.
- Real-time assessment: <500ms latency
- Returns risk score (0-100) and category (Low/Medium/High/Critical)
- Critical alerts (76-100) trigger automatic notifications
operationId: createRiskAssessment
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RiskAssessmentRequest'
example:
user_id: "child-123"
assessment_type: comprehensive
data_sources:
- voice_analysis_id: "voice-456"
- text_analysis_id: "text-789"
- behavioral_data_id: "behavior-012"
responses:
'201':
description: Risk assessment created
content:
application/json:
schema:
$ref: '#/components/schemas/RiskAssessmentResponse'
example:
id: "assessment-abc123"
user_id: "child-123"
risk_score: 45
risk_category: medium
risk_factors:
- category: anxiety
severity: moderate
confidence: 0.87
- category: academic_stress
severity: high
confidence: 0.92
recommendations:
- resource_id: "resource-001"
title: "应对焦虑的呼吸练习"
type: video
alerts_triggered: []
created_at: "2025-12-31T12:00:00Z"
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalServerError'
get:
tags:
- Risk Assessment
summary: List risk assessments
description: |
Retrieve risk assessments with pagination and filtering.
Access control applies (users can only see their own or assigned cases).
operationId: listRiskAssessments
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PageSizeParam'
- name: user_id
in: query
schema:
type: string
description: Filter by user ID
- name: risk_category
in: query
schema:
type: string
enum: [low, medium, high, critical]
description: Filter by risk category
- name: start_date
in: query
schema:
type: string
format: date
description: Filter assessments after this date
responses:
'200':
description: List of risk assessments
content:
application/json:
schema:
$ref: '#/components/schemas/RiskAssessmentList'
'400':
$ref: '#/components/responses/BadRequest'
/risk-assessments/{assessment_id}:
get:
tags:
- Risk Assessment
summary: Get risk assessment by ID
description: Retrieve detailed risk assessment by ID
operationId: getRiskAssessmentById
parameters:
- name: assessment_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Risk assessment retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/RiskAssessmentResponse'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
# ============================================
# DATA COLLECTION
# ============================================
/data/voice:
post:
tags:
- Data Collection
summary: Upload voice data
description: |
Upload voice recording for analysis.
- Supports: MP3, WAV, M4A (max 10MB)
- Processes: Emotion detection, speech rate, dialect recognition
- Returns: voice_analysis_id for use in risk assessment
operationId: uploadVoiceData
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
user_id:
type: string
description: User ID
audio_file:
type: string
format: binary
description: Audio file (MP3, WAV, M4A)
metadata:
type: object
properties:
duration_seconds:
type: integer
context:
type: string
description: Context (e.g., "phone_call", "voice_message")
required:
- user_id
- audio_file
responses:
'201':
description: Voice data uploaded
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceAnalysisResponse'
example:
id: "voice-abc123"
user_id: "child-123"
status: processing
estimated_completion: "2025-12-31T12:01:00Z"
'400':
$ref: '#/components/responses/BadRequest'
'413':
description: File too large (max 10MB)
/data/text:
post:
tags:
- Data Collection
summary: Submit text data
description: |
Submit text for sentiment and emotion analysis.
- Supports: Simplified Chinese, Traditional Chinese
- Processes: Sentiment, emotion, risk keywords
- Real-time processing: <200ms
operationId: submitTextData
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TextDataRequest'
example:
user_id: "child-123"
text: "今天心情不太好,感觉压力很大..."
context: diary_entry
timestamp: "2025-12-31T12:00:00Z"
responses:
'201':
description: Text analyzed
content:
application/json:
schema:
$ref: '#/components/schemas/TextAnalysisResponse'
example:
id: "text-abc123"
user_id: "child-123"
sentiment: negative
sentiment_score: -0.65
emotions:
- emotion: sadness
confidence: 0.78
- emotion: stress
confidence: 0.85
risk_keywords:
- keyword: "压力"
category: academic_stress
created_at: "2025-12-31T12:00:00Z"
'400':
$ref: '#/components/responses/BadRequest'
# ============================================
# RESOURCES
# ============================================
/resources:
get:
tags:
- Resources
summary: List intervention resources
description: |
Browse resource library with filtering and pagination.
- 20,000+ resources (videos, audio, articles, tools)
- Personalized recommendations based on risk profile
operationId: listResources
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PageSizeParam'
- name: category
in: query
schema:
type: string
enum: [depression, anxiety, self_harm, social_withdrawal, academic_stress, family_conflict]
description: Filter by risk category
- name: resource_type
in: query
schema:
type: string
enum: [video, audio, article, interactive_tool]
description: Filter by resource type
- name: age_group
in: query
schema:
type: string
enum: [elementary, middle_school, high_school]
description: Filter by age appropriateness
- name: recommended
in: query
schema:
type: boolean
description: Only show personalized recommendations
responses:
'200':
description: List of resources
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceList'
'400':
$ref: '#/components/responses/BadRequest'
/resources/{resource_id}:
get:
tags:
- Resources
summary: Get resource by ID
description: Retrieve detailed resource information
operationId: getResourceById
parameters:
- name: resource_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Resource retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceResponse'
'404':
$ref: '#/components/responses/NotFound'
/resources/{resource_id}/track-usage:
post:
tags:
- Resources
summary: Track resource usage
description: Record that user accessed a resource (for analytics and recommendations)
operationId: trackResourceUsage
parameters:
- name: resource_id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
action:
type: string
enum: [viewed, completed, liked, shared]
duration_seconds:
type: integer
description: Time spent (for videos)
responses:
'204':
description: Usage tracked
'404':
$ref: '#/components/responses/NotFound'
# ============================================
# COMMUNICATION
# ============================================
/conversations:
post:
tags:
- Communication
summary: Start a conversation
description: |
Create a new conversation (1-on-1 or group).
Participants can be: child, parent, guardian, psychologist.
operationId: createConversation
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationCreateRequest'
responses:
'201':
description: Conversation created
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationResponse'
'400':
$ref: '#/components/responses/BadRequest'
get:
tags:
- Communication
summary: List conversations
description: Get list of conversations for current user
operationId: listConversations
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PageSizeParam'
responses:
'200':
description: List of conversations
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationList'
/conversations/{conversation_id}/messages:
post:
tags:
- Communication
summary: Send message
description: Send a text message in a conversation
operationId: sendMessage
parameters:
- name: conversation_id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MessageRequest'
responses:
'201':
description: Message sent
content:
application/json:
schema:
$ref: '#/components/schemas/MessageResponse'
'403':
$ref: '#/components/responses/Forbidden'
get:
tags:
- Communication
summary: Get messages
description: Retrieve messages in a conversation with pagination
operationId: getMessages
parameters:
- name: conversation_id
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PageSizeParam'
responses:
'200':
description: Messages retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/MessageList'
/consultations:
post:
tags:
- Communication
summary: Book consultation
description: Schedule a counseling session with a psychologist
operationId: bookConsultation
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ConsultationRequest'
responses:
'201':
description: Consultation booked
content:
application/json:
schema:
$ref: '#/components/schemas/ConsultationResponse'
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: Time slot not available
# ============================================
# ANALYTICS
# ============================================
/analytics/dashboard:
get:
tags:
- Analytics
summary: Get dashboard data
description: |
Retrieve dashboard data based on user role.
- Child: Personal mood trends
- Guardian/Parent: Child's risk trends
- Teacher: Class-level statistics
- Psychologist: Case load summary
- Administrator: Platform-wide KPIs
operationId: getDashboard
parameters:
- name: time_range
in: query
schema:
type: string
enum: [7days, 30days, 90days, 1year]
description: Time range for analytics
responses:
'200':
description: Dashboard data
content:
application/json:
schema:
$ref: '#/components/schemas/DashboardResponse'
'403':
$ref: '#/components/responses/Forbidden'
# ============================================
# COMPONENTS
# ============================================
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT token obtained from /auth/login endpoint
parameters:
PageParam:
name: page
in: query
schema:
type: integer
minimum: 1
default: 1
description: Page number
PageSizeParam:
name: page_size
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: Items per page
schemas:
# Common Schemas
ErrorResponse:
type: object
required:
- error
- message
- trace_id
properties:
error:
type: string
description: Error code
message:
type: string
description: Human-readable error message
trace_id:
type: string
description: OpenTelemetry trace ID for debugging
details:
type: object
description: Additional error details
example:
error: "VALIDATION_ERROR"
message: "Phone number format is invalid"
trace_id: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
details:
field: "phone"
constraint: "E.164 format required"
HealthResponse:
type: object
required:
- status
- timestamp
properties:
status:
type: string
enum: [healthy, degraded, unhealthy]
timestamp:
type: string
format: date-time
trace_id:
type: string
description: OpenTelemetry trace ID for debugging (present in unhealthy responses)
checks:
type: object
additionalProperties:
type: string
enum: [healthy, unhealthy]
ReadinessResponse:
type: object
required:
- ready
properties:
ready:
type: boolean
services:
type: object
additionalProperties:
type: boolean
# User Schemas
UserRegistration:
type: object
required:
- phone
- password
- role
- name
- age
properties:
phone:
type: string
description: Phone number in E.164 format
example: "+8613800138000"
password:
type: string
format: password
minLength: 8
description: Password (min 8 chars, must include uppercase, lowercase, number)
role:
type: string
enum: [child, guardian, parent, teacher, psychologist, administrator]
name:
type: string
description: Full name
age:
type: integer
minimum: 1
maximum: 18
description: Age (for children)
consent_token:
type: string
description: Parental consent token (required for age <14)
UserResponse:
type: object
required:
- id
- phone
- role
- name
- created_at
properties:
id:
type: string
description: User UUID
phone:
type: string
role:
type: string
enum: [child, guardian, parent, teacher, psychologist, administrator]
name:
type: string
age:
type: integer
avatar_url:
type: string
format: uri
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
UserUpdateRequest:
type: object
properties:
name:
type: string
avatar_url:
type: string
format: uri
password:
type: string
format: password
# Authentication Schemas
LoginRequest:
type: object
required:
- phone
- password
properties:
phone:
type: string
password:
type: string
format: password
LoginResponse:
type: object
required:
- access_token
- token_type
- expires_in
properties:
access_token:
type: string
description: JWT access token
token_type:
type: string
example: "bearer"
expires_in:
type: integer
description: Token validity in seconds (604800 = 7 days)
refresh_token:
type: string
description: Refresh token for obtaining new access token
user:
$ref: '#/components/schemas/UserResponse'
# Risk Assessment Schemas
RiskAssessmentRequest:
type: object
required:
- user_id
- assessment_type
properties:
user_id:
type: string
assessment_type:
type: string
enum: [comprehensive, voice_only, text_only, behavioral_only]
data_sources:
type: array
items:
type: object
additionalProperties:
type: string
RiskAssessmentResponse:
type: object
required:
- id
- user_id
- risk_score
- risk_category
- created_at
properties:
id:
type: string
user_id:
type: string
risk_score:
type: integer
minimum: 0
maximum: 100
risk_category:
type: string
enum: [low, medium, high, critical]
risk_factors:
type: array
items:
type: object
properties:
category:
type: string
enum: [depression, anxiety, self_harm, social_withdrawal, academic_stress, family_conflict]
severity:
type: string
enum: [low, moderate, high, critical]
confidence:
type: number
format: float
minimum: 0
maximum: 1
recommendations:
type: array
items:
type: object
properties:
resource_id:
type: string
title:
type: string
type:
type: string
enum: [video, audio, article, interactive_tool]
alerts_triggered:
type: array
items:
type: object
properties:
recipient_role:
type: string
enum: [guardian, parent, teacher, psychologist]
notification_method:
type: string
enum: [sms, wechat, push, phone_call]
sent_at:
type: string
format: date-time
created_at:
type: string
format: date-time
RiskAssessmentList:
type: object
required:
- items
- total
- page
- page_size
properties:
items:
type: array
items:
$ref: '#/components/schemas/RiskAssessmentResponse'
total:
type: integer
page:
type: integer
page_size:
type: integer
# Data Collection Schemas
VoiceAnalysisResponse:
type: object
required:
- id
- user_id
- status
properties:
id:
type: string
user_id:
type: string
status:
type: string
enum: [processing, completed, failed]
estimated_completion:
type: string
format: date-time
results:
type: object
properties:
emotions:
type: array
items:
type: object
properties:
emotion:
type: string
confidence:
type: number
format: float
speech_rate:
type: number
format: float
description: Words per minute
dialect:
type: string
description: Detected dialect
dialect_confidence:
type: number
format: float
TextDataRequest:
type: object
required:
- user_id
- text
properties:
user_id:
type: string
text:
type: string
maxLength: 10000
context:
type: string
enum: [chat_message, diary_entry, homework_comment, other]
timestamp:
type: string
format: date-time
TextAnalysisResponse:
type: object
required:
- id
- user_id
- sentiment
- created_at
properties:
id:
type: string
user_id:
type: string
sentiment:
type: string
enum: [positive, neutral, negative]
sentiment_score:
type: number
format: float
minimum: -1
maximum: 1
emotions:
type: array
items:
type: object
properties:
emotion:
type: string
confidence:
type: number
format: float
risk_keywords:
type: array
items:
type: object
properties:
keyword:
type: string
category:
type: string
created_at:
type: string
format: date-time
# Resource Schemas
ResourceResponse:
type: object
required:
- id
- title
- type
- category
properties:
id:
type: string
title:
type: string
description:
type: string
type:
type: string
enum: [video, audio, article, interactive_tool]
category:
type: string
enum: [depression, anxiety, self_harm, social_withdrawal, academic_stress, family_conflict]
age_group:
type: string
enum: [elementary, middle_school, high_school]
duration_seconds:
type: integer
description: Duration (for video/audio)
url:
type: string
format: uri
thumbnail_url:
type: string
format: uri
created_at:
type: string
format: date-time
ResourceList:
type: object
required:
- items
- total
properties:
items:
type: array
items:
$ref: '#/components/schemas/ResourceResponse'
total:
type: integer
page:
type: integer
page_size:
type: integer
# Communication Schemas
ConversationCreateRequest:
type: object
required:
- participant_ids
properties:
participant_ids:
type: array
items:
type: string
minItems: 2
title:
type: string
ConversationResponse:
type: object
required:
- id
- participants
- created_at
properties:
id:
type: string
title:
type: string
participants:
type: array
items:
$ref: '#/components/schemas/UserResponse'
last_message:
type: object
properties:
content:
type: string
sent_at:
type: string
format: date-time
created_at:
type: string
format: date-time
ConversationList:
type: object
required:
- items
- total
properties:
items:
type: array
items:
$ref: '#/components/schemas/ConversationResponse'
total:
type: integer
page:
type: integer
page_size:
type: integer
MessageRequest:
type: object
required:
- content
properties:
content:
type: string
maxLength: 5000
message_type:
type: string
enum: [text, image, voice]
default: text
MessageResponse:
type: object
required:
- id
- conversation_id
- sender_id
- content
- sent_at
properties:
id:
type: string
conversation_id:
type: string
sender_id:
type: string
sender_name:
type: string
content:
type: string
message_type:
type: string
enum: [text, image, voice]
sent_at:
type: string
format: date-time
MessageList:
type: object
required:
- items
- total
properties:
items:
type: array
items:
$ref: '#/components/schemas/MessageResponse'
total:
type: integer
page:
type: integer
page_size:
type: integer
ConsultationRequest:
type: object
required:
- psychologist_id
- preferred_time
properties:
psychologist_id:
type: string
preferred_time:
type: string
format: date-time
notes:
type: string
maxLength: 1000
ConsultationResponse:
type: object
required:
- id
- child_id
- psychologist_id
- scheduled_time
- status
properties:
id:
type: string
child_id:
type: string
psychologist_id:
type: string
scheduled_time:
type: string
format: date-time
duration_minutes:
type: integer
default: 50
status:
type: string
enum: [scheduled, in_progress, completed, cancelled]
video_call_url:
type: string
format: uri
notes:
type: string
created_at:
type: string
format: date-time
# Analytics Schemas
DashboardResponse:
type: object
required:
- role
- data
properties:
role:
type: string
enum: [child, guardian, parent, teacher, psychologist, administrator]
data:
type: object
additionalProperties: true
description: Role-specific dashboard data
responses:
BadRequest:
description: Bad request (validation error)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Unauthorized:
description: Unauthorized (missing or invalid token)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Forbidden:
description: Forbidden (insufficient permissions)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'