dramaling-vocab-learning/docs/03_development/api/api-specification.md

873 lines
15 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.

# DramaLing API 規格文檔
## 1. API 概述
### 1.1 基本資訊
- **Base URL**:
- 開發: `http://localhost:3000/api`
- 生產: `https://api.dramaling.com`
- **版本**: v1
- **協議**: HTTPS
- **格式**: JSON
- **認證**: Bearer Token (JWT)
### 1.2 通用規範
#### 請求標頭
```http
Content-Type: application/json
Authorization: Bearer <token>
Accept-Language: zh-TW
X-Request-ID: <uuid>
```
#### 響應格式
```typescript
interface SuccessResponse<T> {
success: true;
data: T;
meta?: {
page?: number;
limit?: number;
total?: number;
hasMore?: boolean;
};
}
interface ErrorResponse {
success: false;
error: {
code: string;
message: string;
details?: any;
};
timestamp: string;
}
```
#### HTTP 狀態碼
- `200 OK` - 請求成功
- `201 Created` - 資源創建成功
- `204 No Content` - 刪除成功
- `400 Bad Request` - 請求參數錯誤
- `401 Unauthorized` - 未認證
- `403 Forbidden` - 無權限
- `404 Not Found` - 資源不存在
- `409 Conflict` - 資源衝突
- `422 Unprocessable Entity` - 驗證失敗
- `429 Too Many Requests` - 請求過多
- `500 Internal Server Error` - 伺服器錯誤
## 2. 認證 API
### 2.1 註冊
**POST** `/api/auth/register`
#### 請求
```json
{
"email": "user@example.com",
"password": "SecurePass123!",
"username": "johndoe"
}
```
#### 響應 (201)
```json
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"username": "johndoe",
"emailVerified": false,
"createdAt": "2024-03-15T10:00:00Z"
},
"tokens": {
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"expiresIn": 900
}
}
}
```
#### 錯誤響應 (409)
```json
{
"success": false,
"error": {
"code": "EMAIL_EXISTS",
"message": "Email already registered"
}
}
```
### 2.2 登入
**POST** `/api/auth/login`
#### 請求
```json
{
"email": "user@example.com",
"password": "SecurePass123!",
"rememberMe": true
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"username": "johndoe",
"avatarUrl": "https://...",
"lastLoginAt": "2024-03-15T10:00:00Z"
},
"tokens": {
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"expiresIn": 2592000
}
}
}
```
### 2.3 Google OAuth
**POST** `/api/auth/google`
#### 請求
```json
{
"idToken": "google_id_token"
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@gmail.com",
"username": "user",
"provider": "google",
"avatarUrl": "https://..."
},
"tokens": {
"accessToken": "eyJ...",
"refreshToken": "eyJ..."
},
"isNewUser": false
}
}
```
### 2.4 重新整理 Token
**POST** `/api/auth/refresh`
#### 請求
```json
{
"refreshToken": "eyJ..."
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"expiresIn": 900
}
}
```
### 2.5 登出
**POST** `/api/auth/logout`
#### 請求
```json
{
"refreshToken": "eyJ..."
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"message": "Logged out successfully"
}
}
```
### 2.6 忘記密碼
**POST** `/api/auth/forgot-password`
#### 請求
```json
{
"email": "user@example.com"
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"message": "Password reset email sent"
}
}
```
### 2.7 重設密碼
**POST** `/api/auth/reset-password`
#### 請求
```json
{
"token": "reset_token",
"newPassword": "NewSecurePass123!"
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"message": "Password reset successfully"
}
}
```
## 3. 用戶 API
### 3.1 取得個人資料
**GET** `/api/users/me`
#### 響應 (200)
```json
{
"success": true,
"data": {
"id": "uuid",
"email": "user@example.com",
"username": "johndoe",
"avatarUrl": "https://...",
"emailVerified": true,
"createdAt": "2024-03-01T00:00:00Z",
"stats": {
"totalFlashcards": 150,
"totalDecks": 5,
"studyStreak": 7,
"level": 3,
"experience": 1250
},
"preferences": {
"dailyGoal": 20,
"reminderTime": "09:00",
"reminderEnabled": true,
"theme": "light",
"language": "zh-TW"
}
}
}
```
### 3.2 更新個人資料
**PATCH** `/api/users/me`
#### 請求
```json
{
"username": "newusername",
"avatarUrl": "https://..."
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"id": "uuid",
"username": "newusername",
"avatarUrl": "https://...",
"updatedAt": "2024-03-15T10:00:00Z"
}
}
```
### 3.3 更新偏好設定
**PUT** `/api/users/me/preferences`
#### 請求
```json
{
"dailyGoal": 30,
"reminderTime": "20:00",
"reminderEnabled": true,
"theme": "dark",
"language": "zh-TW",
"soundEnabled": true,
"autoPlayAudio": false
}
```
## 4. 卡組 API
### 4.1 取得卡組列表
**GET** `/api/decks`
#### 查詢參數
- `page` (number): 頁數,預設 1
- `limit` (number): 每頁數量,預設 20
- `sort` (string): 排序方式 `created_at` | `updated_at` | `name`
- `order` (string): 排序順序 `asc` | `desc`
#### 響應 (200)
```json
{
"success": true,
"data": [
{
"id": "uuid",
"name": "Business English",
"description": "Common business vocabulary",
"coverImage": "https://...",
"flashcardCount": 45,
"isPublic": false,
"tags": ["business", "professional"],
"createdAt": "2024-03-01T00:00:00Z",
"updatedAt": "2024-03-15T00:00:00Z"
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 5,
"hasMore": false
}
}
```
### 4.2 取得單一卡組
**GET** `/api/decks/{deckId}`
#### 響應 (200)
```json
{
"success": true,
"data": {
"id": "uuid",
"name": "Business English",
"description": "Common business vocabulary",
"coverImage": "https://...",
"flashcardCount": 45,
"isPublic": false,
"tags": ["business", "professional"],
"flashcards": [
{
"id": "uuid",
"word": "negotiate",
"translation": "協商",
"difficulty": "intermediate"
}
],
"createdAt": "2024-03-01T00:00:00Z"
}
}
```
### 4.3 創建卡組
**POST** `/api/decks`
#### 請求
```json
{
"name": "TOEFL Vocabulary",
"description": "Essential TOEFL words",
"coverImage": "https://...",
"isPublic": false,
"tags": ["toefl", "exam"]
}
```
#### 響應 (201)
```json
{
"success": true,
"data": {
"id": "uuid",
"name": "TOEFL Vocabulary",
"description": "Essential TOEFL words",
"flashcardCount": 0,
"createdAt": "2024-03-15T10:00:00Z"
}
}
```
### 4.4 更新卡組
**PATCH** `/api/decks/{deckId}`
#### 請求
```json
{
"name": "Updated Name",
"description": "Updated description"
}
```
### 4.5 刪除卡組
**DELETE** `/api/decks/{deckId}`
#### 響應 (204)
無內容
## 5. 詞卡 API
### 5.1 取得詞卡列表
**GET** `/api/flashcards`
#### 查詢參數
- `deckId` (string): 卡組 ID
- `search` (string): 搜尋關鍵字
- `tags` (string[]): 標籤篩選
- `difficulty` (string): 難度篩選
- `status` (string): 學習狀態 `new` | `learning` | `review` | `mastered`
- `page` (number): 頁數
- `limit` (number): 每頁數量
#### 響應 (200)
```json
{
"success": true,
"data": [
{
"id": "uuid",
"deckId": "uuid",
"word": "negotiate",
"translation": "協商",
"definition": "To discuss something with someone in order to reach an agreement",
"partOfSpeech": "verb",
"pronunciation": "/nɪˈɡoʊʃieɪt/",
"exampleSentence": "We need to negotiate a better deal.",
"exampleTranslation": "我們需要協商一個更好的交易。",
"difficulty": "intermediate",
"tags": ["business", "communication"],
"learningStatus": {
"status": "learning",
"nextReviewDate": "2024-03-16T00:00:00Z",
"accuracy": 75
}
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 150,
"hasMore": true
}
}
```
### 5.2 取得單一詞卡
**GET** `/api/flashcards/{flashcardId}`
### 5.3 創建詞卡
**POST** `/api/flashcards`
#### 請求
```json
{
"deckId": "uuid",
"word": "negotiate",
"translation": "協商",
"definition": "To discuss something with someone in order to reach an agreement",
"partOfSpeech": "verb",
"pronunciation": "/nɪˈɡoʊʃieɪt/",
"exampleSentence": "We need to negotiate a better deal.",
"exampleTranslation": "我們需要協商一個更好的交易。",
"difficulty": "intermediate",
"memoryTip": "Think of 'go' + 'she' + 'ate' = negotiate",
"tags": ["business", "communication"]
}
```
### 5.4 更新詞卡
**PATCH** `/api/flashcards/{flashcardId}`
### 5.5 刪除詞卡
**DELETE** `/api/flashcards/{flashcardId}`
### 5.6 批量操作
**POST** `/api/flashcards/bulk`
#### 請求
```json
{
"flashcardIds": ["uuid1", "uuid2", "uuid3"],
"operation": "move",
"targetDeckId": "uuid"
}
```
## 6. AI 生成 API
### 6.1 生成詞卡
**POST** `/api/ai/generate`
#### 請求
```json
{
"text": "The quick brown fox jumps over the lazy dog...",
"theme": "daily_conversation",
"count": 10,
"difficulty": "intermediate",
"includeExamples": true,
"targetDeckId": "uuid"
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"requestId": "uuid",
"status": "processing",
"estimatedTime": 5000,
"flashcards": [
{
"word": "negotiate",
"translation": "協商",
"definition": "To discuss...",
"pronunciation": "/nɪˈɡoʊʃieɪt/",
"example": "We need to negotiate...",
"difficulty": "intermediate"
}
],
"metadata": {
"tokensUsed": 1500,
"processingTime": 3200,
"model": "gemini-pro"
}
}
}
```
### 6.2 取得生成狀態
**GET** `/api/ai/generate/{requestId}`
#### 響應 (200)
```json
{
"success": true,
"data": {
"requestId": "uuid",
"status": "completed",
"flashcards": [...],
"completedAt": "2024-03-15T10:00:05Z"
}
}
```
### 6.3 取得用戶配額
**GET** `/api/ai/quota`
#### 響應 (200)
```json
{
"success": true,
"data": {
"daily": {
"used": 25,
"limit": 50,
"resetsAt": "2024-03-16T00:00:00Z"
},
"monthly": {
"used": 500,
"limit": 1500
},
"isPremium": false
}
}
```
## 7. 學習 API
### 7.1 開始學習會話
**POST** `/api/learning/sessions`
#### 請求
```json
{
"deckId": "uuid",
"mode": "flashcard",
"cardLimit": 20
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"sessionId": "uuid",
"cards": [...],
"totalCards": 20,
"newCards": 5,
"reviewCards": 15
}
}
```
### 7.2 提交學習結果
**POST** `/api/learning/reviews`
#### 請求
```json
{
"sessionId": "uuid",
"flashcardId": "uuid",
"rating": 4,
"timeSpent": 15,
"isCorrect": true
}
```
#### 響應 (200)
```json
{
"success": true,
"data": {
"nextReviewDate": "2024-03-18T00:00:00Z",
"interval": 3,
"easeFactor": 2.5,
"repetitions": 2
}
}
```
### 7.3 取得待複習詞卡
**GET** `/api/learning/due`
#### 查詢參數
- `deckId` (string): 特定卡組
- `limit` (number): 數量限制
#### 響應 (200)
```json
{
"success": true,
"data": {
"dueCards": [...],
"newCards": [...],
"totalDue": 25,
"totalNew": 10
}
}
```
### 7.4 結束學習會話
**POST** `/api/learning/sessions/{sessionId}/complete`
#### 響應 (200)
```json
{
"success": true,
"data": {
"summary": {
"cardsStudied": 20,
"correctAnswers": 18,
"accuracy": 90,
"timeSpent": 600,
"experience": 100,
"streakDays": 8
}
}
}
```
## 8. 統計 API
### 8.1 取得學習統計
**GET** `/api/stats`
#### 查詢參數
- `period` (string): `daily` | `weekly` | `monthly` | `yearly`
- `startDate` (string): YYYY-MM-DD
- `endDate` (string): YYYY-MM-DD
#### 響應 (200)
```json
{
"success": true,
"data": {
"overview": {
"totalCards": 500,
"masteredCards": 200,
"learningCards": 250,
"newCards": 50,
"studyStreak": 15,
"totalStudyTime": 12000
},
"daily": [
{
"date": "2024-03-15",
"cardsStudied": 30,
"newCards": 5,
"reviewCards": 25,
"accuracy": 85,
"studyTime": 45
}
],
"heatmap": {
"2024-03-15": 3,
"2024-03-14": 2,
"2024-03-13": 4
}
}
}
```
### 8.2 取得成就列表
**GET** `/api/stats/achievements`
#### 響應 (200)
```json
{
"success": true,
"data": {
"unlocked": [
{
"id": "first_card",
"name": "First Step",
"description": "Create your first flashcard",
"icon": "🎯",
"unlockedAt": "2024-03-01T00:00:00Z",
"points": 10
}
],
"inProgress": [
{
"id": "week_streak",
"name": "Week Warrior",
"description": "Study for 7 days in a row",
"progress": 85,
"target": 7,
"current": 6
}
],
"totalPoints": 250
}
}
```
## 9. 錯誤處理
### 9.1 錯誤碼列表
| 錯誤碼 | HTTP 狀態 | 描述 |
|--------|-----------|------|
| `UNAUTHORIZED` | 401 | 未認證 |
| `FORBIDDEN` | 403 | 無權限 |
| `NOT_FOUND` | 404 | 資源不存在 |
| `VALIDATION_ERROR` | 422 | 驗證失敗 |
| `EMAIL_EXISTS` | 409 | Email 已存在 |
| `USERNAME_EXISTS` | 409 | 用戶名已存在 |
| `INVALID_CREDENTIALS` | 401 | 認證資訊錯誤 |
| `TOKEN_EXPIRED` | 401 | Token 過期 |
| `RATE_LIMIT_EXCEEDED` | 429 | 請求過多 |
| `QUOTA_EXCEEDED` | 402 | 配額超限 |
| `AI_SERVICE_ERROR` | 503 | AI 服務錯誤 |
| `DATABASE_ERROR` | 500 | 資料庫錯誤 |
### 9.2 錯誤響應範例
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"email": "Invalid email format",
"password": "Password must be at least 8 characters"
}
},
"timestamp": "2024-03-15T10:00:00Z"
}
```
## 10. Rate Limiting
### 10.1 限制規則
- 一般 API: 100 requests/minute
- AI 生成: 10 requests/minute
- 認證相關: 5 requests/minute
### 10.2 響應標頭
```http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1710496800
```
### 10.3 超限響應 (429)
```json
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"retryAfter": 60
}
}
```
## 11. Webhook
### 11.1 事件類型
- `user.created` - 新用戶註冊
- `flashcard.generated` - AI 生成完成
- `achievement.unlocked` - 成就解鎖
- `subscription.updated` - 訂閱更新
### 11.2 Webhook 格式
```json
{
"id": "evt_uuid",
"type": "flashcard.generated",
"created": "2024-03-15T10:00:00Z",
"data": {
"requestId": "uuid",
"userId": "uuid",
"flashcardCount": 10
}
}
```
### 11.3 簽名驗證
```javascript
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expected) {
throw new Error('Invalid signature');
}
```