dramaling-vocab-learning/docs/03_development/api/api-endpoints-detailed.md

12 KiB

DramaLing API 端點詳細規格

🌐 API 基礎設定

Base URL

Development: http://localhost:3000/api
Production: https://api.dramaling.com

認證方式

Authorization: Bearer <JWT_TOKEN>

響應格式

interface ApiResponse<T> {
  success: boolean
  data?: T
  error?: {
    code: string
    message: string
    details?: any
  }
  meta?: {
    pagination?: {
      page: number
      limit: number
      total: number
      totalPages: number
    }
  }
}

🔐 認證 API

POST /api/auth/register

註冊新用戶

// Request
interface RegisterRequest {
  email: string
  username: string
  password: string
  confirmPassword: string
}

// Response
interface RegisterResponse {
  user: {
    id: string
    email: string
    username: string
  }
  message: string
}

// Validation
- email: valid email format
- username: 3-20 characters, alphanumeric and underscore
- password: min 8 chars, must contain uppercase, lowercase, number
- confirmPassword: must match password

POST /api/auth/login

用戶登入

// Request
interface LoginRequest {
  email: string
  password: string
  rememberMe?: boolean
}

// Response
interface LoginResponse {
  user: User
  accessToken: string
  refreshToken: string
  expiresIn: number
}

// Error codes
- INVALID_CREDENTIALS: 帳號或密碼錯誤
- ACCOUNT_LOCKED: 帳號被鎖定
- EMAIL_NOT_VERIFIED: Email 未驗證

POST /api/auth/logout

登出

// Request
interface LogoutRequest {
  refreshToken?: string
  allDevices?: boolean
}

// Response
interface LogoutResponse {
  message: string
}

POST /api/auth/refresh

更新 Token

// Request
interface RefreshRequest {
  refreshToken: string
}

// Response
interface RefreshResponse {
  accessToken: string
  refreshToken: string
  expiresIn: number
}

POST /api/auth/verify-email

驗證 Email

// Request
interface VerifyEmailRequest {
  token: string
}

// Response
interface VerifyEmailResponse {
  message: string
  user: User
}

POST /api/auth/forgot-password

忘記密碼

// Request
interface ForgotPasswordRequest {
  email: string
}

// Response
interface ForgotPasswordResponse {
  message: string
}

POST /api/auth/reset-password

重設密碼

// Request
interface ResetPasswordRequest {
  token: string
  newPassword: string
  confirmPassword: string
}

// Response
interface ResetPasswordResponse {
  message: string
}

POST /api/auth/google

Google OAuth

// Request
interface GoogleAuthRequest {
  idToken: string
}

// Response
interface GoogleAuthResponse {
  user: User
  accessToken: string
  refreshToken: string
  isNewUser: boolean
}

🎃 用戶 API

GET /api/users/profile

獲取用戶資料

// Response
interface ProfileResponse {
  user: User
  profile: UserProfile
  stats: UserStats
}

PUT /api/users/profile

更新用戶資料

// Request
interface UpdateProfileRequest {
  username?: string
  displayName?: string
  bio?: string
  avatar?: File
  preferredLanguage?: string
  timezone?: string
}

// Response
interface UpdateProfileResponse {
  user: User
  message: string
}

PUT /api/users/settings

更新用戶設定

// Request
interface UpdateSettingsRequest {
  dailyGoal?: number
  reminderEnabled?: boolean
  reminderTime?: string
  emailNotifications?: boolean
  pushNotifications?: boolean
  theme?: 'light' | 'dark' | 'auto'
  studyMode?: 'flip' | 'quiz' | 'typing'
}

DELETE /api/users/account

刪除帳號

// Request
interface DeleteAccountRequest {
  password: string
  reason?: string
}

// Response
interface DeleteAccountResponse {
  message: string
}

🎓 詞卡 API

GET /api/flashcard-sets

獲取卡組列表

// Query parameters
interface GetSetsQuery {
  page?: number
  limit?: number
  search?: string
  tags?: string[]
  orderBy?: 'created' | 'updated' | 'name' | 'progress'
  order?: 'asc' | 'desc'
}

// Response
interface GetSetsResponse {
  sets: FlashcardSet[]
  pagination: Pagination
}

POST /api/flashcard-sets

創建卡組

// Request
interface CreateSetRequest {
  name: string
  description?: string
  color?: string
  tags?: string[]
  isPublic?: boolean
}

// Response
interface CreateSetResponse {
  set: FlashcardSet
}

GET /api/flashcard-sets/:setId

獲取卡組詳情

// Response
interface GetSetDetailResponse {
  set: FlashcardSet
  cards: Flashcard[]
  stats: SetStats
}

PUT /api/flashcard-sets/:setId

更新卡組

// Request
interface UpdateSetRequest {
  name?: string
  description?: string
  color?: string
  tags?: string[]
  isPublic?: boolean
}

DELETE /api/flashcard-sets/:setId

刪除卡組

// Response
interface DeleteSetResponse {
  message: string
  deletedCount: number
}

GET /api/flashcards

獲取詞卡列表

// Query parameters
interface GetCardsQuery {
  setId?: string
  search?: string
  tags?: string[]
  difficulty?: 'beginner' | 'intermediate' | 'advanced'
  mastered?: boolean
  favorite?: boolean
  dueForReview?: boolean
  page?: number
  limit?: number
}

// Response
interface GetCardsResponse {
  cards: Flashcard[]
  pagination: Pagination
}

POST /api/flashcards

創建詞卡

// Request
interface CreateCardRequest {
  setId: string
  word: string
  translation: string
  partOfSpeech?: string
  pronunciation?: string
  definition?: string
  exampleSentence?: string
  exampleTranslation?: string
  synonyms?: string[]
  tags?: string[]
  difficulty?: 'beginner' | 'intermediate' | 'advanced'
}

// Response
interface CreateCardResponse {
  card: Flashcard
}

PUT /api/flashcards/:cardId

更新詞卡

// Request - same as CreateCardRequest but all fields optional

DELETE /api/flashcards/:cardId

刪除詞卡

POST /api/flashcards/batch

批量操作

// Request
interface BatchOperationRequest {
  operation: 'create' | 'update' | 'delete' | 'move'
  cardIds?: string[]
  data?: any
  targetSetId?: string
}

// Response
interface BatchOperationResponse {
  success: number
  failed: number
  errors?: any[]
}

🤖 AI 生成 API

POST /api/ai/generate

AI 生成詞卡

// Request
interface GenerateRequest {
  mode: 'text' | 'theme'
  input: string // text content or theme name
  difficulty: 'beginner' | 'intermediate' | 'advanced'
  count: number // 5-20
  includeExamples?: boolean
  includeSynonyms?: boolean
}

// Response
interface GenerateResponse {
  cards: GeneratedCard[]
  usage: {
    promptTokens: number
    completionTokens: number
    totalTokens: number
  }
}

interface GeneratedCard {
  word: string
  translation: string
  partOfSpeech: string
  pronunciation: string
  definition: string
  example: string
  exampleTranslation: string
  synonyms: string[]
  difficulty: string
  confidence: number // 0-1
}

POST /api/ai/analyze-text

分析文本難度

// Request
interface AnalyzeTextRequest {
  text: string
}

// Response
interface AnalyzeTextResponse {
  difficulty: 'beginner' | 'intermediate' | 'advanced'
  wordCount: number
  uniqueWords: number
  averageSentenceLength: number
  readabilityScore: number
  suggestedWords: string[]
}

GET /api/ai/quota

查詢 AI 使用額度

// Response
interface QuotaResponse {
  used: number
  limit: number
  resetAt: string
  isPremium: boolean
}

📚 學習 API

GET /api/learning/due

獲取待複習詞卡

// Query parameters
interface GetDueCardsQuery {
  setId?: string
  limit?: number
}

// Response
interface GetDueCardsResponse {
  cards: StudyCard[]
  totalDue: number
}

interface StudyCard extends Flashcard {
  learningRecord: LearningRecord
}

POST /api/learning/review

提交評分

// Request
interface ReviewRequest {
  cardId: string
  rating: 1 | 2 | 3 | 4 | 5
  responseTime: number // milliseconds
  mode: 'flip' | 'quiz' | 'typing'
}

// Response
interface ReviewResponse {
  nextReviewDate: string
  interval: number
  easeFactor: number
  masteryLevel: number
}

GET /api/learning/stats

獲取學習統計

// Query parameters
interface GetStatsQuery {
  period: 'today' | 'week' | 'month' | 'year' | 'all'
  setId?: string
}

// Response
interface StatsResponse {
  cardsReviewed: number
  cardsLearned: number
  cardsMastered: number
  studyTime: number // minutes
  accuracy: number // percentage
  streak: number
  dailyGoalProgress: number
  chart: {
    dates: string[]
    values: number[]
  }
}

POST /api/learning/session/start

開始學習會話

// Request
interface StartSessionRequest {
  mode: 'review' | 'learn' | 'cram'
  setId?: string
}

// Response
interface StartSessionResponse {
  sessionId: string
  cards: StudyCard[]
}

POST /api/learning/session/end

結束學習會話

// Request
interface EndSessionRequest {
  sessionId: string
}

// Response
interface EndSessionResponse {
  duration: number
  cardsStudied: number
  accuracy: number
  xpEarned: number
  achievements: Achievement[]
}

🏆 成就 API

GET /api/achievements

獲取成就列表

// Response
interface GetAchievementsResponse {
  unlocked: Achievement[]
  locked: Achievement[]
  recent: Achievement[]
}

POST /api/achievements/:achievementId/claim

領取成就獎勵

// Response
interface ClaimAchievementResponse {
  xpEarned: number
  totalXp: number
  newLevel?: number
}

🔔 通知 API

GET /api/notifications

獲取通知

// Query parameters
interface GetNotificationsQuery {
  unreadOnly?: boolean
  type?: string
  page?: number
  limit?: number
}

// Response
interface GetNotificationsResponse {
  notifications: Notification[]
  unreadCount: number
  pagination: Pagination
}

PUT /api/notifications/:notificationId/read

標記已讀

PUT /api/notifications/read-all

全部標記已讀

DELETE /api/notifications/:notificationId

刪除通知

📁 匯出/匯入 API

GET /api/export/cards

匯出詞卡

// Query parameters
interface ExportQuery {
  format: 'csv' | 'json' | 'anki'
  setId?: string
  cardIds?: string[]
}

// Response: File download

POST /api/import/cards

匯入詞卡

// Request: FormData with file
interface ImportRequest {
  file: File
  setId: string
  format: 'csv' | 'json' | 'anki'
  duplicateStrategy: 'skip' | 'replace' | 'create'
}

// Response
interface ImportResponse {
  imported: number
  skipped: number
  errors: any[]
}

🔒 錯誤碼規範

enum ErrorCode {
  // Authentication
  AUTH_INVALID_TOKEN = 'AUTH001',
  AUTH_TOKEN_EXPIRED = 'AUTH002',
  AUTH_UNAUTHORIZED = 'AUTH003',
  
  // Validation
  VALIDATION_ERROR = 'VAL001',
  INVALID_INPUT = 'VAL002',
  
  // Resource
  NOT_FOUND = 'RES001',
  ALREADY_EXISTS = 'RES002',
  
  // Rate Limit
  RATE_LIMIT_EXCEEDED = 'RATE001',
  QUOTA_EXCEEDED = 'RATE002',
  
  // Server
  INTERNAL_ERROR = 'SRV001',
  SERVICE_UNAVAILABLE = 'SRV002',
}

📊 Rate Limiting

Endpoint Free User Premium User
AI Generate 50/day Unlimited
API Calls 1000/hour 10000/hour
File Upload 10MB 50MB
Export 5/day Unlimited

🔧 Webhooks

可用 Webhooks

  1. user.created - 新用戶註冊
  2. user.deleted - 用戶刪除
  3. subscription.created - 訂閱創建
  4. subscription.updated - 訂閱更新
  5. achievement.unlocked - 成就解鎖

Webhook Payload

interface WebhookPayload {
  event: string
  timestamp: string
  data: any
  signature: string
}