載入中...
載入中...
AnonMail REST API 完整端點參考
https://vetmail.vercel.app格式: JSON認證: Cookie (jwt)以下 /api/v1 端點是提供給外部整合(嵌入式 widget、合作夥伴後台、自動化流程)使用的正式契約, 採 Bearer API Key 認證(Authorization: Bearer ak_<40 位 hex>)。 Key 具備 read(GET)與 write(POST/PATCH)兩種 scope。 有金鑰的端點回應會帶上 X-RateLimit-Limit / Remaining / Reset 速率限制標頭; 超限時回傳 429 並附 Retry-After。
完整 OpenAPI 3.1 規格: /openapi.json (可匯入 Swagger UI、Postman、Insomnia 等工具)。
/api/v1/submit公開scope: 無— 提交案件(widget 用,無需金鑰)/api/v1/casesBearer API Keyscope: read— 案件列表(分頁、可篩選)/api/v1/cases/{id}Bearer API Keyscope: read— 案件詳情(不含內部備註)/api/v1/cases/{id}Bearer API Keyscope: write— 更新案件狀態 / 指派/api/v1/cases/{id}/replyBearer API Keyscope: write— 回覆案件(一律對外可見)/api/v1/statsBearer API Keyscope: read— 案件統計數據/api/v1/audit-logsBearer API Keyscope: read— 稽核日誌查詢(分頁、可篩選)/api/v1/form-config公開scope: 無— 表單欄位設定(無需金鑰)⚠️ 兩個 submit 端點不要搞混
POST /api/submit(內部 / 舊版):必填 agree_policy: true, 回應為扁平結構 { tracking_code, message }。POST /api/v1/submit(widget / 整合):不需 agree_policy, tracking code 巢狀於 data 之下 { data: { tracking_code, case_id } }。外部整合請一律使用 /api/v1/submit。下方「公開端點」「認證端點」「案件管理端點」等區段為內部 cookie-session 端點,不屬於 v1 契約,僅供管理後台自身使用。
/api/submit公開提交匿名陳情(JSON 或 multipart/form-data 夾帶附件)
Request Body
{
"category": "harassment", // safety | harassment | discrimination | ethics | labor | management | environment | other
"priority": "high", // low | medium | high | urgent
"title": "主旨文字(1-100 字)",
"department": "行銷部", // 選填,0-50 字
"content": "詳細陳情內容...(1-10000 字)",
"agree_policy": true // 必須為 true
}Response
{
"success": true,
"tracking_code": "TRK-A3B7-KN2Q-WE",
"message": "陳情已成功提交"
}Status Codes
/api/track公開以追蹤碼查詢案件進度
Request Body
{
"tracking_code": "TRK-A3B7-KN2Q-WE"
}Response
{
"success": true,
"case": {
"tracking_code": "TRK-A3B7-KN2Q-WE",
"category": "harassment",
"priority": "high",
"status": "investigating",
"title": "主旨",
"content": "陳情內容...",
"submitted_at": "2026-03-20T08:00:00Z",
"messages": [
{ "author_type": "hr", "content": "已收到您的陳情...", "created_at": "..." }
]
},
"retaliation_checkin": null // 或 { "id": "...", "cohort": "3m", "prompt": "..." }
}Status Codes
/api/reply-anon公開匿名追問(員工端)
Request Body
{
"tracking_code": "TRK-A3B7-KN2Q-WE",
"content": "補充說明...(1-10000 字)"
}Response
{
"success": true,
"message": {
"content": "補充說明...",
"author_type": "employee",
"created_at": "2026-03-21T09:00:00Z"
}
}Status Codes
/api/tenant/config公開取得目前租戶的公開設定
Response
{
"success": true,
"tenant": {
"slug": "my-company",
"company_name": "範例企業",
"logo_url": null,
"primary_color": "#2DD4BF"
}
}Status Codes
/api/onboarding公開自助租戶註冊(需先 GET /api/captcha/challenge 取得驗證題)
Request Body
{
"slug": "my-company", // 2-50 字,小寫英數與連字號
"company_name": "新公司名稱",
"admin_email": "admin@example.com",
"admin_password": "securePassword123", // 8-256 字
"admin_name": "管理員姓名",
"plan": "free", // free | pro | enterprise(選填,預設 free)
"captcha_token": "<來自 /api/captcha/challenge>",
"captcha_answer": 12
}Response
{
"success": true,
"requires_payment": false,
"plan": "free",
"tenant": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"slug": "my-company",
"company_name": "新公司名稱",
"subdomain_url": "https://vetmail.vercel.app"
}
}Status Codes
/api/auth/login公開管理員登入
Request Body
{
"email": "admin@example.com",
"password": "yourPassword"
}Response
{
"success": true,
"message": "登入成功",
"user": { "email": "admin@example.com", "full_name": "Admin", "role": "admin" }
}Status Codes
/api/auth/session需登入驗證目前 session 是否有效
Response
{
"authenticated": true,
"user": {
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "admin@example.com",
"full_name": "Admin",
"role": "admin",
"tenant_id": "550e8400-e29b-41d4-a716-446655440001"
}
}Status Codes
/api/auth/logout需登入登出並清除 session
Response
{
"success": true
}Status Codes
/api/cases需登入取得案件列表(query:status / priority / category / search / page / per_page)
Response
{
"success": true,
"cases": [
{
"id": "550e8400-...", "category": "harassment", "priority": "high",
"status": "submitted", "title": "主旨", "department": null,
"assigned_to": null, "submitted_at": "2026-03-20T08:00:00Z",
"ai_risk_score": null, "ai_risk_level": null, "ai_summary": null
}
],
"total": 42,
"page": 1,
"per_page": 20
}Status Codes
/api/cases/[id]需登入取得單一案件詳情(含訊息與附件)
Response
{
"success": true,
"case": {
"id": "550e8400-...",
"category": "harassment", "priority": "high", "status": "investigating",
"title": "主旨", "content": "內容...", "department": null,
"assigned_to": null, "submitted_at": "2026-03-20T08:00:00Z",
"sla_ack_deadline": "2026-03-27T08:00:00Z",
"sla_resolution_deadline": "2026-06-18T08:00:00Z",
"ai_risk_score": null, "ai_risk_level": null, "ai_summary": null,
"case_messages": [ { "id": "...", "author_type": "hr", "content": "...", "is_internal": false, "created_at": "..." } ],
"case_attachments": [ { "id": "...", "file_name": "...", "file_size": 1024, "mime_type": "image/png", "created_at": "..." } ]
}
}Status Codes
/api/cases/[id]需登入更新案件狀態、指派或標籤
Request Body
{
"status": "investigating", // submitted | acknowledged | investigating | pending_decision | resolved | escalated | closed
"assigned_to": "處理人名稱", // 選填
"tags": ["騷擾", "重複申訴"] // 選填,最多 20 個
}Response
{
"success": true,
"case": {
"id": "...", "status": "investigating", "assigned_to": "處理人名稱",
"tags": ["騷擾"], "acknowledged_at": "...", "resolved_at": null,
"closed_at": null, "retention_deletion_at": null
}
}Status Codes
/api/cases/[id]/reply需登入管理員回覆案件(is_internal 為內部備註)
Request Body
{
"content": "感謝您的反映,我們已開始調查...",
"is_internal": false
}Response
{
"success": true,
"message": { "id": "...", "content": "...", "author_type": "hr", "is_internal": false, "created_at": "..." }
}Status Codes
/api/cases/[id]/analyze需登入AI 分析案件內容(需租戶開啟 AI 分析並簽署同意書)
Response
{
"success": true,
"analysis": {
"ai_category_suggestion": "harassment",
"ai_risk_score": 78,
"ai_risk_level": "high",
"ai_summary": "案件摘要...",
"ai_tags": ["騷擾", "主管"],
"ai_analyzed_at": "2026-03-20T10:00:00Z"
}
}Status Codes
/api/cases/batch需登入批次更新案件狀態(最多 50 件)
Request Body
{
"case_ids": ["550e8400-...", "550e8401-..."],
"status": "acknowledged"
}Response
{
"success": true,
"updated": 2,
"errors": [] // 失敗項目:[{ "id": "...", "error": "原因" }]
}Status Codes
/api/cases/report需登入取得報告資料(query:type=single&case_id=… 或 type=monthly&month=YYYY-MM)
Response
{
"success": true,
"report": {
"type": "monthly",
"month": "2026-03",
"generated_at": "2026-03-31T12:00:00Z",
"stats": {
"total": 12,
"by_status": { "submitted": 2, "investigating": 4 },
"by_category": { "harassment": 5, "discrimination": 3 },
"by_priority": { "high": 4, "medium": 6 },
"avg_response_hours": 18.5,
"risk_distribution": {}
},
"cases": [ { "id": "...", "title": "..." } ]
}
}Status Codes
/api/dashboard/stats需登入總覽統計數據
Response
{
"success": true,
"stats": {
"total": 42,
"by_status": { "submitted": 5, "investigating": 8 },
"by_category": { "harassment": 12 },
"by_priority": { "high": 9 },
"trend": [ { "date": "2026-03-01", "count": 3 } ],
"avg_response_hours": 16.2,
"avg_resolution_hours": 96.8
}
}Status Codes
/api/dashboard/analytics需登入進階分析資料(趨勢圖表)
Response
{
"success": true,
"analytics": {
"priorityDistribution": { "low": 3, "medium": 12, "high": 8, "urgent": 2 },
"departmentBreakdown": [ { "department": "行銷部", "count": 6 } ],
"weeklyTrend": [ { "week": "2026-W12", "count": 5, "resolved": 3 } ],
"avgResolutionDays": 4.2,
"responseRate": 0.92,
"topCategories": [ { "category": "harassment", "count": 12, "percentage": 35 } ]
}
}Status Codes
/api/audit需登入取得稽核日誌(query:page / per_page / action / actor / from / to)
Response
{
"success": true,
"logs": [
{
"id": "...",
"action": "status_change",
"actor": "admin@example.com",
"target": "CASE-550E8400",
"details": { "from": "submitted", "to": "acknowledged" },
"ip_address": null,
"created_at": "2026-03-20T10:00:00Z"
}
],
"total": 128,
"page": 1,
"per_page": 50
}Status Codes
/api/notifications/preferences需登入取得通知偏好設定
Response
{
"success": true,
"preferences": {
"notification_email": "hr@example.com",
"contact_email": null,
"line_notify_token": null
}
}Status Codes
/api/notifications/preferences需登入更新通知偏好設定(需 admin 角色)
Request Body
{
"notification_email": "hr@example.com" // 或 null 表示停用
}Response
{
"success": true
}Status Codes
/api/tenant/config需登入更新租戶設定(需 admin 角色)
Request Body
{
"company_name": "新名稱", // 選填,1-100 字
"primary_color": "#2DD4BF", // 選填,#RRGGBB
"notification_email": "hr@example.com", // 選填,可為 null
"contact_email": null, // 選填
"line_notify_token": null // 選填
}Response
{
"success": true,
"tenant": {
"slug": "my-company", "company_name": "新名稱", "primary_color": "#2DD4BF",
"notification_email": "hr@example.com", "contact_email": null,
"line_notify_token": null, "plan": "free"
}
}Status Codes
/api/billing/status需登入取得目前帳單與方案狀態
Response
{
"success": true,
"billing": {
"plan": "pro",
"plan_name": "Pro",
"max_admins": 5,
"max_cases_per_month": 500,
"has_subscription": true,
"usage": { "month": "2026-03", "cases_count": 18, "admins_count": 2 }
}
}Status Codes
/api/billing/checkout需登入建立 Stripe Checkout Session(需 admin 角色)
Request Body
{
"plan": "pro" // pro | enterprise
}Response
{
"success": true,
"checkout_url": "https://checkout.stripe.com/..."
}Status Codes
/api/billing/portal需登入建立 Stripe 客戶管理入口(需 admin 角色)
Response
{
"success": true,
"portal_url": "https://billing.stripe.com/..."
}Status Codes
/api/admin/admins需登入取得管理員列表
Response
{
"success": true,
"admins": [
{
"id": "550e8400-...", "email": "admin@example.com", "full_name": "Admin",
"role": "admin", "is_active": true, "last_login_at": "...", "created_at": "..."
}
]
}Status Codes
/api/admin/export需登入匯出租戶完整資料(JSON 檔案下載)
Response
{
"exported_at": "2026-03-20T12:00:00Z",
"tenant_id": "550e8400-...",
"cases": [ { "id": "...", "category": "...", "status": "...", "legal_hold": false } ],
"messages": [ { "id": "...", "case_id": "...", "author_type": "hr" } ],
"audit_logs": [ { "id": "...", "action": "..." } ],
"admins": [ { "id": "...", "email": "..." } ]
}Status Codes