dramaling-app/docs/technical/api-specifications.md

998 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API 規格文檔
## 概述
定義 Drama Ling 應用的完整 RESTful API 規格,基於 `system_structure_design.json` 中定義的14個功能特性和9個數據源設計。
## API 設計原則
### RESTful 設計標準
- [ ] **資源導向**: API端點基於資源設計而非動作
- [ ] **HTTP動詞**: 正確使用GET、POST、PUT、DELETE、PATCH
- [ ] **狀態碼**: 使用標準HTTP狀態碼表示結果
- [ ] **無狀態**: API設計為無狀態不依賴server端session
- [ ] **版本控制**: API版本控制策略 (如 `/api/v1/`)
### API 安全原則
- [ ] **身份驗證**: JWT Token認證機制
- [ ] **授權控制**: Role-based權限控制
- [ ] **資料驗證**: 嚴格的輸入資料驗證
- [ ] **速率限制**: 防止API濫用的速率控制
- [ ] **HTTPS強制**: 所有API強制使用HTTPS
### 回應格式標準
```json
{
"success": boolean,
"data": object | array | null,
"message": string,
"error": {
"code": string,
"message": string,
"details": object
},
"meta": {
"timestamp": "ISO8601",
"request_id": "string",
"pagination": object
}
}
```
## 認證與授權 API
### 用戶認證
```http
POST /api/v1/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "securePassword123",
"username": "dramatic_learner",
"preferredLanguage": "en",
"nativeLanguage": "zh-TW"
}
```
```http
Response 201 Created
{
"success": true,
"data": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"username": "dramatic_learner",
"email": "user@example.com",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440001",
"expiresIn": 3600
},
"message": "User registered successfully",
"meta": {
"timestamp": "2024-09-05T15:30:00Z",
"requestId": "550e8400-e29b-41d4-a716-446655440002"
}
}
```
### 登入驗證
```http
POST /api/v1/auth/login
{
"email": "user@example.com",
"password": "securePassword123"
}
```
### Token 更新
```http
POST /api/v1/auth/refresh
Authorization: Bearer <refresh_token>
```
### 登出
```http
POST /api/v1/auth/logout
Authorization: Bearer <access_token>
```
## 用戶資料管理 API
### 用戶資料 (UserProfile)
#### 獲取用戶資料
```http
GET /api/v1/users/profile
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"user_id": "USR_12345",
"username": "dramatic_learner",
"email": "user@example.com",
"avatar_url": "https://cdn.example.com/avatars/12345.jpg",
"level": "B1",
"total_score": 15680,
"streak_days": 15,
"joined_date": "2024-01-15T08:00:00Z",
"last_active": "2024-09-05T14:30:00Z",
"preferences": {
"target_language": "en",
"native_language": "zh-TW",
"difficulty_preference": "adaptive",
"daily_goal_minutes": 30,
"notifications_enabled": true,
"theme": "light"
},
"subscription": {
"plan": "premium",
"status": "active",
"expires_at": "2025-01-15T08:00:00Z"
}
}
}
```
#### 更新用戶資料
```http
PUT /api/v1/users/profile
Authorization: Bearer <access_token>
{
"username": "new_username",
"avatar_url": "https://cdn.example.com/avatars/new_avatar.jpg",
"preferences": {
"daily_goal_minutes": 45,
"notifications_enabled": false
}
}
```
#### 用戶學習統計
```http
GET /api/v1/users/stats
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"total_dialogues": 245,
"total_study_time": 1280, // minutes
"vocabulary_learned": 890,
"vocabulary_mastered": 650,
"scenarios_completed": 35,
"achievements_unlocked": 18,
"current_streak": 15,
"longest_streak": 28,
"weekly_progress": {
"dialogues_this_week": 12,
"minutes_this_week": 180,
"goal_completion_rate": 0.85
}
}
}
```
## 學習內容 API
### 課程與場景 (Lesson)
#### 獲取場景列表
```http
GET /api/v1/lessons/scenarios
Authorization: Bearer <access_token>
Query Parameters:
- category: string (daily_life, social, emergency, professional)
- difficulty: string (A1, A2, B1, B2, C1, C2)
- limit: integer (default: 20)
- offset: integer (default: 0)
Response 200 OK
{
"success": true,
"data": {
"scenarios": [
{
"scenario_id": "SC_Restaurant_01",
"title": "餐廳訂位",
"description": "學習如何在餐廳預約座位和點餐",
"category": "daily_life",
"difficulty": "A2",
"estimated_duration": 8, // minutes
"thumbnail_url": "https://cdn.example.com/scenarios/restaurant.jpg",
"vocabulary_count": 25,
"completion_rate": 0.75,
"user_completed": true,
"user_score": 85,
"unlock_condition": null,
"is_premium": false
}
],
"pagination": {
"total": 65,
"page": 1,
"per_page": 20,
"total_pages": 4
}
}
}
```
#### 獲取場景詳情
```http
GET /api/v1/lessons/scenarios/{scenario_id}
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"scenario_id": "SC_Restaurant_01",
"title": "餐廳訂位",
"description": "學習如何在餐廳預約座位和點餐",
"category": "daily_life",
"difficulty": "A2",
"learning_objectives": [
"學會預約餐廳座位",
"掌握點餐相關詞彙",
"練習詢問食材和偏好"
],
"target_vocabulary": [
{
"word": "reservation",
"phonetic": "/ˌrezəˈveɪʃən/",
"translation": "預約",
"definition": "an arrangement to have something kept for you"
}
],
"cultural_notes": "西式餐廳通常需要事先預約,特別是在熱門時段...",
"estimated_duration": 8,
"prerequisite_scenarios": ["SC_Greeting_01"],
"user_progress": {
"completed": true,
"best_score": 85,
"completion_count": 3,
"last_completed": "2024-09-03T19:20:00Z"
}
}
}
```
### 詞彙管理 API
#### 獲取詞彙列表
```http
GET /api/v1/vocabulary
Authorization: Bearer <access_token>
Query Parameters:
- category: string (life, academic, business, etc.)
- difficulty: string (A1-C2)
- mastery_level: string (learning, practicing, mastered)
- limit: integer (default: 50)
Response 200 OK
{
"success": true,
"data": {
"vocabulary": [
{
"vocab_id": "VOC_0001",
"word": "restaurant",
"phonetic": "/ˈrestərɑːnt/",
"part_of_speech": "noun",
"definition": "A place where people pay to sit and eat meals",
"translation": "餐廳",
"difficulty": "A2",
"frequency_rank": 1250,
"user_mastery": {
"level": "practicing", // learning, practicing, mastered
"score": 75,
"review_count": 5,
"last_reviewed": "2024-09-03T10:15:00Z",
"next_review": "2024-09-07T10:15:00Z"
},
"example_sentences": [
{
"english": "We made a reservation at the new restaurant.",
"chinese": "我們在新餐廳訂了位。"
}
]
}
]
}
}
```
#### 詞彙複習API
```http
GET /api/v1/vocabulary/review/daily
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"review_session_id": "REV_20240905_USR12345",
"total_words": 15,
"estimated_time": 5, // minutes
"words": [
{
"vocab_id": "VOC_0001",
"word": "restaurant",
"review_type": "recognition", // recognition, recall, spelling
"options": ["餐廳", "旅館", "商店", "學校"] // for recognition type
}
]
}
}
```
#### 提交複習結果
```http
POST /api/v1/vocabulary/review/submit
Authorization: Bearer <access_token>
{
"review_session_id": "REV_20240905_USR12345",
"results": [
{
"vocab_id": "VOC_0001",
"user_answer": "餐廳",
"is_correct": true,
"response_time": 2.5, // seconds
"confidence": 4 // 1-5 scale
}
]
}
```
## 對話練習 API
### 對話系統 (Dialogue)
#### 開始對話練習
```http
POST /api/v1/dialogues/start
Authorization: Bearer <access_token>
{
"scenario_id": "SC_Restaurant_01",
"difficulty_override": "A2", // optional
"target_vocabulary": ["reservation", "menu", "order"] // optional
}
Response 201 Created
{
"success": true,
"data": {
"dialogue_id": "DLG_20240905_001",
"scenario_id": "SC_Restaurant_01",
"session_token": "session_token_here",
"initial_context": {
"setting": "高級餐廳內部晚上8點",
"your_role": "客人",
"ai_role": "餐廳服務員",
"objective": "成功預約並點餐"
},
"ai_message": {
"message": "Good evening! Welcome to Milano Restaurant. Do you have a reservation?",
"audio_url": "https://cdn.example.com/audio/dlg001_001.mp3",
"suggestions": [
"Yes, I have a reservation under Smith.",
"No, but could we get a table for two?",
"I'd like to make a reservation for tonight."
]
}
}
}
```
#### 發送對話訊息
```http
POST /api/v1/dialogues/{dialogue_id}/message
Authorization: Bearer <access_token>
{
"message": "Yes, I have a reservation under Chen for 8 PM.",
"message_type": "text", // text, audio
"audio_url": "https://cdn.example.com/user_audio/msg001.mp3" // if audio
}
Response 200 OK
{
"success": true,
"data": {
"ai_response": {
"message": "Perfect! Mr. Chen, your table for two is ready. Right this way please.",
"audio_url": "https://cdn.example.com/audio/dlg001_002.mp3",
"analysis": {
"grammar_score": 90,
"semantic_score": 95,
"fluency_score": 85,
"overall_score": 90,
"feedback": "Excellent use of formal language for restaurant context!"
},
"suggestions": [
"Thank you. Could we see the menu please?",
"Great! What do you recommend today?",
"Thank you. We'd like to start with drinks."
]
},
"dialogue_progress": {
"turns_completed": 2,
"estimated_turns_remaining": 6,
"objectives_completed": ["greeting", "reservation_confirmation"],
"objectives_remaining": ["ordering", "payment"]
}
}
}
```
#### 獲取AI分析詳情
```http
GET /api/v1/dialogues/{dialogue_id}/analysis
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"dialogue_id": "DLG_20240905_001",
"overall_analysis": {
"grammar_score": 88,
"semantic_score": 92,
"fluency_score": 85,
"total_score": 88,
"completion_percentage": 100
},
"detailed_feedback": [
{
"turn_number": 1,
"user_message": "Yes, I have a reservation under Chen for 8 PM.",
"analysis": {
"grammar_issues": [],
"semantic_appropriateness": "Excellent - appropriate formality level",
"fluency_notes": "Natural and confident delivery",
"suggestions": [],
"vocabulary_used": [
{
"word": "reservation",
"usage_correctness": "perfect",
"context_appropriateness": "excellent"
}
]
}
}
],
"improvement_suggestions": [
"Consider using more varied vocabulary for ordering",
"Practice pronunciation of 'th' sounds"
],
"vocabulary_progress": {
"words_practiced": 8,
"words_used_correctly": 7,
"new_words_encountered": 3
}
}
}
```
#### 結束對話
```http
POST /api/v1/dialogues/{dialogue_id}/complete
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"dialogue_summary": {
"dialogue_id": "DLG_20240905_001",
"duration": 420, // seconds
"turns_completed": 8,
"final_score": 88,
"objectives_achieved": 4,
"objectives_total": 4,
"vocabulary_practiced": 12,
"experience_gained": 150,
"score_gained": 75
},
"rewards": {
"experience_points": 150,
"score_points": 75,
"achievements_unlocked": ["First Perfect Dialogue"],
"vocabulary_progress": {
"words_advanced": 3,
"words_mastered": 1
}
}
}
}
```
## 任務系統 API
### 任務管理 (Task & TaskReward)
#### 獲取可用任務
```http
GET /api/v1/tasks
Authorization: Bearer <access_token>
Query Parameters:
- type: string (daily, weekly, achievement, challenge)
- status: string (available, in_progress, completed)
Response 200 OK
{
"success": true,
"data": {
"tasks": [
{
"task_id": "TASK_DAILY_001",
"type": "daily",
"title": "完成3次對話練習",
"description": "今天完成任意3次對話練習以獲得獎勵",
"objectives": [
{
"objective_id": "OBJ_001",
"description": "完成對話練習",
"target_value": 3,
"current_value": 1,
"unit": "次"
}
],
"rewards": {
"experience": 100,
"score": 50,
"special_items": ["daily_streak_bonus"]
},
"deadline": "2024-09-05T23:59:59Z",
"status": "in_progress",
"created_at": "2024-09-05T00:00:00Z"
}
]
}
}
```
#### 獲取任務詳情
```http
GET /api/v1/tasks/{task_id}
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"task_id": "TASK_WEEKLY_001",
"type": "weekly",
"title": "週練習大師",
"description": "本週完成20次對話練習並達到平均85分",
"long_description": "挑戰自己在本週內完成20次高品質的對話練習...",
"objectives": [
{
"objective_id": "OBJ_001",
"description": "完成對話練習",
"target_value": 20,
"current_value": 8,
"unit": "次"
},
{
"objective_id": "OBJ_002",
"description": "平均分數達標",
"target_value": 85,
"current_value": 87.5,
"unit": "分"
}
],
"rewards": {
"experience": 500,
"score": 300,
"special_items": ["premium_scenario_unlock"],
"achievements": ["weekly_master"]
},
"progress_percentage": 40,
"deadline": "2024-09-08T23:59:59Z",
"difficulty": "medium"
}
}
```
#### 領取任務獎勵
```http
POST /api/v1/tasks/{task_id}/claim_reward
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"rewards_claimed": {
"experience": 500,
"score": 300,
"special_items": ["premium_scenario_unlock"],
"achievements": ["weekly_master"]
},
"updated_user_stats": {
"total_experience": 15680,
"total_score": 8950,
"level": "B1+",
"achievements_count": 19
}
}
}
```
## 排行榜與競爭 API
### 排行榜系統 (Leaderboard)
#### 獲取排行榜
```http
GET /api/v1/leaderboard
Authorization: Bearer <access_token>
Query Parameters:
- type: string (global, weekly, friends, regional)
- category: string (overall, dialogue_count, vocabulary_mastered)
- limit: integer (default: 50)
Response 200 OK
{
"success": true,
"data": {
"leaderboard_type": "global",
"category": "overall",
"period": "all_time",
"updated_at": "2024-09-05T15:30:00Z",
"user_rank": {
"rank": 1247,
"score": 15680,
"percentile": 78.5
},
"top_users": [
{
"rank": 1,
"user_id": "USR_VIP_001",
"username": "LanguageMaster",
"avatar_url": "https://cdn.example.com/avatars/vip001.jpg",
"score": 45680,
"level": "C2",
"country": "TW",
"streak_days": 365,
"badges": ["yearly_champion", "perfectionist"]
}
],
"nearby_users": [
// Users around current user's rank
]
}
}
```
#### 好友排行榜
```http
GET /api/v1/leaderboard/friends
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"friends_ranking": [
{
"rank": 1,
"user_id": "USR_12346",
"username": "StudyBuddy",
"avatar_url": "https://cdn.example.com/avatars/12346.jpg",
"score": 18950,
"level": "B2",
"status": "online",
"recent_activity": "完成了商務會議場景 - 2小時前"
}
],
"current_user": {
"rank": 3,
"score": 15680,
"score_difference": -3270, // difference from rank 1
"rank_change": 1 // compared to last week
}
}
}
```
## 訂閱與購買 API
### 訂閱管理 (Subscription)
#### 獲取訂閱方案
```http
GET /api/v1/subscriptions/plans
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"plans": [
{
"plan_id": "PLAN_BASIC",
"name": "基礎版",
"description": "解鎖基礎功能,享受無廣告體驗",
"price": {
"monthly": {
"amount": 199,
"currency": "TWD",
"original_price": 199
},
"yearly": {
"amount": 1980,
"currency": "TWD",
"original_price": 2388,
"discount_percentage": 17
}
},
"features": [
"無限對話練習",
"無廣告體驗",
"基礎AI分析",
"雲端同步"
],
"limitations": [
"僅基礎和社交場景",
"不含語音識別"
]
}
],
"current_subscription": {
"plan_id": "PLAN_PREMIUM",
"status": "active",
"expires_at": "2025-01-15T08:00:00Z",
"auto_renewal": true,
"payment_method": "credit_card"
}
}
}
```
#### 訂閱方案
```http
POST /api/v1/subscriptions/subscribe
Authorization: Bearer <access_token>
{
"plan_id": "PLAN_PREMIUM",
"billing_cycle": "yearly", // monthly, yearly
"payment_method_id": "pm_1234567890",
"auto_renewal": true
}
Response 201 Created
{
"success": true,
"data": {
"subscription_id": "SUB_20240905_001",
"plan_id": "PLAN_PREMIUM",
"status": "active",
"started_at": "2024-09-05T15:30:00Z",
"expires_at": "2025-09-05T15:30:00Z",
"next_billing_date": "2025-09-05T15:30:00Z",
"amount_paid": 3999,
"currency": "TWD"
}
}
```
### 內購系統 (Purchase)
#### 獲取付費內容
```http
GET /api/v1/store/content
Authorization: Bearer <access_token>
Query Parameters:
- category: string (scenario_pack, expert_course, premium_content)
- price_range: string (0-100, 100-500, 500+)
Response 200 OK
{
"success": true,
"data": {
"content_packs": [
{
"content_id": "PACK_TRAVEL_001",
"type": "scenario_pack",
"title": "旅遊場景包",
"description": "包含機場、飯店、觀光等15個實用旅遊場景",
"price": {
"amount": 149,
"currency": "TWD",
"original_price": 199,
"discount_percentage": 25
},
"content_preview": {
"scenarios_count": 15,
"estimated_hours": 8,
"difficulty_range": "A2-B2",
"preview_scenario": "SC_AIRPORT_001"
},
"thumbnail_url": "https://cdn.example.com/packs/travel.jpg",
"user_owned": false,
"special_offer": {
"expires_at": "2024-09-10T23:59:59Z",
"offer_text": "限時75折優惠"
}
}
]
}
}
```
#### 購買內容
```http
POST /api/v1/store/purchase
Authorization: Bearer <access_token>
{
"content_id": "PACK_TRAVEL_001",
"payment_method_id": "pm_1234567890"
}
Response 201 Created
{
"success": true,
"data": {
"purchase_id": "PUR_20240905_001",
"content_id": "PACK_TRAVEL_001",
"amount_paid": 149,
"currency": "TWD",
"purchased_at": "2024-09-05T15:45:00Z",
"content_unlocked": {
"scenarios": ["SC_AIRPORT_001", "SC_HOTEL_001", "..."],
"access_expires": null // permanent access
}
}
}
```
### 廣告系統 (AdImpression)
#### 獲取廣告獎勵機會
```http
GET /api/v1/ads/opportunities
Authorization: Bearer <access_token>
Response 200 OK
{
"success": true,
"data": {
"available_ads": [
{
"ad_id": "AD_REWARD_001",
"type": "video",
"duration": 30, // seconds
"reward": {
"type": "extra_dialogue",
"quantity": 2,
"description": "額外2次對話練習機會"
},
"cooldown_remaining": 0, // seconds until next ad
"daily_limit_remaining": 3
}
]
}
}
```
#### 觀看廣告獲得獎勵
```http
POST /api/v1/ads/watch
Authorization: Bearer <access_token>
{
"ad_id": "AD_REWARD_001",
"watch_duration": 30, // seconds actually watched
"completion_status": "completed" // completed, skipped, error
}
Response 200 OK
{
"success": true,
"data": {
"reward_granted": {
"type": "extra_dialogue",
"quantity": 2,
"expires_at": "2024-09-06T15:45:00Z"
},
"next_ad_available_at": "2024-09-05T16:15:00Z"
}
}
```
---
## 錯誤處理
### 標準錯誤碼
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "輸入資料驗證失敗",
"details": {
"field": "email",
"reason": "invalid_format"
}
}
}
```
### 常見錯誤碼
- `UNAUTHORIZED` (401): 未授權存取
- `FORBIDDEN` (403): 權限不足
- `NOT_FOUND` (404): 資源不存在
- `VALIDATION_ERROR` (400): 資料驗證失敗
- `RATE_LIMIT_EXCEEDED` (429): 超過速率限制
- `INTERNAL_SERVER_ERROR` (500): 伺服器內部錯誤
- `SERVICE_UNAVAILABLE` (503): 服務暫時不可用
### 訂閱相關錯誤
- `SUBSCRIPTION_REQUIRED`: 需要訂閱才能存取
- `SUBSCRIPTION_EXPIRED`: 訂閱已過期
- `PAYMENT_FAILED`: 付款處理失敗
- `CONTENT_NOT_PURCHASED`: 內容未購買
---
## API 版本控制與部署
### 版本控制策略
- [ ] **URL版本控制**: `/api/v1/`, `/api/v2/`
- [ ] **向後相容**: 新版本保持向後相容性
- [ ] **廢棄通知**: 提前6個月通知API廢棄
- [ ] **多版本支援**: 同時支援2-3個版本
- [ ] **版本文檔**: 每個版本維護獨立文檔
### 環境配置
```bash
# 開發環境
API_BASE_URL=https://dev-api.dramaling.com
API_VERSION=v1
# 測試環境
API_BASE_URL=https://staging-api.dramaling.com
API_VERSION=v1
# 生產環境
API_BASE_URL=https://api.dramaling.com
API_VERSION=v1
```
### 效能考量
- [ ] **回應時間**: 95%的API請求在200ms內回應
- [ ] **快取策略**: 靜態內容使用CDN動態內容使用Redis
- [ ] **資料庫優化**: 適當的索引和查詢優化
- [ ] **負載平衡**: 水平擴展API服務器
- [ ] **監控告警**: API效能和錯誤率監控
---
## 待完成任務
### 高優先級
1. [ ] 完善所有API端點的詳細規格和範例
2. [ ] 設計API的認證和授權機制
3. [ ] 建立API文檔的自動生成和維護流程
4. [ ] 實現API的錯誤處理和驗證邏輯
### 中優先級
1. [ ] 設計API的快取和效能優化策略
2. [ ] 建立API的測試套件和自動化測試
3. [ ] 規劃API的版本控制和遷移策略
4. [ ] 設計API的監控和分析系統
### 低優先級
1. [ ] 研究GraphQL作為REST API的補充
2. [ ] 探索Real-time API (WebSocket) 的應用場景
3. [ ] 建立API的開發者工具和SDK
4. [ ] 設計第三方整合的API授權機制
---
**最後更新**: 2024年9月5日
**負責人**: 待分配
**審查週期**: 每兩週檢討一次