openapi: 3.1.0
info:
  title: NexTrend Lab · 公開 API
  version: 1.0.0
  description: |
    這份文件描述客戶可直接串接的公開 API。
    - 所有 `/api/v1/{provider}/{endpoint}` 皆使用 `X-Api-Key` 做鑑權。
    - 建議由伺服器端安全保存 API Key，避免在前端明文暴露。
servers:
  - url: https://your-domain.com
    description: Production
  - url: http://localhost:3000
    description: Local development

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
      required:
        - error
    MeResponse:
      type: object
      properties:
        email:
          type: string
        apiKey:
          type: string
          description: 原始 API Key
        apiKeyMasked:
          type: string
        balance:
          type: integer
        todayRequestCount:
          type: integer
        todayUsedUnits:
          type: integer
    BillingOrder:
      type: object
      properties:
        id:
          type: integer
        provider:
          type: string
        amount:
          type: integer
        credits:
          type: integer
        status:
          type: string
        createdAt:
          type: string
          format: date-time
    TopupRequest:
      type: object
      properties:
        credits:
          type: integer
          minimum: 1
        provider:
          type: string
          description: airwallex
      required:
        - credits
    TopupResponse:
      type: object
      properties:
        success:
          type: boolean
        orderId:
          type: integer
        newBalance:
          type: integer

paths:
  /api/v1/{provider}/{endpoint}:
    get:
      summary: 統一電商／社交資料查詢
      description: |
        統一入口，會依 provider / endpoint 與後端設定進行最佳路由，
        並套用錢包扣點、速率限制與快取。
      security:
        - ApiKeyAuth: []
      parameters:
        - name: provider
          in: path
          required: true
          description: 平台代號，例如 taobao、jd、douyin、tiktok、xiaohongshu、weibo 等。
          schema:
            type: string
        - name: endpoint
          in: path
          required: true
          description: endpoint key，例如 item-detail-v9、product-detail-v2、note-search-v2。
          schema:
            type: string
      responses:
        '200':
          description: 查詢成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    description: 依 endpoint 轉換後的資料
                  fromCache:
                    type: boolean
                  remainingBalance:
                    type: integer
        '401':
          description: API key 缺失或無效
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: 餘額不足
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: 每日上限或每分鐘 rate limit 超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/auth/register:
    post:
      summary: 註冊新帳號
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
                  minLength: 8
              required:
                - email
                - password
      responses:
        '200':
          description: 註冊成功，回傳 API Key 與初始餘額
          content:
            application/json:
              schema:
                type: object
                properties:
                  email:
                    type: string
                  apiKey:
                    type: string
                  balance:
                    type: integer
        '400':
          description: Email 已存在或密碼太短
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/auth/login:
    post:
      summary: 登入帳戶
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
              required:
                - email
                - password
      responses:
        '200':
          description: 登入成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  email:
                    type: string
                  apiKey:
                    type: string
                  balance:
                    type: integer
        '401':
          description: 帳密錯誤
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/auth/logout:
    post:
      summary: 登出帳戶
      responses:
        '200':
          description: 成功

  /api/auth/me:
    get:
      summary: 取得目前登入使用者資訊
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeResponse'
        '401':
          description: 未登入
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/auth/forgot-password:
    post:
      summary: 申請重設密碼
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
              required:
                - email
      responses:
        '200':
          description: 成功，若該信箱存在會寄送重設連結

  /api/auth/reset-password:
    post:
      summary: 使用 token 重設密碼
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                newPassword:
                  type: string
                  minLength: 8
              required:
                - token
                - newPassword
      responses:
        '200':
          description: 密碼已更新
        '400':
          description: token 無效或已過期
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/billing/topup:
    post:
      summary: 儲值 credits（需登入）
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TopupRequest'
      responses:
        '200':
          description: 儲值成功或建立 pending 訂單
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopupResponse'
        '400':
          description: 參數錯誤或找不到錢包
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /api/billing/orders:
    get:
      summary: 取得最近 50 筆儲值訂單
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/BillingOrder'

