ScoreInsight Public API Reference

本文件提供第三方應用程式使用 ScoreInsight 計分系統第三方 API 的方式,供外部系統讀取公開資料。

本次開放的資料來源共 4 個唯讀資料端點:提交明細、個人排名、小隊排名、加扣分紀錄。

版本 1.0 最後更新:2026-05-13 唯讀 API Base Path:/rest/v1

1. 總覽

Base URL
https://scoreinsight-api-proxy.yongsin0129.workers.dev/rest/v1
API Key
請向 ScoreInsight 管理方索取
請第三方應用直接使用本文件列出的 API Base URL 與端點路徑進行串接。
資料項目 Endpoint 用途
提交明細 /v_public_submission_detail 查詢個人每日填寫紀錄與答案明細
個人排行榜 /v_public_user_rankings 查詢個人排行榜
小隊排行榜 /v_public_group_rankings 查詢小隊排行榜
加扣分紀錄 /v_public_score_adjustments 查詢個人或組別加扣分歷史

2. 認證與請求格式

本 API 為 HTTP JSON 查詢介面。請在每次請求中攜帶以下 headers:

Header 說明
apikey <由 ScoreInsight 管理方提供> 第三方 API 存取金鑰
Authorization Bearer <由 ScoreInsight 管理方提供> Bearer Token 驗證格式
Accept application/json 回傳 JSON 資料

cURL 範例

curl "https://scoreinsight-api-proxy.yongsin0129.workers.dev/rest/v1/v_public_user_rankings?select=*&order=rank.asc&limit=20" \
  -H "apikey: <YOUR_API_KEY>" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Accept: application/json"

JavaScript fetch 範例

const apiKey = "<YOUR_API_KEY>"

const response = await fetch(
  "https://scoreinsight-api-proxy.yongsin0129.workers.dev/rest/v1/v_public_user_rankings?select=*&order=rank.asc&limit=20",
  {
    method: "GET",
    headers: {
      apikey: apiKey,
      Authorization: `Bearer ${apiKey}`,
      Accept: "application/json"
    }
  }
)

const data = await response.json()

3. 查詢語法

本 API 支援以下查詢參數格式。最常用的參數如下:

參數 範例 說明
select select=* 指定回傳欄位,* 表示全部欄位
order order=rank.asc 排序欄位,可加 .asc.desc
limit limit=20 限制回傳筆數
offset offset=20 分頁跳過前 N 筆資料
欄位=eq.值 user_id=eq.123 等於
欄位=gte.值 business_date=gte.2026-05-01 大於等於
欄位=lte.值 business_date=lte.2026-05-31 小於等於
欄位=ilike.*關鍵字* user_name=ilike.*王* 模糊搜尋,忽略大小寫
欄位=in.(...) group_name=in.(北區第一組,北區第二組) 多值查詢
欄位=not.is.null rank=not.is.null 排除空值
排行榜類資料建議加上 rank=not.is.nullavg_rank=not.is.null,避免拿到超過顯示閾值而被隱藏排名的資料列。

4. API Endpoints

GET /v_public_submission_detail

提交明細

查詢個人提交紀錄。此 endpoint 保留所有紀錄,不會自動排除 is_deleted = truelegal_record = false 的資料。

常用查詢範例

GET /rest/v1/v_public_submission_detail
  ?select=*
  &user_id=eq.123
  &business_date=gte.2026-05-01
  &business_date=lte.2026-05-31
  &order=submitted_at.desc
  &limit=50

欄位說明

欄位 型別 說明
submission_idinteger提交 ID
submitted_atstring (timestamptz)原始提交時間,通常為 UTC 時間
submitted_at_taiwanstring (timestamp)轉換為台北時區後的提交時間
business_datestring (date)業務日期;台北時間中午 12:00 前視為前一天
user_idinteger使用者 ID
user_namestring使用者名稱
user_rolestring組織角色:big_group_leader / captain / vice_captain / member
group_idinteger | null組別 ID
main_groupstring | null大隊名稱
sub_groupstring | null小隊代號
group_namestring | null組別名稱
is_deletedboolean是否已軟刪除
legal_recordboolean是否為有效計分記錄
submission_notestring | null提交備註
phone_check_resultstringMATCHMISMATCH
user_daily_sequence_idinteger | null同一使用者在同一業務日的第幾筆提交
answer_detailsarray<object>答案明細陣列,見下方結構
total_scoreinteger本次提交總分

answer_details 結構

欄位 型別 說明
question_idinteger題目 ID
question_titlestring題目標題
question_descriptionstring | null題目說明
question_typestringsingle_selectmulti_select
optionsarray | object | null題目選項設定
scoreinteger該題得分
answer_detailobject | string | null原始答案資料

回應範例

[
  {
    "submission_id": 1085,
    "submitted_at": "2026-05-13T01:48:22.318241+00:00",
    "submitted_at_taiwan": "2026-05-13T09:48:22.318241",
    "business_date": "2026-05-12",
    "user_id": 123,
    "user_name": "王小明",
    "user_role": "captain",
    "group_id": 7,
    "main_group": "北區",
    "sub_group": "01",
    "group_name": "北區第一組",
    "is_deleted": false,
    "legal_record": true,
    "submission_note": null,
    "phone_check_result": "MATCH",
    "user_daily_sequence_id": 2,
    "answer_details": [
      {
        "question_id": 3,
        "question_title": "今日持咒",
        "question_description": "依實際完成情況填寫",
        "question_type": "single_select",
        "options": [{ "label": "10", "value": 10 }],
        "score": 10,
        "answer_detail": { "selectedLabel": "10" }
      }
    ],
    "total_score": 25
  }
]
GET /v_public_user_rankings

個人排行榜

查詢個人排行榜。資料約每 5 分鐘刷新一次。

常用查詢範例

GET /rest/v1/v_public_user_rankings
  ?select=rank,user_id,user_name,user_role,group_name,total_score,average_score
  &rank=not.is.null
  &order=rank.asc
  &limit=30

欄位說明

欄位 型別 說明
rankinteger | null排名;若超過顯示閾值可能為 null
user_idinteger使用者 ID
user_namestring使用者名稱
user_rolestring組織角色
group_idinteger | null組別 ID
group_namestring組別名稱
main_groupstring | null大隊名稱
sub_groupstring | null小隊代號
total_submissionsinteger有效提交次數
form_total_scorenumber表單累積分數
adjustment_scorenumber加扣分總和
total_scorenumber總分 = 表單分 + 加扣分
average_scorenumber平均表單分

回應範例

[
  {
    "rank": 1,
    "user_id": 123,
    "user_name": "王小明",
    "user_role": "captain",
    "group_id": 7,
    "group_name": "北區第一組",
    "main_group": "北區",
    "sub_group": "01",
    "total_submissions": 28,
    "form_total_score": 560,
    "adjustment_score": 15,
    "total_score": 575,
    "average_score": 20
  }
]
GET /v_public_group_rankings

小隊排行榜

查詢小隊排行榜。資料約每 5 分鐘刷新一次。

常用查詢範例

GET /rest/v1/v_public_group_rankings
  ?select=rank,avg_rank,group_id,group_name,main_group,group_total_score,group_avg_total_score
  &order=rank.asc
  &limit=20

欄位說明

欄位 型別 說明
rankinteger | null小隊總分排名
avg_rankinteger | null小隊平均總分排名
group_idinteger組別 ID
group_namestring組別名稱
main_groupstring大隊名稱
member_countinteger成員數,不含大隊長
total_submissionsinteger組內總提交次數
group_form_scorenumber組內成員表單總分
group_adjustment_scorenumber組別加扣分 + 成員個人加扣分
group_total_scorenumber組總分,已含大隊長分數
big_leader_scorenumber大隊長貢獻分數
group_avg_scorenumber組平均表單分
group_avg_total_scorenumber組平均總分,分母包含大隊長

回應範例

[
  {
    "rank": 1,
    "avg_rank": 2,
    "group_id": 7,
    "group_name": "北區第一組",
    "main_group": "北區",
    "member_count": 12,
    "total_submissions": 280,
    "group_form_score": 4300,
    "group_adjustment_score": 90,
    "group_total_score": 4475,
    "big_leader_score": 85,
    "group_avg_score": 358.33,
    "group_avg_total_score": 344.23
  }
]
GET /v_public_score_adjustments

加扣分紀錄

查詢個人或組別的加扣分紀錄。此 endpoint 不會自動排除 is_deleted = true 的資料。

常用查詢範例

GET /rest/v1/v_public_score_adjustments
  ?select=*
  &created_at=gte.2026-05-01T00:00:00Z
  &created_at=lt.2026-06-01T00:00:00Z
  &order=created_at.desc
  &limit=100

欄位說明

欄位 型別 說明
idinteger加扣分記錄 ID
amountinteger分數;正數為加分,負數為扣分
reasonstring | null原因說明
categorystring | null分類標籤
notestring | null備註
created_atstring (timestamptz)建立時間
created_bystring (uuid) | null建立者帳號 ID
updated_atstring (timestamptz)最後更新時間
updated_bystring (uuid) | null最後更新者帳號 ID
is_deletedboolean是否軟刪除
legal_recordboolean是否為有效計分記錄
user_idinteger | null若為個人加扣分,對應的使用者 ID
user_namestring | null若為個人加扣分,對應的使用者名稱
user_rolestring | null若為個人加扣分,對應的使用者角色
user_group_idinteger | null若為個人加扣分,使用者所屬組別 ID
user_group_namestring | null若為個人加扣分,使用者所屬組別名稱
user_main_groupstring | null若為個人加扣分,使用者所屬大隊
group_idinteger | null若為組別加扣分,對應的組別 ID
group_namestring | null若為組別加扣分,對應的組別名稱
group_main_groupstring | null若為組別加扣分,對應的大隊名稱

回應範例

[
  {
    "id": 501,
    "amount": -5,
    "reason": "遲到",
    "category": "紀律",
    "note": null,
    "created_at": "2026-05-13T02:10:00+00:00",
    "created_by": "6ddf73d6-b2fe-4f14-8f43-7e3317bd8fa1",
    "updated_at": "2026-05-13T02:10:00+00:00",
    "updated_by": "6ddf73d6-b2fe-4f14-8f43-7e3317bd8fa1",
    "is_deleted": false,
    "legal_record": true,
    "user_id": 123,
    "user_name": "王小明",
    "user_role": "captain",
    "user_group_id": 7,
    "user_group_name": "北區第一組",
    "user_main_group": "北區",
    "group_id": null,
    "group_name": null,
    "group_main_group": null
  }
]

5. 錯誤與限制

常見 HTTP 狀態碼

狀態碼 情境
200查詢成功
400查詢參數格式錯誤
401未提供或提供了無效的 API key / Authorization header
404找不到對應 endpoint
429請求頻率過高
500伺服器發生未預期錯誤
API 目前設有流量限制:同一 IP 每 60 秒最多 120 次請求。超過限制時會回傳 429 Too Many Requests
這 4 個 endpoint 為唯讀查詢用途,請只使用 GET / HEAD。不要對這些資料端點發送寫入請求。

6. 業務規則說明

  • business_date:系統以台北時區為準,且中午 12:00 前視為前一天。
  • legal_record:同一使用者在同一業務日內,最後一筆且未刪除的提交才會是有效計分記錄。
  • 排行榜刷新頻率:個人排行榜與小隊排行榜資料約每 5 分鐘更新一次,不保證即時反映最新提交。
  • group_total_score:小隊總分已包含大隊長貢獻分數。
  • group_avg_total_score:平均總分的分母包含大隊長,因此會以 member_count + 1 計算。
  • 公開資料範圍:提交明細與加扣分紀錄會保留刪除狀態與有效紀錄欄位,是否要只採用有效資料,請由使用方依需求自行過濾。
若第三方只想取得「有效提交」資料,建議在提交明細 endpoint 上加條件 legal_record=eq.trueis_deleted=eq.false