{
  "openapi": "3.0.3",
  "info": {
    "title": "VetPro 獸醫百科 API",
    "description": "VetPro Veterinary Encyclopedia API — 提供 2,500+ 疾病、886 種藥物、鑑別診斷、文獻查詢等獸醫臨床知識。\n\nAPI 設計用於 EMR 系統的 AI Agent 整合，支援 MCP (Model Context Protocol) Server。\n\n**授權方式**：在 HTTP header 加入 `x-api-key`\n\n**免驗證端點**：`/api/health`、`/api/v1/meta`",
    "version": "1.0.0",
    "license": {
      "name": "VetPro 內容條款：僅供閱讀與臨床參考，不得再散布、商用或訓練模型",
      "url": "https://vetpro-nine.vercel.app/terms"
    },
    "contact": {
      "name": "VetPro Team",
      "url": "https://vetpro-nine.vercel.app"
    }
  },
  "servers": [
    {
      "url": "https://vetpro-nine.vercel.app",
      "description": "Production"
    },
    {
      "url": "http://localhost:3000",
      "description": "Local development"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "x-tagGroups": [
    {
      "name": "Public API",
      "tags": ["System", "Search", "Diseases", "DDX", "Drugs", "References"]
    },
    {
      "name": "Admin API",
      "tags": ["Admin"]
    }
  ],
  "paths": {
    "/api/v1/meta": {
      "get": {
        "operationId": "getMeta",
        "summary": "API 元資料 / API Metadata",
        "description": "取得 API 版本、資料統計、支援的物種與本體論等元資訊。此端點免驗證。",
        "tags": [
          "System"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "API metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "系統健康檢查 / Health Check",
        "description": "驗證資料庫可讀性、核心資料表存在、FTS 索引可查詢。此端點免驗證。",
        "tags": [
          "System"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "System healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "description": "System unhealthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "operationId": "globalSearch",
        "summary": "全文搜尋 / Global Search",
        "description": "跨疾病與藥物的全文搜尋（FTS5），支援中英文。回傳最多 15 筆疾病 + 5 筆藥物。",
        "tags": [
          "Search"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "搜尋關鍵字（中文或英文）",
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "example": "pancreatitis"
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SearchResult"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/diseases": {
      "get": {
        "operationId": "listDiseases",
        "summary": "疾病列表 / Disease List",
        "description": "取得疾病列表，支援分頁。可依 bodySystem 和 species 篩選。預設每頁 100 筆，最多 200 筆。",
        "tags": [
          "Diseases"
        ],
        "parameters": [
          {
            "name": "bodySystem",
            "in": "query",
            "description": "依體系篩選（如 cardiac, renal, neurology）",
            "schema": {
              "type": "string"
            },
            "example": "cardiac"
          },
          {
            "name": "species",
            "in": "query",
            "description": "依物種篩選",
            "schema": {
              "type": "string",
              "enum": [
                "dog",
                "cat",
                "rabbit",
                "ferret",
                "guinea pig",
                "hamster",
                "chinchilla",
                "rat",
                "bird"
              ]
            },
            "example": "dog"
          },
          {
            "name": "page",
            "in": "query",
            "description": "頁碼（從 1 開始）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "每頁數量（1-200，預設 100）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated disease list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DiseaseSummary"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "totalPages": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/diseases/{slug}": {
      "get": {
        "operationId": "getDiseaseDetail",
        "summary": "疾病詳情 / Disease Detail",
        "description": "取得單一疾病的完整臨床資料，包含病因、病理、診斷、治療、文獻等。",
        "tags": [
          "Diseases"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "疾病的 URL slug",
            "schema": {
              "type": "string"
            },
            "example": "pancreatitis"
          }
        ],
        "responses": {
          "200": {
            "description": "Disease details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiseaseDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ddx": {
      "get": {
        "operationId": "differentialDiagnosis",
        "summary": "鑑別診斷 / Differential Diagnosis",
        "description": "根據臨床症狀和實驗室數據進行鑑別診斷。計分 v2（預設）：每個輸入依特異性加權（ln(N/n)，常見症狀權重低），分數 = 100 ×（疾病能解釋的加權表現比例 − 排除症狀扣分 + 物種盛行率先驗）；每筆結果附 evidence 與 qualityGrade。scoring=v1 取得 2026-09-25 前的舊公式（2×症狀命中數² + 1.5×覆蓋率 + 2.5×Lab 命中數²，排除症狀直接移除疾病）。症狀 ID 可用舊的重複寫法（如 icterus），會換成 canonical ID 並在 warnings 說明。回傳前 50 名候選疾病。",
        "tags": [
          "DDX"
        ],
        "parameters": [
          {
            "name": "symptoms",
            "in": "query",
            "description": "逗號分隔的症狀 ID（至少需要 symptoms 或 labs 之一，最多 50 個）",
            "schema": {
              "type": "string",
              "maxLength": 2000
            },
            "example": "vomiting,diarrhoea,anorexia"
          },
          {
            "name": "labs",
            "in": "query",
            "description": "逗號分隔的實驗室異常 ID（最多 30 個）",
            "schema": {
              "type": "string",
              "maxLength": 1500
            },
            "example": "azotaemia,hyperkalaemia"
          },
          {
            "name": "exclude",
            "in": "query",
            "description": "逗號分隔的排除症狀 ID（最多 50 個）。v2：與其相關的疾病依連結頻率扣分；v1：直接移除",
            "schema": {
              "type": "string",
              "maxLength": 2000
            },
            "example": "seizures,jaundice"
          },
          {
            "name": "species",
            "in": "query",
            "description": "物種篩選",
            "schema": {
              "type": "string",
              "enum": [
                "dog",
                "cat",
                "both"
              ],
              "default": "both"
            },
            "example": "dog"
          },
          {
            "name": "scoring",
            "in": "query",
            "description": "計分版本：v2（預設）或 v1（舊公式，過渡期保留）",
            "schema": {
              "type": "string",
              "enum": [
                "v2",
                "v1"
              ],
              "default": "v2"
            },
            "example": "v2"
          },
          {
            "name": "minGrade",
            "in": "query",
            "description": "只回內容稽核等級不低於此的記錄：Gold；Silver（Gold + Silver）；Bronze（排除 Failed）。預設全部列出（內容稽核等級只在同分時決勝，不影響分數）",
            "schema": {
              "type": "string",
              "enum": [
                "Gold",
                "Silver",
                "Bronze"
              ]
            },
            "example": "Silver"
          }
        ],
        "responses": {
          "200": {
            "description": "DDX results sorted by composite score",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DdxResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/drugs": {
      "get": {
        "operationId": "searchDrugs",
        "summary": "藥物搜尋 / Drug Search",
        "description": "搜尋或篩選藥物。支援 FTS 全文搜尋或 classification/species 篩選。",
        "tags": [
          "Drugs"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "搜尋關鍵字（藥名、商品名、別名）",
            "schema": {
              "type": "string"
            },
            "example": "amoxicillin"
          },
          {
            "name": "classification",
            "in": "query",
            "description": "依藥物分類篩選",
            "schema": {
              "type": "string"
            },
            "example": "Antibacterial"
          },
          {
            "name": "species",
            "in": "query",
            "description": "依物種篩選",
            "schema": {
              "type": "string"
            },
            "example": "dog"
          },
          {
            "name": "page",
            "in": "query",
            "description": "頁碼（從 1 開始，僅篩選模式有效）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "每頁數量（1-200，預設 100，僅篩選模式有效）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Drug search results (filter mode includes pagination)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrugSearchResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/drugs/{slug}": {
      "get": {
        "operationId": "getDrugDetail",
        "summary": "藥物詳情 / Drug Detail",
        "description": "取得單一藥物的完整資料，包含劑量、交互作用、藥理學等。",
        "tags": [
          "Drugs"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "藥物的 URL slug",
            "schema": {
              "type": "string"
            },
            "example": "amoxicillin"
          }
        ],
        "responses": {
          "200": {
            "description": "Drug details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrugDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/drugs/interactions": {
      "get": {
        "operationId": "checkDrugInteractions",
        "summary": "藥物交互作用檢查 / Drug Interaction Checker",
        "description": "檢查 2-10 種藥物之間的已知交互作用。支援 drug-level 和 class-level 匹配。",
        "tags": [
          "Drugs"
        ],
        "parameters": [
          {
            "name": "drugs",
            "in": "query",
            "required": true,
            "description": "逗號分隔的藥物 ID（格式 D####，2-10 個）",
            "schema": {
              "type": "string"
            },
            "example": "D0001,D0034,D0089"
          }
        ],
        "responses": {
          "200": {
            "description": "Interaction check results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InteractionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/symptoms": {
      "get": {
        "operationId": "listSymptoms",
        "summary": "症狀列表 / Symptom List",
        "description": "取得所有臨床症狀（含鑑別診斷數量）。支援 FTS 搜尋。",
        "tags": [
          "DDX"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "搜尋關鍵字",
            "schema": {
              "type": "string"
            },
            "example": "vomiting"
          }
        ],
        "responses": {
          "200": {
            "description": "Symptom list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Symptom"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/lab-findings": {
      "get": {
        "operationId": "listLabFindings",
        "summary": "實驗室指標列表 / Lab Findings List",
        "description": "取得所有實驗室異常指標（含關聯疾病數量）。支援搜尋。",
        "tags": [
          "DDX"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "搜尋關鍵字",
            "schema": {
              "type": "string"
            },
            "example": "azotaemia"
          }
        ],
        "responses": {
          "200": {
            "description": "Lab findings list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LabFinding"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/references": {
      "get": {
        "operationId": "listReferences",
        "summary": "文獻查詢 / Reference Library",
        "description": "分頁查詢獸醫文獻庫。支援 source type、組織、疾病、Open Access、年份等多重篩選。",
        "tags": [
          "References"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "頁碼（從 1 開始）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "每頁數量（1-100）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "sourceType",
            "in": "query",
            "description": "文獻類型篩選",
            "schema": {
              "type": "string",
              "enum": [
                "pubmed",
                "guideline",
                "consensus"
              ]
            }
          },
          {
            "name": "sourceOrg",
            "in": "query",
            "description": "來源組織篩選",
            "schema": {
              "type": "string"
            },
            "example": "ACVIM"
          },
          {
            "name": "diseaseSlug",
            "in": "query",
            "description": "依關聯疾病篩選",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "openAccess",
            "in": "query",
            "description": "僅顯示開放取用文獻（1=是）",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "搜尋標題",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "year",
            "in": "query",
            "description": "精確年份篩選",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "排序方式",
            "schema": {
              "type": "string",
              "enum": [
                "recent",
                "year_desc",
                "year_asc"
              ],
              "default": "recent"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated reference list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferenceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/admin/keys": {
      "get": {
        "operationId": "listAdminKeys",
        "summary": "列出 API Keys / List API Keys",
        "description": "列出所有已建立的 API keys（金鑰以遮罩方式顯示，不會暴露完整 key）。回傳 key ID、名稱、scope、建立時間、最後使用時間。",
        "tags": ["Admin"],
        "security": [{ "AdminKeyAuth": [] }],
        "responses": {
          "200": {
            "description": "API key list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminKeyListResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createAdminKey",
        "summary": "建立 API Key / Create API Key",
        "description": "建立新的 API key。key 格式為 `vp_` + 32 字元隨機字串。完整 key 僅在此回應中回傳一次，之後無法再取得。ID 為 SHA-256 hash 前 16 字元。",
        "tags": ["Admin"],
        "security": [{ "AdminKeyAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKeyRequest"
              },
              "example": {
                "name": "EMR Client A",
                "scope": ["*"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created (full key returned ONLY in this response)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminKeyCreatedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/admin/keys/{keyId}": {
      "delete": {
        "operationId": "revokeAdminKey",
        "summary": "撤銷 API Key / Revoke API Key",
        "description": "撤銷（刪除）指定的 API key。撤銷後該 key 立即失效（5 秒內 cache 過期後生效）。同時清除相關 metadata 和 usage 計數器。",
        "tags": ["Admin"],
        "security": [{ "AdminKeyAuth": [] }],
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "description": "API key ID（SHA-256 hash 前 16 字元）",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$",
              "minLength": 16,
              "maxLength": 16
            },
            "example": "a1b2c3d4e5f6a7b8"
          }
        ],
        "responses": {
          "200": {
            "description": "Key revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminKeyDeletedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "rotateAdminKey",
        "summary": "輪換 API Key / Rotate API Key",
        "description": "為指定的 API key 進行輪換（rotation）。生成新 key，舊 key 保留 24 小時的 grace period，期間新舊 key 皆有效。完整新 key 僅在此回應中回傳一次。",
        "tags": ["Admin"],
        "security": [{ "AdminKeyAuth": [] }],
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "description": "要輪換的 API key ID（SHA-256 hash 前 16 字元）",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$",
              "minLength": 16,
              "maxLength": 16
            },
            "example": "a1b2c3d4e5f6a7b8"
          }
        ],
        "responses": {
          "200": {
            "description": "Key rotated (new full key returned ONLY in this response)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminKeyRotatedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/admin/usage": {
      "get": {
        "operationId": "getAdminUsage",
        "summary": "使用統計 / Usage Statistics",
        "description": "查看 API 使用統計。可指定天數範圍和特定 key。回傳每個 key 的總呼叫數、每日明細、最熱門端點。",
        "tags": ["Admin"],
        "security": [{ "AdminKeyAuth": [] }],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "description": "統計天數（1-90，預設 7）",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 90,
              "default": 7
            }
          },
          {
            "name": "key",
            "in": "query",
            "description": "指定 key hash ID（可選，不指定則回傳所有 key）",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage statistics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUsageResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API 金鑰。透過 x-api-key header 傳遞。"
      },
      "AdminKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-admin-key",
        "description": "管理員金鑰。用於 Admin API 端點，透過 x-admin-key header 傳遞。設定方式：env var VETPRO_ADMIN_KEY。"
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request parameters",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "BAD_REQUEST",
                "message": "At least one of 'symptoms' or 'labs' query parameter is required"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "UNAUTHORIZED",
                "message": "Invalid or missing API key. Provide a valid 'x-api-key' header."
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "NOT_FOUND",
                "message": "Resource not found"
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "RATE_LIMITED",
                "message": "Rate limit exceeded. Max 100 requests per minute."
              },
              "meta": {
                "retryAfterMs": 15000
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Invalid or missing admin key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "FORBIDDEN",
                "message": "Invalid admin key."
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Redis not configured (Admin API requires Upstash Redis)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "SERVICE_UNAVAILABLE",
                "message": "Redis not configured. Admin API requires Upstash Redis."
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "apiVersion": "1.0",
              "error": {
                "code": "INTERNAL_ERROR",
                "message": "An unexpected error occurred"
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "apiVersion",
          "error"
        ],
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "機器可讀的錯誤代碼",
                "example": "BAD_REQUEST"
              },
              "message": {
                "type": "string",
                "description": "人類可讀的錯誤描述",
                "example": "Missing required parameter"
              }
            }
          }
        }
      },
      "MetaResponse": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "dataVersion": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "engineVersion": {
            "$ref": "#/components/schemas/DdxEngineVersion"
          },
          "knowledgeHash": {
            "$ref": "#/components/schemas/DdxKnowledgeHash"
          },
          "buildSha": {
            "$ref": "#/components/schemas/DdxBuildSha"
          },
          "statistics": {
            "type": "object",
            "properties": {
              "diseases": {
                "type": "integer",
                "example": 2510
              },
              "drugs": {
                "type": "integer",
                "example": 886
              },
              "symptoms": {
                "type": "integer",
                "example": 214,
                "description": "可選的症狀 ID 數（不含別名）"
              },
              "symptomAliases": {
                "type": "integer",
                "example": 22,
                "description": "被對到原 ID 的重複症狀 ID 數（data/ddx/symptom-aliases.json）"
              },
              "labFindings": {
                "type": "integer",
                "example": 67,
                "description": "可選的檢驗異常 ID 數（不含別名）"
              },
              "labAliases": {
                "type": "integer",
                "example": 6,
                "description": "被對到原 ID 的重複檢驗 ID 數（data/ddx/lab-aliases.json）"
              },
              "references": {
                "type": "integer",
                "example": 6844
              },
              "drugInteractions": {
                "type": "integer"
              },
              "symptomDiseaseLinks": {
                "type": "integer"
              },
              "labDiseaseLinks": {
                "type": "integer"
              },
              "ontologyMappings": {
                "type": "integer"
              }
            }
          },
          "supportedSpecies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "bodySystems": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "drugClassifications": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ontologySources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "referenceSourceTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "endpoints": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "auth": {
            "type": "object",
            "properties": {
              "method": {
                "type": "string"
              },
              "header": {
                "type": "string"
              },
              "rateLimit": {
                "type": "string"
              },
              "publicEndpoints": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "license": {
            "type": "string",
            "example": "VetPro 內容條款：僅供閱讀與臨床參考，不得再散布、商用或訓練模型"
          },
          "mcpPackage": {
            "type": "string",
            "example": "@vetpro/mcp-server"
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "meta": {
            "type": "object",
            "properties": {
              "requestId": {
                "type": "string",
                "format": "uuid"
              },
              "responseTimeMs": {
                "type": "integer"
              }
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "error"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "responseTimeMs": {
            "type": "integer"
          },
          "database": {
            "type": "object",
            "properties": {
              "diseases": {
                "type": "integer"
              },
              "drugs": {
                "type": "integer"
              },
              "references": {
                "type": "integer"
              },
              "interactions": {
                "type": "integer"
              }
            }
          },
          "fts": {
            "type": "object",
            "properties": {
              "diseaseFts": {
                "type": "string"
              },
              "drugFts": {
                "type": "string"
              }
            }
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "disease",
              "drug"
            ]
          },
          "slug": {
            "type": "string"
          },
          "nameEn": {
            "type": "string"
          },
          "nameZh": {
            "type": "string",
            "nullable": true
          },
          "bodySystem": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "DiseaseSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "nameEn": {
            "type": "string"
          },
          "nameZh": {
            "type": "string",
            "nullable": true
          },
          "bodySystem": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "species": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "DiseaseDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "nameEn": {
            "type": "string"
          },
          "nameZh": {
            "type": "string",
            "nullable": true
          },
          "bodySystem": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "etiology": {
            "description": "Parsed JSON — 結構化病因資料",
            "nullable": true
          },
          "pathophysiology": {
            "type": "string",
            "nullable": true
          },
          "clinicalSigns": {
            "description": "Parsed JSON — 結構化臨床症狀",
            "nullable": true
          },
          "diagnosis": {
            "description": "Parsed JSON — 結構化診斷資料",
            "nullable": true
          },
          "treatment": {
            "description": "Parsed JSON — 結構化治療方案",
            "nullable": true
          },
          "prognosis": {
            "type": "string",
            "nullable": true
          },
          "stagingSystem": {
            "description": "Parsed JSON — 分期系統",
            "nullable": true
          },
          "emergencyNotes": {
            "type": "string",
            "nullable": true
          },
          "diagnosticAlgorithm": {
            "description": "Parsed JSON — 診斷流程",
            "nullable": true
          },
          "clinicalPearls": {
            "description": "Parsed JSON — 臨床要點",
            "nullable": true
          },
          "monitoringItems": {
            "description": "Parsed JSON — 監測項目",
            "nullable": true
          },
          "ddxSource": {
            "type": "string",
            "nullable": true
          },
          "aliases": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "alias": {
                  "type": "string"
                },
                "language": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "species": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "speciesCommon": {
                  "type": "string"
                },
                "speciesScientific": {
                  "type": "string",
                  "nullable": true
                },
                "prevalence": {
                  "type": "string",
                  "nullable": true
                },
                "notes": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "references": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DiseaseReference"
            }
          },
          "ontologyMappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OntologyMapping"
            }
          }
        }
      },
      "DdxEngineVersion": {
        "type": "string",
        "example": "2.0.0",
        "description": "鑑別引擎版本：計分語義改變時遞增。分數是未校正的支持分數，不是機率"
      },
      "DdxKnowledgeHash": {
        "type": "string",
        "nullable": true,
        "pattern": "^[0-9a-f]{64}$",
        "description": "引擎讀取的全部鑑別知識（疾病、症狀、檢驗、連結、物種、三份 data/ddx JSON 與計分參數）的 SHA-256；與資料列順序、建置時產生的 ID 無關。資料庫早於此欄位時為 null"
      },
      "DdxBuildSha": {
        "type": "string",
        "nullable": true,
        "description": "部署的 git commit SHA；非 Vercel 環境為 null"
      },
      "DdxResponse": {
        "type": "object",
        "properties": {
          "engineVersion": {
            "$ref": "#/components/schemas/DdxEngineVersion"
          },
          "knowledgeHash": {
            "$ref": "#/components/schemas/DdxKnowledgeHash"
          },
          "buildSha": {
            "$ref": "#/components/schemas/DdxBuildSha"
          },
          "scoring": {
            "type": "string",
            "enum": [
              "v2",
              "v1"
            ],
            "description": "本次使用的計分版本"
          },
          "query": {
            "type": "object",
            "properties": {
              "symptoms": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "labs": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "exclude": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "species": {
                "type": "string"
              },
              "minGrade": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "Gold",
                  "Silver",
                  "Bronze"
                ],
                "description": "本次套用的稽核等級門檻；未指定為 null"
              }
            }
          },
          "resultCount": {
            "type": "integer"
          },
          "totalInputs": {
            "type": "integer"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "未知 ID、物種退回 both、alias 換成 canonical ID、尚無疾病連結的輸入等說明"
          },
          "redFlags": {
            "type": "object",
            "description": "急診警示：輸入中的急診型症狀，以及前 5 名內分診為急診的疾病（最多 3 個）",
            "properties": {
              "level": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "stat"
                ],
                "description": "只有輸入包含急診型症狀時為 stat；只有急診分級的鑑別、沒有急診型症狀時為 null（emergencyDifferentials 仍會列出）"
              },
              "triggered": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "zh": {
                      "type": "string"
                    },
                    "why": {
                      "type": "string",
                      "description": "先做什麼（不含劑量）"
                    }
                  }
                }
              },
              "emergencyDifferentials": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "nameEn": {
                      "type": "string"
                    },
                    "nameZh": {
                      "type": "string",
                      "nullable": true
                    },
                    "urgencyScore": {
                      "type": "integer"
                    },
                    "compositeScore": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "disclaimer": {
            "type": "string",
            "description": "臨床決策支援、非診斷的聲明（中英）"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DdxResult"
            }
          }
        }
      },
      "DdxResult": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "nameEn": {
            "type": "string"
          },
          "nameZh": {
            "type": "string",
            "nullable": true
          },
          "bodySystem": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "matchCount": {
            "type": "integer",
            "description": "匹配的症狀數"
          },
          "labMatchCount": {
            "type": "integer",
            "description": "匹配的 lab 數"
          },
          "totalSymptoms": {
            "type": "integer"
          },
          "totalLabs": {
            "type": "integer"
          },
          "matchedSymptoms": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "matchedLabs": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "compositeScore": {
            "type": "number",
            "description": "v2：100 ×（explained − 排除症狀扣分 + prior + qualityPrior），約 0–100；v1：2×症狀命中數² + 1.5×覆蓋率 + 0.25×頻率加成 + 2.5×Lab 命中數²"
          },
          "urgencyScore": {
            "type": "integer",
            "minimum": 1,
            "maximum": 4,
            "description": "v2：以疾病本身的分診等級為準（沒有分診等級的少數記錄才看連結急迫度）；v1：只看連結急迫度（多數為預設的 semi-urgent）"
          },
          "frequencyScore": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3
          },
          "species": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ddxSource": {
            "type": "string",
            "nullable": true,
            "description": "book | auto-generated | book-only"
          },
          "qualityGrade": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Gold",
              "Silver",
              "Bronze",
              "Failed"
            ],
            "description": "疾病記錄通過內容稽核的程度；Bronze／Failed 的內容尚未完成覆核，v2 只在同分時以等級決勝（2026-10-15 起不再以 qualityPrior 調整分數）。同一疾病的重複記錄與品種專屬記錄（data/ddx/duplicate-records.json、breed-variants.json）已折進本尊，不會單獨出現在結果中"
          },
          "explained": {
            "type": "number",
            "description": "v2：此疾病能解釋的加權表現比例（0–1）"
          },
          "prior": {
            "type": "number",
            "description": "v2：物種盛行率先驗（common +0.06、rare −0.04 …）"
          },
          "qualityPrior": {
            "type": "number",
            "description": "v2：內容稽核先驗。2026-10-15 起為 0（內容稽核等級不影響分數，只在同分時決勝）；之前是 Gold +0.06、Silver +0.03、Bronze 0、Failed −0.08"
          },
          "coverage": {
            "type": "number",
            "description": "v2：病人表現佔此疾病自身症狀（依頻率加權）的比例（0–1）；不計入分數，只在同分時決定先後"
          },
          "evidence": {
            "type": "array",
            "description": "v2：此疾病連結到的輸入症狀／檢驗",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "symptom",
                    "lab"
                  ]
                },
                "frequency": {
                  "type": "string",
                  "description": "common | uncommon | rare"
                },
                "weight": {
                  "type": "number",
                  "description": "特異性 × 頻率權重"
                },
                "curated": {
                  "type": "boolean",
                  "description": "此連結帶有來自書籍萃取的說明（true），或為自動產生（false）"
                }
              }
            }
          },
          "triageLevel": {
            "type": "string",
            "nullable": true,
            "enum": [
              "emergency",
              "urgent",
              "semi-urgent",
              "routine"
            ],
            "description": "v2：疾病本身的分診等級；urgencyScore 以它為準（急診 4、緊急 3、半緊急 2、非緊急 1）"
          },
          "contraEvidence": {
            "type": "array",
            "description": "v2：此疾病連結到的排除症狀（每一項都扣了分）",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "frequency": {
                  "type": "string"
                }
              }
            }
          },
          "primaryTests": {
            "type": "array",
            "description": "v2：這筆記錄自己的主要檢查名稱（最多 4 項）；只有通用套版清單的記錄回空陣列",
            "items": {
              "type": "string"
            }
          },
          "differentials": {
            "type": "array",
            "description": "v2：這筆記錄自己的鑑別清單（最多 5 項）；名稱對得上站內疾病記錄時附 slug",
            "items": {
              "type": "object",
              "properties": {
                "nameEn": {
                  "type": "string",
                  "nullable": true
                },
                "nameZh": {
                  "type": "string",
                  "nullable": true
                },
                "slug": {
                  "type": "string",
                  "nullable": true,
                  "description": "對應的疾病記錄；對不上時為 null"
                },
                "keyDifference": {
                  "type": "string",
                  "description": "記錄有寫「如何區分」時才出現"
                }
              }
            }
          },
          "breedVariants": {
            "type": "array",
            "description": "v2：折進這筆結果的品種專屬記錄（data/ddx/breed-variants.json），只列查詢物種的記錄",
            "items": {
              "type": "object",
              "properties": {
                "slug": {
                  "type": "string"
                },
                "nameEn": {
                  "type": "string"
                },
                "nameZh": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          }
        }
      },
      "DrugSearchResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "object",
            "description": "回傳查詢參數，依搜尋方式不同：{ q } 或 { classification, species }",
            "additionalProperties": {
              "type": "string",
              "nullable": true
            }
          },
          "total": {
            "type": "integer"
          },
          "drugs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DrugSummary"
            }
          },
          "pagination": {
            "type": "object",
            "nullable": true,
            "description": "僅篩選模式回傳（FTS 搜尋模式不含此欄位）",
            "properties": {
              "page": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              },
              "totalPages": {
                "type": "integer"
              }
            }
          }
        }
      },
      "DrugSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "nameEn": {
            "type": "string"
          },
          "nameZh": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string"
          },
          "formulation": {
            "type": "string",
            "nullable": true
          },
          "supportedSpecies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "DrugDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "nameEn": {
            "type": "string"
          },
          "nameZh": {
            "type": "string",
            "nullable": true
          },
          "tradeNames": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string"
          },
          "formulation": {
            "type": "string",
            "nullable": true
          },
          "pharmacology": {
            "description": "Parsed JSON — 藥理學結構化資料",
            "nullable": true
          },
          "pharmacokinetics": {
            "description": "Parsed JSON — 藥物動力學結構化資料",
            "nullable": true
          },
          "structuredAdverseEffects": {
            "description": "Parsed JSON — 結構化不良反應",
            "nullable": true
          },
          "supportedSpecies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "metadata": {
            "description": "Parsed JSON — 額外元資料",
            "nullable": true
          },
          "dosages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dosage"
            }
          },
          "interactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DrugInteractionDetail"
            }
          },
          "relatedDiseases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DrugRelatedDisease"
            }
          }
        }
      },
      "Dosage": {
        "type": "object",
        "properties": {
          "species": {
            "type": "string"
          },
          "dosageText": {
            "type": "string",
            "nullable": true,
            "description": "文字劑量。自 2026-09-27 起一律為 null：劑量數字取自 DRUGAPI，原書劑量文字只在建置時用來交叉核對數字，不對外提供。核對結果見 structuredDosage._review.text / textReason"
          },
          "structuredDosage": {
            "description": "Parsed JSON — 結構化劑量資料（自 2026-09-29 起不含任何劑量數字：VetPro 改依 DRUGAPI 對外內容，DRUGAPI 目前不提供可執行劑量；只保留禁忌旗標、警語與 _review）。_review 為可信度判定：provenance（auto-generated / generic-fallback 表示 standard 是依藥物分類套用的預設值，不是本藥劑量，請勿使用；plumbs-validated / extracted）、text（verified / unverified / hidden / no-dose / none）、textReason、calculator（ok / blocked）、calculatorReason、structuredRejected（人工核對判定 standard 有誤的原因；有值時請勿使用 standard）、textConflict（本藥文字劑量與 standard 互相矛盾）、entries（standard 以外各適應症劑量的交叉核對結果，鍵同劑量項目，例如 loading、indications.xxx）。只有 calculator = ok 的劑量經過原書劑量文字交叉核對",
            "nullable": true
          }
        }
      },
      "Interaction": {
        "type": "object",
        "properties": {
          "drugA": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              }
            }
          },
          "drugB": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "nameEn": {
                "type": "string"
              }
            }
          },
          "severity": {
            "type": "string",
            "enum": [
              "high",
              "moderate",
              "low"
            ]
          },
          "mechanism": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "InteractionResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "object"
          },
          "interactionCount": {
            "type": "integer"
          },
          "interactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Interaction"
            }
          }
        }
      },
      "Symptom": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "zhName": {
            "type": "string"
          },
          "enName": {
            "type": "string"
          },
          "section": {
            "type": "string",
            "nullable": true
          },
          "sectionName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "differentialCount": {
            "type": "integer"
          }
        }
      },
      "LabFinding": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "zhName": {
            "type": "string"
          },
          "enName": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "diseaseCount": {
            "type": "integer"
          }
        }
      },
      "Reference": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "pmid": {
            "type": "string",
            "nullable": true
          },
          "doi": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string"
          },
          "authors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "Parsed JSON array of author names"
          },
          "journal": {
            "type": "string",
            "nullable": true
          },
          "year": {
            "type": "integer",
            "nullable": true
          },
          "sourceType": {
            "type": "string",
            "nullable": true
          },
          "sourceOrg": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "isOpenAccess": {
            "type": "boolean"
          }
        }
      },
      "ReferenceResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "pmid": {
                  "type": "string",
                  "nullable": true
                },
                "doi": {
                  "type": "string",
                  "nullable": true
                },
                "title": {
                  "type": "string"
                },
                "authors": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "nullable": true
                },
                "journal": {
                  "type": "string",
                  "nullable": true
                },
                "year": {
                  "type": "integer",
                  "nullable": true
                },
                "sourceType": {
                  "type": "string",
                  "nullable": true
                },
                "sourceOrg": {
                  "type": "string",
                  "nullable": true
                },
                "url": {
                  "type": "string",
                  "nullable": true
                },
                "isOpenAccess": {
                  "type": "boolean"
                },
                "fetchedAt": {
                  "type": "string",
                  "nullable": true
                },
                "diseases": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "slug": {
                        "type": "string"
                      },
                      "nameEn": {
                        "type": "string",
                        "nullable": true
                      },
                      "nameZh": {
                        "type": "string",
                        "nullable": true
                      },
                      "bodySystem": {
                        "type": "string",
                        "nullable": true
                      },
                      "relevance": {
                        "type": "string",
                        "nullable": true
                      },
                      "section": {
                        "type": "string",
                        "nullable": true
                      }
                    }
                  }
                }
              }
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "page": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              },
              "totalPages": {
                "type": "integer"
              }
            }
          },
          "filters": {
            "type": "object",
            "properties": {
              "sourceOrgs": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "OntologyMapping": {
        "type": "object",
        "properties": {
          "ontologySource": {
            "type": "string",
            "description": "本體論來源 (MONDO, DOID, SNOMED_VET, ICD10CM)"
          },
          "ontologyCode": {
            "type": "string"
          },
          "ontologyLabel": {
            "type": "string",
            "nullable": true
          },
          "confidence": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "DiseaseReference": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "authors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "Parsed JSON array of author names"
          },
          "journal": {
            "type": "string",
            "nullable": true
          },
          "year": {
            "type": "integer",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "sourceType": {
            "type": "string",
            "nullable": true
          },
          "sourceOrg": {
            "type": "string",
            "nullable": true
          },
          "relevance": {
            "type": "string",
            "nullable": true,
            "description": "primary | supporting | historical"
          },
          "section": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "DrugInteractionDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "targetDrugId": {
            "type": "string",
            "nullable": true
          },
          "targetDrugSlug": {
            "type": "string",
            "nullable": true
          },
          "targetName": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "high",
              "moderate",
              "low"
            ]
          },
          "mechanism": {
            "type": "string",
            "nullable": true
          },
          "isDrugLevel": {
            "type": "boolean"
          }
        }
      },
      "DrugRelatedDisease": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "diseaseId": {
            "type": "string"
          },
          "diseaseSlug": {
            "type": "string"
          },
          "diseaseNameEn": {
            "type": "string"
          },
          "diseaseNameZh": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateKeyRequest": {
        "type": "object",
        "required": ["name"],
        "properties": {
          "name": {
            "type": "string",
            "description": "API key 名稱（用於識別用途）",
            "minLength": 1,
            "maxLength": 100,
            "example": "EMR Client A"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "允許存取的端點。[\"*\"] 表示全部端點，或指定路徑如 [\"/api/v1/ddx\", \"/api/v1/drugs/*\"]。",
            "default": ["*"],
            "example": ["*"]
          }
        }
      },
      "AdminKeyInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Key ID（SHA-256 hash 前 16 字元）",
            "example": "a1b2c3d4e5f6a7b8"
          },
          "name": {
            "type": "string",
            "description": "Key 名稱",
            "example": "EMR Client A"
          },
          "keyMasked": {
            "type": "string",
            "description": "遮罩後的 key（顯示前 6 + 後 4 字元）",
            "example": "vp_abc...xyz1"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["*"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastUsed": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "最後一次使用此 key 的時間"
          }
        }
      },
      "AdminKeyListResponse": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminKeyInfo"
            }
          },
          "total": {
            "type": "integer",
            "description": "Key 總數"
          }
        }
      },
      "AdminKeyCreatedResponse": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "id": {
            "type": "string",
            "description": "Key ID（SHA-256 hash 前 16 字元）",
            "example": "a1b2c3d4e5f6a7b8"
          },
          "key": {
            "type": "string",
            "description": "完整 API key（僅此次回傳！請妥善保存）",
            "example": "vp_AbCdEfGhIjKlMnOpQrStUvWxYz012345"
          },
          "name": {
            "type": "string",
            "example": "EMR Client A"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["*"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AdminKeyDeletedResponse": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "deleted": {
            "type": "boolean",
            "example": true
          },
          "keyId": {
            "type": "string",
            "description": "被撤銷的 Key ID",
            "example": "a1b2c3d4e5f6a7b8"
          }
        }
      },
      "AdminKeyRotatedResponse": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "oldKeyId": {
            "type": "string",
            "description": "舊 key ID",
            "example": "a1b2c3d4e5f6a7b8"
          },
          "newKeyId": {
            "type": "string",
            "description": "新 key ID",
            "example": "f8e7d6c5b4a39281"
          },
          "newKey": {
            "type": "string",
            "description": "完整新 API key（僅此次回傳！請妥善保存）",
            "example": "vp_NewKeyAbCdEfGhIjKlMnOpQrStUvWx"
          },
          "name": {
            "type": "string"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rotatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "gracePeriod": {
            "type": "string",
            "description": "Grace period 說明",
            "example": "24 hours — old key remains valid until then"
          }
        }
      },
      "AdminUsageKeyStats": {
        "type": "object",
        "properties": {
          "keyHash": {
            "type": "string",
            "description": "Key hash ID"
          },
          "name": {
            "type": "string",
            "description": "Key 名稱"
          },
          "total": {
            "type": "integer",
            "description": "期間內總呼叫次數"
          },
          "daily": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "每日呼叫次數（key 為日期 YYYY-MM-DD）",
            "example": {
              "2026-02-19": 42,
              "2026-02-18": 35
            }
          },
          "topEndpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "endpoint": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                }
              }
            },
            "description": "最熱門端點（依呼叫次數排序）"
          }
        }
      },
      "AdminUsageResponse": {
        "type": "object",
        "properties": {
          "apiVersion": {
            "type": "string",
            "example": "1.0"
          },
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date",
                "example": "2026-02-13"
              },
              "to": {
                "type": "string",
                "format": "date",
                "example": "2026-02-19"
              },
              "days": {
                "type": "integer",
                "example": 7
              }
            }
          },
          "totalRequests": {
            "type": "integer",
            "description": "所有 key 在期間內的總呼叫次數"
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminUsageKeyStats"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "System",
      "description": "系統端點（健康檢查、元資料）"
    },
    {
      "name": "Search",
      "description": "全文搜尋"
    },
    {
      "name": "Diseases",
      "description": "疾病百科"
    },
    {
      "name": "DDX",
      "description": "鑑別診斷（症狀 + 實驗室數據）"
    },
    {
      "name": "Drugs",
      "description": "藥物庫（劑量、交互作用）"
    },
    {
      "name": "References",
      "description": "獸醫文獻庫"
    },
    {
      "name": "Admin",
      "description": "管理員 API — API Key CRUD、使用統計、Key Rotation。需要 x-admin-key header 認證。"
    }
  ]
}
