FastComments.com

即時評論 API

FastComments API

FastComments 提供一套 API 讓您與多種資源互動。您可以使用我們的平台建置整合,甚至自行開發客戶端!

在本文件中,您將找到 API 所支援的所有資源,並附有其請求與回應類型的說明。

對於企業客戶,所有 API 存取皆會記錄於稽核日誌中。

產生的 SDK

FastComments 現在會從程式碼產生一份 API Spec(此規格尚未完整,但已包含許多 API)。

我們也提供了多種常見語言的 SDK:

認證

API 透過在 X-API-KEY 標頭或 API_KEY 查詢參數中傳遞您的 api key 來驗證。您還需要提供 tenantId 以呼叫 API。tenantId 可從與 API 金鑰相同的頁面取得。

安全說明

這些路由應該由 伺服器 呼叫。請勿 從瀏覽器呼叫。若這樣做會暴露您的 API 金鑰,任何能看到頁面原始碼的人都能取得完整帳號存取權限!

認證方式一 – 標頭

  • 標頭:X-API-KEY
  • 標頭:X-TENANT-ID

認證方式二 – 查詢參數

  • 查詢參數:API_KEY
  • 查詢參數:tenantId

認證方式三 – OAuth Bearer Token

  • 標頭:Authorization: Bearer fcat_...

第三方應用程式(如 Zapier)以及 MCP 伺服器 的客戶端會透過 OAuth 取得 token,而非使用 API 金鑰。此 token 可用於此處的所有端點。token 已隱含租戶資訊,故 tenantId 為可選,但若提供則必須與 token 相符。GET 請求需要 read 範圍,其他方法則需要 write 範圍。完整流程(包括客戶端註冊、PKCE、刷新與撤銷)請參考 OAuth Authorization。發現端點位於 https://fastcomments.com/.well-known/oauth-authorization-server。

讀取自己的寫入

FastComments 提供 Active-Active 可用性。來自您資料中心的請求會自動路由至離您最近的 presence 點。這是自動化的,通常您可以觀察到讀寫一致性(read‑your‑write)語意。若您想確保讀取自己的寫入,可將請求固定到特定區域的 API 主機(但大多數整合通常不需要這麼做):

  • gdc-oregon.fastcomments.com
  • gdc-virginia.fastcomments.com
  • gdc-singapore.fastcomments.com
  • gdc-falkenstein2.fastcomments.com
  • gdc-sao-paulo.fastcomments.com
  • eudc-helsinki2.fastcomments.com
  • eudc-limburg.fastcomments.com
  • eudc-france.fastcomments.com

請注意,若您這樣做,可能需要設定備援,因為我們過去已棄用某些入口節點,並使用新名稱進行切換。

稽核日誌結構 Internal Link

An AuditLog 是一個物件,代表具有此功能存取權限的租戶的稽核事件。

AuditLog 物件的結構如下:

AuditLog 結構
Copy Copy
1
2interface AuditLog {
3 id: string;
4 /** Who performed the event. **/
5 userId?: string;
6 username?: string;
7 resourceName: string;
8 crudType: 'c' | 'r' | 'u' | 'd' | 'login';
9 from: string;
10 url?: string;
11 ip?: string;
12 /** The browser that performed the event, when it came from one. **/
13 ua?: string;
14 /** A hash of the session the event came from, for correlating one person's actions. Never the session itself. **/
15 sIdHashed?: string;
16 when: string;
17 description?: string;
18 serverStartDate: string;
19 /** The id of the object the event was performed on, as opposed to who performed it. **/
20 targetId?: string;
21 /** A human-readable label for that object, e.g. "jsmith (jsmith@example.com)". **/
22 targetLabel?: string;
23 objectDetails?: object;
24}
25

targetId 與 targetLabel 描述事件執行的對象;userId 與 username 描述執行者。對於更新,objectDetails.changes 包含一個 {field: {from, to}} 的映射,說明實際變更的內容。

稽核日誌是不可變的,也無法手動寫入。FastComments.com 僅能決定何時寫入稽核日誌。然而,您可以透過此 API 讀取它。

稽核日誌中的事件會在兩年後過期。

批次工作結構 Internal Link

BatchJob 是一個長時間執行的任務,例如匯入、匯出,或是頁面遷移。工作會排入佇列,然後被取出並在背景執行。

processedCount 與 totalCount 顯示進度。它們的單位取決於 type:

  • migrate-pages:已完成的遷移數量,對應於請求的遷移總數。
  • undo-page-migration:已還原的記錄。此類型沒有 totalCount。
  • import、export 以及其他工作:已處理的列數。

BatchJob 物件的結構如下:

BatchJob 結構
Copy Copy
1
2interface BatchJob {
3 id: string
4 /** 例如 migrate-pages、undo-page-migration、migrate-domains、import、export、users-export 或 copy-comments。 **/
5 type: string
6 status: 'requested' | 'running' | 'success' | 'failed'
7 createdAt: string
8 completedAt?: string
9 processedCount: number
10 /** 總工作量,若事先已知的話。 **/
11 totalCount?: number
12 /** migrate-pages:每個已完成的遷移一筆記錄,依請求順序排列。 **/
13 pageMigrationResults?: Array<PageMigrationSuccess | PageMigrationFailure>
14 /**
15 * migrate-pages:在工作完成(成功或失敗)後設定。於 90 天內傳遞至 POST /api/v1/pages/migrations/:undoId/undo。
16 * undo-page-migration:正在還原的遷移。
17 **/
18 undoId?: string
19 /** undo-page-migration:在工作完成後設定。 **/
20 pageMigrationUndoResult?: PageMigrationUndoResult
21}
22
23interface PageMigrationSuccess {
24 from: string
25 to: string
26 type: 'urlId' | 'domain'
27 status: 'success'
28 commentsMigrated: number
29}
30
31interface PageMigrationFailure {
32 from: string
33 to: string
34 type: 'urlId' | 'domain'
35 status: 'failed'
36 code: string
37 reason: string
38}
39
40interface PageMigrationUndoResult {
41 /** 記錄已恢復至遷移前的值。 **/
42 restored: number
43 /** 記錄因遷移後已變更或不再存在而未被處理。 **/
44 skipped: number
45 /** 記錄在合併頁面時被刪除的遷移。這些無法復原。 **/
46 notRestorable: number
47}
48

重試

如果執行頁面遷移工作的伺服器重新啟動,該工作會重新放回佇列,並在最後一次完成的遷移之後繼續執行。工作最多會嘗試 3 次,之後其 status 會變為 failed。

評論結構 Internal Link

一個 Comment 物件代表使用者留下的一則評論。

父評論與子評論之間的關聯是透過 parentId 定義的。

Comment 物件的結構如下:

評論結構
Copy Copy
1
2interface Comment {
3 /** 唯讀: 如果垃圾郵件引擎判定該評論為垃圾郵件,則設為 true。 **/
4 aiDeterminedSpam?: boolean
5 /** 該評論是否被核准顯示。儲存評論時設為 true,否則將被隱藏。 **/
6 approved?: boolean
7 /** 使用者的大頭貼。 **/
8 avatarSrc?: string
9 /** 子評論。並非在所有情況下都有填入。當透過 API 將 asTree 設為 true 時會使用。 **/
10 children: Comment[]
11 /** 使用者輸入的原始評論內容。 **/
12 comment: string
13 /** 唯讀: 使用者的評論解析後的 HTML。 **/
14 commentHTML?: string
15 /** 使用者的電子郵件。若不允許匿名評論則為必填。 **/
16 commenterEmail?: string
17 /** 使用者的連結(例如,他們的部落格)。 **/
18 commenterLink?: string
19 /** 使用者的名稱。總是必填。如果沒有可用名稱,請設為像 "Anonymous" 之類的值。 **/
20 commenterName: string
21 /** 留言的日期,使用 UTC epoch。 **/
22 date: number
23 /** 評論的「顯示標籤」,例如 "Admin"、"Moderator" 或類似 "VIP User" 的標示。 **/
24 displayLabel?: string
25 /** 留言發布的網域。 **/
26 domain?: string
27 /** 唯讀: 該評論被檢舉的次數。 **/
28 flagCount?: number
29 /** 評論中成功解析出的 #hashtags。你也可以手動新增 hashtags 以供查詢,但它們不會自動顯示在評論文字中。 **/
30 hashTags?: CommentHashTag[]
31 /** 唯讀: 評論是否包含圖片? **/
32 hasImages?: boolean
33 /** 唯讀: 評論是否包含連結? **/
34 hasLinks?: boolean
35 /** 唯讀: 唯一的評論 id。 **/
36 id: string
37 /** 僅在建立時使用!此值會被雜湊後儲存。 **/
38 ip?: string
39 /** 唯讀: 目前使用者是否封鎖了撰寫此評論的使用者? **/
40 isBlocked?: boolean
41 /** 唯讀: 此評論是否由管理員所發?會自動根據 userId 設定。 **/
42 isByAdmin?: boolean
43 /** 唯讀: 此評論是否由版主所發?會自動根據 userId 設定。 **/
44 isByModerator?: boolean
45 /** 若評論被軟刪除(由於其他設定必須保留佔位符),則設為 true。 **/
46 isDeleted?: boolean
47 /** 若使用者帳號被刪除且評論需被保留,則設為 true。 **/
48 isDeletedUser?: boolean
49 /** 唯讀: 該評論是否已被目前登入使用者(contextUserId)檢舉? **/
50 isFlagged?: boolean
51 /** 該評論是否被置頂? **/
52 isPinned?: boolean
53 /** 該評論是否被鎖定?若為 true,則沒有人(包括版主)能回覆、編輯或刪除該評論,直到解除鎖定。 **/
54 isLocked?: boolean
55 /** 該評論是否為垃圾評論? **/
56 isSpam?: boolean
57 /** 唯讀: 該評論在目前使用者(contextUserId)是否被投下倒票? **/
58 isVotedDown?: boolean
59 /** 唯讀: 該評論在目前使用者(contextUserId)是否被投上票? **/
60 isVotedUp?: boolean
61 /** 評論所使用的語系。如果未提供,將從 HTTP 的 Accept-Language 標頭推斷。 **/
62 locale?: 'de_de' | 'en_us' | 'es_es' | 'fr_fr' | 'it_it' | 'ja_jp' | 'ko_kr' | 'pl_pl' | 'pt_br' | 'ru_ru' | 'tr_tr' | 'zh_cn' | 'zh_tw'
63 /** 唯讀: 評論中成功解析出的 @mentions。 **/
64 mentions?: CommentUserMention[]
65 /** 與評論相關的選用 metadata。 **/
66 meta?: Record<string, string | number | boolean>
67 /** 與此評論相關的選用審核群組 id 清單。 **/
68 moderationGroupIds?: string[]|null
69 /** 唯讀: 對應目前使用者(contextUserId)對此評論投票的 vote 物件 id。 **/
70 myVoteId?: string
71 /** 是否已為此評論發送給評論者通知。若要在匯入時避免發送通知,請設為 true。 **/
72 notificationSentForParent?: boolean
73 /** 是否已為此評論發送給租戶使用者通知。若要在匯入時避免發送通知,請設為 true。 **/
74 notificationSentForParentTenant?: boolean
75 /** 此評論所在頁面的標題。 **/
76 pageTitle?: string
77 /** 若我們在回覆一則評論,這是我們所回覆的評論 ID。 **/
78 parentId?: string|null
79 /** 該評論是否被標記為已審核。 **/
80 reviewed: boolean
81 /** 該評論所屬的租戶 id。 **/
82 tenantId: string
83 /** 撰寫該評論的使用者。當使用名稱/電子郵件儲存評論時會自動建立。 **/
84 userId?: string|null
85 /** 此評論可見位置的 URL,例如部落格文章。 **/
86 url: string
87 /** 你傳給我們的 urlId 的「清理」版本。儲存時你會指定此欄位,但當你取回評論時,此欄位會被「清理」,你的原始值會移到 "urlIdRaw"。 **/
88 urlId: string
89 /** 唯讀: 你傳給我們的原始 urlId。 **/
90 urlIdRaw?: string
91 /** 使用者與此評論是否已通過驗證? **/
92 verified: boolean
93 /** 被投上的票數。 **/
94 votesUp?: number
95 /** 被投下的票數。 **/
96 votesDown?: number
97 /** 評論的「聲望」(= votes up - votes down)。 **/
98 votes?: number
99}
100

有些欄位被標示為 READONLY — 這些欄位由 API 回傳但無法設定。

評論文字結構

評論是使用 FastComments 的一種 Markdown 變體撰寫,這就是 Markdown 外加傳統 bbcode 風格的圖片標籤,例如 [img]path[/img]。

文字儲存在兩個欄位。使用者輸入的原始文字會不作修改地儲存在 comment 欄位。這會被渲染並儲存在 commentHTML 欄位。

允許的 HTML 標籤為 b, u, i, strike, pre, span, code, img, a, strong, ul, ol, li, and br。

建議渲染該 HTML,因為它是非常小的 HTML 子集,建立一個渲染器相當簡單。舉例來說,針對 React Native 與 Flutter 有多個函式庫可以協助。

你也可以選擇渲染 comment 欄位未正規化的值。 範例解析器在這裡。

這個範例解析器也可以調整以處理 HTML,並將 HTML 標籤轉換成你平台上預期渲染的元素。

標註

當使用者在評論中被標註時,資訊會儲存在名為 mentions 的清單中。該清單中的每個物件具有以下結構。

評論提及物件
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** 使用者的 id。對於 SSO 使用者,會加上你的租戶 id 做為前綴。 **/
4 id: string
5 /** 最終的 @mention 標籤文字,包括 @ 符號。 **/
6 tag: string
7 /** 原始的 @mention 標籤文字,包括 @ 符號。 **/
8 rawTag: string
9 /** 被標註的使用者類型。user = FastComments.com 帳號。sso = SSOUser。 **/
10 type: 'user'|'sso'
11 /** 若使用者選擇不接收通知,此欄位仍會被設為 true(表示已送出)。 **/
12 sent: boolean
13}
14

主題標籤

當使用 hashtag 並成功解析時,資訊會儲存在名為 hashTags 的清單中。該清單中的每個物件具有以下結構。若設定了 retain,也可以手動將 hashtags 新增到評論的 hashTags 陣列以供查詢。

評論標籤物件
Copy CopyRun External Link
1
2interface CommentHashTag {
3 /** hashtag 的 id。 **/
4 id: string
5 /** 最終的 #hashtag 標籤文字,包括 # 符號。 **/
6 tag: string
7 /** 若該 hashtag 與自訂 URL 關聯,則會定義此欄位。 **/
8 url?: string
9 /** 若在評論更新時應保留該 hashtag(即使它不存在於評論文字中),可設此欄位為 true。對於在不更改評論文字的情況下標註評論很有用。 **/
10 retain?: boolean
11}
12

電子郵件範本結構 Internal Link

一個 EmailTemplate 物件代表租戶的自訂電子郵件範本設定。

系統會透過下列方式選擇要使用的電子郵件範本:

  • 其類型識別符,我們稱之為 emailTemplateId。這些是常數。
  • domain。我們會先嘗試尋找與相關物件(例如 Comment)所屬網域相符的範本,若找不到相符者,則會嘗試尋找 domain 為 null 或 * 的範本。

以下為 EmailTemplate 物件的結構:

電子郵件範本結構
Copy Copy
1
2interface EmailTemplate {
3 id: string
4 tenantId: string
5 emailTemplateId: string
6 displayName: string
7 /** 唯讀 **/
8 createdAt: string
9 /** 唯讀 **/
10 updatedAt: string
11 /** 唯讀 **/
12 updatedByUserId: string
13 /** 範本應該關聯的網域。 **/
14 domain?: string | '*' | null
15 /** 以 EJS 語法的電子郵件範本內容。 **/
16 ejs: string
17 /** 針對每個支援的語系,覆寫翻譯鍵到值的映射。 **/
18 translationOverridesByLocale: Record<string, Record<string, string>>
19 /** 表示範本的渲染上下文的物件。 **/
20 testData: object
21}
22

注意事項

  • 您可以從 /definitions 端點取得有效的 emailTemplateId 值。
  • /definitions 端點也包含預設翻譯和測試資料。
  • 如果結構或測試資料無效,範本將無法儲存。

動態貼文結構 Internal Link

A FeedPost 物件代表 FastComments 供稿中的一篇貼文。供稿是一系列貼文的串流,每篇貼文都有自己的評論串,透過 Feed 小工具呈現。每篇貼文都有作者、可選的富內容、媒體與連結,且可以加上標籤,以便過濾供稿。

FeedPost 物件的結構如下:

FeedPost 結構
Copy Copy
1
2interface FeedPost {
3 /** READONLY **/
4 _id: string
5 /** READONLY **/
6 tenantId: string
7 title?: string
8 /** 貼文作者的 FastComments 或 SSO 使用者 ID。 **/
9 fromUserId?: string
10 /** 未設定時由使用者填入。 **/
11 fromUserDisplayName?: string | null
12 /** READONLY。由使用者填入。 **/
13 fromUserAvatar?: string | null
14 /** 用於過濾供稿。 **/
15 tags?: string[]
16 /** 供稿內的排序權重。值越高越優先。 **/
17 weight?: number
18 /** 供自行使用的自由鍵/值對。 **/
19 meta?: Record<string, string>
20 /** 已清理的 HTML。 **/
21 contentHTML?: string
22 media?: FeedPostMediaItem[]
23 links?: FeedPostLink[]
24 /** READONLY **/
25 createdAt: string
26 /** READONLY。回應類型計數。 **/
27 reacts?: Record<string, number>
28 /** READONLY **/
29 commentCount?: number | null
30}
31
32interface FeedPostMediaItem {
33 title?: string
34 /** 點擊時媒體項目的連結目標。 **/
35 linkUrl?: string
36 /** 每個不同尺寸各有一筆條目。小工具會挑選最適合的。 **/
37 sizes: FeedPostMediaItemAsset[]
38}
39
40interface FeedPostMediaItemAsset {
41 w: number
42 h: number
43 src: string
44}
45
46interface FeedPostLink {
47 /** 連結文字,例如「立即註冊」。 **/
48 text?: string
49 /** 連結旁顯示的標題。 **/
50 title?: string
51 /** 連結旁顯示的描述。 **/
52 description?: string
53 url?: string
54}
55

注意事項:

  • 其中一些欄位標記為 READONLY —— 這些欄位由 API 回傳,但無法設定。
  • 貼文的評論是一般評論,其 urlId 為 post: 加上貼文的 _id。使用此值搭配評論 API,即可讀取或建立貼文的評論。

標籤結構 Internal Link

一個 HashTag 物件代表使用者可以留下的標籤。HashTag 可用於連結到外部的內容或將相關評論串連起來。

HashTag 物件的結構如下:

HashTag 結構
Copy Copy
1
2interface HashTag {
3 /** 應以 "#" 或其他想要的字元開頭。 **/
4 tag: string
5 /** 可選的 URL,hashtag 可指向此 URL。與其透過 hashtag 篩選評論,UI 在點擊時會導向此處。 **/
6 url?: string
7 /** 唯讀 **/
8 createdAt: string
9}
10

注意:

  • 在某些 API 端點中,你會看到 hashtag 被用在 URL 中。請記得對值進行 URI 編碼。例如,# 應該表示為 %23。
  • 其中某些欄位被標示為 READONLY - 這些欄位由 API 回傳,但無法設定。

通知計數結構 Internal Link

A NotificationCount 物件表示使用者的未讀通知數量與相關的描述性資訊。

如果沒有未讀通知,該使用者將不會有 NotificationCount。

NotificationCount 物件會自動建立,無法透過 API 建立。它們也會在一年後過期。

您可以透過刪除使用者的 NotificationCount 來清除該使用者的未讀通知數量。

NotificationCount 物件的結構如下:

NotificationCount 結構
Copy Copy
1
2interface NotificationCount {
3 id: string // 使用者 id
4 count: number
5 createdAt: string // 日期字串
6 expireAt: string // 日期字串
7}
8

通知結構 Internal Link

A Notification 物件代表使用者的通知。

Notification 物件會自動產生,無法透過 API 建立。它們也會在一年後過期。
通知無法被刪除。但可以更新將 viewed 設為 false,且您可以依 viewed 進行查詢。

使用者也可以透過將通知中的 optedOut 設為 true 來取消特定評論的通知。再將其設為 false 即可重新訂閱。

有不同的通知類型 ─ 請檢查 relatedObjectType 與 type。

通知的產生方式相當彈性,可由多種情境觸發(請參考 NotificationType)。

截至目前,Notification 的存在並不代表會或應該發送電子郵件。相反地,通知用於通知資訊流與相關整合。

Notification 物件的結構如下:

通知結構
Copy Copy
1
2enum NotificationObjectType {
3 Comment = 0,
4 Profile = 1,
5 Tenant = 2
6}
7
8enum NotificationType {
9 /** 如果有人回覆您。 **/
10 RepliedToMe = 0,
11 /** 如果有人在您曾評論過的討論串的任何位置回覆(即使是子回覆的子回覆)。 **/
12 RepliedTransientChild = 1,
13 /** 如果您的評論被讚。 **/
14 VotedMyComment =2,
15 /** 如果在您訂閱的頁面根部留下新評論。 **/
16 SubscriptionReplyRoot =3,
17 /** 如果有人在您的個人檔案上留言。 **/
18 CommentedOnProfile =4,
19 /** 如果您收到私訊。 **/
20 DirectMessage =5,
21 /** TrialLimits 僅適用於租戶使用者。 **/
22 TrialLimits =6,
23 /** 如果您被 @ 提及。 **/
24 Mentioned =7
25}
26
27interface Notification {
28 id: string
29 tenantId: string
30 /** 使用 SSO 時,使用者 ID 采用 `<tenant id>:<user id>` 格式。 **/
31 userId?: string
32 /** 使用 SSO 時,您只需關注 `userId`。 **/
33 anonUserId?: string
34 /** urlId 幾乎總是已定義。僅在租戶層級的通知(較少見)時才是可選的。 **/
35 urlId?: string
36 /** URL 已快取,以便快速導向通知來源。 **/
37 url?: string
38 /** 頁面標題已快取,以便快速閱讀通知來源。 **/
39 pageTitle?: string
40 relatedObjectType: NotificationObjectType
41 /** 例如,評論 ID。 **/
42 relatedObjectId: string
43 viewed: boolean
44 createdAt: string // date string
45 type: NotificationType
46 fromCommentId?: string
47 fromVoteId?: string
48 /** fromUserName 與 fromUserAvatarSrc 於此快取,以便快速顯示通知。當使用者資訊更新時,這些也會同步更新。 **/
49 fromUserName: string
50 fromUserId: string
51 fromUserAvatarSrc?: string
52 /** 將此設為 true 可停止接收此物件的通知。 **/
53 optedOut?: boolean
54}
55

頁面結構 Internal Link

一個 Page 物件代表許多評論可能屬於的頁面。這種關係是由 urlId 定義的。

Page 儲存像是頁面標題、評論數量及 urlId 等資訊。

Page 物件的結構如下:

頁面結構
Copy Copy
1
2interface Page {
3 id: string
4 urlId: string
5 url: string
6 title?: string
7 createdAt: string
8 commentCount: number
9 rootCommentCount: number
10 /** 將此設為 null 表示所有 SSO 使用者都可以看到該頁面。空清單表示該頁面對所有使用者關閉。 **/
11 accessibleByGroupIds?: string[] | null
12 /** 此頁面是否已關閉以接受新評論? **/
13 isClosed?: boolean
14}
15

投票結構 Internal Link

Poll 是附加在留言上的,而不是獨立的物件。它會隨留言一起建立(見 POST /api/v1/comments),或稍後透過 PUT /api/v1/polls/:commentId 加入到現有的留言。

投票計數保存在投票本身,因此讀取投票時即可直接取得結果,無需自行加總。這些計數背後的個別投票則是 PollVote 物件。

每個選項都有一個在投票建立時產生的 id。這個 id 用於投票、重新命名選項,以及在您以 PUT 更新投票(新增或移除選項)時保留某個選項(及其投票)。這是引用選項唯一安全的方式——絕不要使用它在清單中的位置。

Poll 結構
Copy Copy
1
2interface CommentPollOption {
3 id: string
4 label: string
5 votes: number
6}
7
8interface CommentPoll {
9 question: string
10 options: CommentPollOption[]
11 totalVotes: number
12 /** 當有設定且時間已過,投票即關閉,不再接受投票。 **/
13 closesAt?: string | null
14 /** 0 為匿名(預設),1 為管理員與版主,2 為所有人。未提供表示匿名。 **/
15 privacy?: 0 | 1 | 2 | null
16 /** 當為 true 時,尚未投票者無法看到計數。未提供表示 false。 **/
17 requireVoteToSeeResults?: boolean | null
18}
19

限制

  • 問題為必填,最多 200 個字元。
  • 一個投票需有 2 到 10 個選項。
  • 選項標籤為必填,最多 100 個字元,且在同一投票內必須唯一(不區分大小寫)。
  • closesAt 在建立投票時必須是未來的時間。若要立即關閉投票,請以過去的日期進行 PATCH。

網站設定

投票遵循您的網站設定,您可以在 Customize Widget 下進行更改:

  • 必須先啟用投票功能才能建立投票,否則 API 會回應 polls-disabled。
  • 投票可以限制為已登入的使用者,在此情況下,僅帶有 anonUserId 的投票會被拒絕並回應 poll-login-required。

投票結果結構 Internal Link

A PollVote 是單個使用者對投票的回答。投票本身顯示的計數會與這些保持同步,因此只有在想知道 誰 投了哪個選項,而不是總計時才需要這些資料。

每位投票者在同一個投票中最多只能有一票。再次投票會將他們原本的投票移至新選項,而不是新增第二票,updatedAt 會記錄此變更的時間。

voterId 為投票者登入時的 userId,若未登入則為 anonUserId。

PollVote 結構
Copy Copy
1
2interface PollVote {
3 id: string
4 tenantId: string
5 commentId: string
6 urlId: string
7 /** 投票者登入時的 userId,否則為 anonUserId。 **/
8 voterId: string
9 optionId: string
10 createdAt: string
11 /** 投票者最後一次將投票移至不同選項的時間。 **/
12 updatedAt?: string
13}
14

隱私

投票的 privacy 設定對此 API 的作用方式與在評論小工具中的作用方式相同:

  • Anonymous(預設):沒有人能看到任何人的投票方式,因此投票內容無法被讀取。GET /api/v1/poll-votes 與 GET /api/v1/poll-votes/:id 會回傳 poll-anonymous。投票的計數仍可從 GET /api/v1/polls/:commentId 取得。
  • Admins and moderators:您的 API 金鑰屬於您網站的管理員,因此可以讀取投票。
  • Everyone:投票內容可被讀取。

投票一旦有投票紀錄,其隱私設定只能收緊,無法放寬。

待處理 Webhook 事件結構 Internal Link

A PendingWebhookEvent 物件代表一個排隊中的 webhook 事件,處於待處理狀態。

PendingWebhookEvent 物件會自動建立,且無法透過 API 手動建立。它們也會在一年後過期。
可以刪除它們,這會將任務從佇列中移除。

有不同的事件類型 - 請檢查 eventType(OutboundSyncEventType)和 type(OutboundSyncType)。

此 API 的常見使用情境是實作自訂監控。您可能會定期呼叫 /count 端點,以根據給定的篩選條件查詢未處理的計數。

PendingWebhookEvent 物件的結構如下:

PendingWebhookEvent 結構
Copy Copy
1
2enum OutboundSyncEventType {
3 Create: 0,
4 Delete: 1,
5 Update: 2
6}
7
8enum OutboundSyncType {
9 /** 針對 WordPress 的同步任務。 **/
10 WP: 0,
11 Webhook: 1
12}
13
14interface PendingWebhookEvent {
15 id: string
16 /** 與事件相關聯的評論 ID。 **/
17 commentId: string
18 /** 事件發生時的評論物件。我們於 2023 年 11 月開始加入此欄位。 **/
19 comment: Comment
20 /** 可能與評論相關聯的外部 ID。 **/
21 externalId: string | null
22 createdAt: Date
23 tenantId: string
24 attemptCount: number
25 /** 在首次嘗試之前以及每次失敗後設定。 **/
26 nextAttemptAt: Date
27 /** 此事件是建立、刪除或更新... **/
28 eventType: OutboundSyncEventType
29 /** 要執行的同步類型(WordPress、呼叫 API 等)。 **/
30 type: OutboundSyncType
31 /** 與評論匹配的網域。我們使用此網域來選擇 API 金鑰。 **/
32 domain: string
33 /** 最近發生的錯誤。此類型未定型,為發生情況的「轉儲」。通常包含具有 statusCode、body 以及 headers 映射的物件。 **/
34 lastError: object | null
35}
36

單點登入使用者結構 Internal Link

FastComments 提供一個易於使用的 SSO 解決方案。使用基於 HMAC 的整合更新使用者資訊就像讓使用者載入含有更新 payload 的頁面一樣簡單。

然而,可能會希望在該流程之外管理使用者,以提高應用程式的一致性。

SSO 使用者 API 提供一種對我們稱為 SSOUsers 的物件進行 CRUD 的方式。這些物件與一般 Users 不同,為了型別安全而分開保存。

SSOUser 物件的結構如下:

SSOUser 結構
Copy Copy
1
2interface SSOUser {
3 id: string
4 username: string
5 email?: string
6 websiteUrl?: string
7 signUpDate: number
8 createdFromUrlId?: string
9 loginCount?: number
10 avatarSrc?: string
11 optedInNotifications?: boolean
12 optedInSubscriptionNotifications?: boolean
13 displayLabel?: string
14 displayName?: string
15 isAccountOwner?: boolean // 管理員權限 - 設定此標記的 SSO 使用者會被當作 SSO 管理員計費(與一般 SSO 使用者分開)
16 isAdminAdmin?: boolean // 管理員權限 - 設定此標記的 SSO 使用者會被當作 SSO 管理員計費(與一般 SSO 使用者分開)
17 isCommentModeratorAdmin?: boolean // 版主權限 - 設定此標記的 SSO 使用者會被當作 SSO 版主計費(與一般 SSO 使用者分開)
18 /** 若為 null,將不會對該使用者套用存取控制。若為空陣列,該使用者將無法看到任何頁面或在 @ 提及其他使用者。 **/
19 groupIds?: string[] | null
20 createdFromSimpleSSO?: boolean
21 /** 不允許其他使用者在該使用者的個人檔案上查看其活動(包括留言)。預設為 true,以預設提供安全的個人檔案。 **/
22 isProfileActivityPrivate?: boolean
23 /** 不允許其他使用者在該使用者的個人檔案上留下留言,或查看現有的個人檔案留言。預設為 false。 **/
24 isProfileCommentsPrivate?: boolean
25 /** 不允許其他使用者發送私人訊息給該使用者。預設為 false。 **/
26 isProfileDMDisabled?: boolean
27 karma?: number
28 /** 使用者徽章的選用設定。 **/
29 badgeConfig?: {
30 /** 指派給使用者的徽章 ID 陣列。限 30 個徽章。順序會保留。這些為在所有頁面可見的全域徽章。 **/
31 badgeIds: string[]
32 /** 只針對當前頁面(urlId)作用的徽章 ID 陣列。這些徽章僅在被指定的頁面上顯示。 **/
33 pageBadgeIds?: string[]
34 /** 若為 true,則以提供的徽章替換所有現有顯示的徽章。全域與頁面範圍的徽章獨立覆蓋。若為 false,則會新增到現有徽章。 **/
35 override?: boolean
36 /** 若為 true,會依租戶設定更新徽章顯示屬性。 **/
37 update?: boolean
38 }
39}
40

SSO 使用者計費

SSO 使用者的計費會根據其權限標記而不同:

  • Regular SSO Users:沒有管理或版主權限的使用者會以一般 SSO 使用者計費
  • SSO Admins:具有 isAccountOwner 或 isAdminAdmin 標記的使用者會被另外計費為 SSO 管理員(與一般租戶管理員相同費率)
  • SSO Moderators:具有 isCommentModeratorAdmin 標記的使用者會被另外計費為 SSO 版主(與一般版主相同費率)

重要:為避免重複計費,系統會自動根據電子郵件地址對 SSO 使用者與一般租戶使用者及版主進行去重。如果 SSO 使用者的電子郵件與一般租戶使用者或版主相同,將不會重複計費。

存取控制

使用者可以被劃分為群組。這就是 groupIds 欄位的用途,且為選用。

@提及

預設情況下,當輸入 @ 字元時,@mentions 將使用 username 搜尋其他 SSO 使用者。如果使用 displayName,當有符合 displayName 的結果時,會忽略符合 username 的結果,且 @mention 的搜尋結果將使用 displayName。

訂閱

在 FastComments 中,使用者可以透過在留言元件中點擊鈴鐺圖示並點選訂閱,來訂閱某個頁面。

對於一般使用者,我們會根據他們的通知設定發送通知電子郵件。

對於 SSO 使用者,為了向後相容我們將此行為做了區分。僅當您將 optedInSubscriptionNotifications 設為 true 時,使用者才會收到這些額外的訂閱通知電子郵件。

徽章

您可以使用 badgeConfig 屬性為 SSO 使用者指派徽章。徽章是顯示在使用者名稱旁的視覺標示。

  • badgeIds - 指派給使用者的徽章 ID 陣列。這些為在所有頁面可見的全域徽章。必須是您 FastComments 帳戶中已建立的有效徽章 ID。限制為 30 個徽章。
  • pageBadgeIds - 選用的徽章 ID 陣列,僅限於當前頁面(urlId)。這些徽章只會在指派它們的頁面上顯示。不同頁面對同一使用者可以有不同的頁面範圍徽章。
  • override - 若為 true,所有現有顯示的徽章將被提供的徽章取代。全域與頁面範圍的徽章獨立覆蓋 — 覆蓋全域徽章不會影響頁面範圍徽章,反之亦然。若為 false 或省略,則會將提供的徽章新增到任何現有徽章上。
  • update - 若為 true,使用者登入時會從租戶設定更新徽章顯示屬性。

訂閱結構 Internal Link

一個 Subscription 物件代表使用者的訂閱。

Subscription 物件會在使用者在評論小工具中點擊通知鈴鐺並點選 "訂閱此頁面" 時建立。

也可以透過 API 建立訂閱。

擁有 Subscription 物件會在與該 Subscription 相關聯的頁面 根層留下新留言時,會產生 Notification 物件並發送電子郵件。

是否發送電子郵件取決於使用者類型。對於一般使用者,這取決於 optedInNotifications。對於 SSO 使用者,則取決於 optedInSubscriptionNotifications。請注意,有些應用程式可能沒有可由網頁存取的頁面概念,在這種情況下,只需將 urlId 設為 您要訂閱的項目的 id(與傳遞給評論小工具的 urlId 值相同)。

以下為 Subscription 物件的結構:

訂閱結構
Copy Copy
1
2interface Subscription {
3 id: string
4 tenantId: string
5 /** 使用 SSO 時,使用者 id 的格式為 `<tenant id>:<user id>`。 **/
6 userId: string
7 anonUserId?: string
8 urlId: string
9 url?: string
10 pageTitle?: string
11 createdAt: string // 日期字串
12}
13

租戶每日使用量結構 Internal Link

A TenantDailyUsage 物件代表租戶在特定日期的使用情況。如果在特定日期內該租戶沒有任何活動,則該日不會有 TenantDailyUsage 物件。

TenantDailyUsage 物件 不是即時的,可能會比實際使用量落後數分鐘。

TenantDailyUsage 物件的結構如下:

TenantDailyUsage 結構
Copy Copy
1
2export interface TenantDailyUsage {
3 yearNumber: number
4 monthNumber: number
5 dayNumber: number
6 commentFetchCount?: number
7 commentCreateCount?: number
8 conversationCreateCount?: number
9 voteCount?: number
10 accountCreatedCount?: number
11 userMentionSearch?: number
12 hashTagSearch?: number
13 gifSearchTrending?: number
14 gifSearch?: number
15 apiCreditsUsed?: number
16 createdAt: string
17 billed: boolean
18 /** Ignored for billing. **/
19 ignored: boolean
20}
21

租戶結構 Internal Link

The Tenant 定義 FastComments.com 的客戶。具有白標存取權的租戶可以透過 API 建立這些租戶。白標租戶無法建立其他白標租戶(僅允許一層巢狀)。

Tenant 物件的結構如下:

租戶結構
Copy Copy
1
2export enum SiteType {
3 Unknown = 0,
4 WordPress = 1
5}
6
7/** 這也可以透過 DomainConfig API 處理。 **/
8export interface TenantDomainConfig {
9 domain: string
10 emailFromName?: string
11 emailFromEmail?: string
12 createdAt?: string,
13 siteType?: FastCommentsSiteType, // 你可能想要使用 Unknown
14 logoSrc?: string, // 原始圖片路徑
15 logoSrc100px?: string, // 為縮圖調整大小
16 footerUnsubscribeURL?: string,
17 emailHeaders?: Record<string, string>,
18 disableUnsubscribeLinks?: boolean,
19 dkim?: {
20 domainName: string,
21 keySelector: string,
22 privateKey: string
23 }
24}
25
26export interface TenantBillingInfo {
27 name: string
28 address: string
29 city: string
30 state: string
31 zip: string
32 country: string
33}
34
35export enum TenantPaymentFrequency {
36 Monthly = 0,
37 Annually = 1
38}
39
40export interface Tenant {
41 id: string
42 name: string
43 email?: string
44 signUpDate: number; // number 是因為「歷史」原因
45 packageId?: string | null
46 paymentFrequency?: TenantPaymentFrequency
47 billingInfoValid?: boolean
48 billingHandledExternally?: boolean
49 createdBy?: string
50 isSetup?: boolean
51 domainConfiguration: FastCommentsAPITenantDomainConfig[]
52 billingInfo?: FastCommentsAPITenantBillingInfo
53 stripeCustomerId?: string
54 stripeSubscriptionId?: string
55 stripePlanId?: string
56 enableProfanityFilter?: boolean
57 enableSpamFilter?: boolean
58 lastBillingIssueReminderDate?: string
59 removeUnverifiedComments?: boolean
60 unverifiedCommentsTTLms?: number
61 commentsRequireApproval?: boolean
62 autoApproveCommentOnVerification?: boolean
63 sendProfaneToSpam?: boolean
64 /** @readonly - 根據 packageId 計算。 **/
65 hasFlexPricing?: boolean
66 /** @readonly **/
67 flexLastBilledAmount?: number
68 /** @readonly - 根據 packageId 計算。 **/
69 hasAuditing?: boolean
70 /** 你可以在租戶上儲存鍵值對,並用於查詢。鍵不能包含 "." 或 "$",或長於 100 個字元。值不得超過 2k 字元。 **/
71 meta?: Record<string, string | null>
72}
73

使用者結構 Internal Link

User 是一個物件,代表所有使用者的最常見共同基準。

請注意,在 FastComments 中,我們有多種不同的使用者使用情境:

  • Secure SSO
  • Simple SSO
  • 租戶使用者(例如:管理員)
  • 留言者

此 API 適用於留言者以及透過 Simple SSO 建立的使用者。基本上,任何透過您的網站建立的使用者都可以透過此 API 存取。租戶使用者也可以透過此方式取得,但若使用 /tenant-users/ API,您將能獲得更多資訊。

對於 Secure SSO,請使用 /sso-users/ API。

您無法更新這些類型的使用者。他們是透過您的網站建立帳號的,因此我們僅提供一些基本的唯讀存取權限,但您無法進行更改。如果您想要這種類型的流程,您需要設定 Secure SSO。

User 物件的結構如下:

User 結構
Copy Copy
1
2export interface User {
3 /** 這也是評論物件中用作 userId 的 id。 **/
4 id: string
5 username: string
6 /** 例如:留言者部落格的連結。 **/
7 websiteUrl?: string
8 email: string
9 signUpDate: number
10 createdFromUrlId: string
11 createdFromTenantId: string
12 avatarSrc?: string
13 locale: FastCommentsLocale
14 displayLabel?: string
15 karma?: number
16}
17

投票結構 Internal Link

一個 Vote 物件代表使用者所留下的投票。

留言與投票之間的關係由 commentId 定義。

Vote 物件的結構如下:

Vote 結構
Copy Copy
1
2interface Vote {
3 id: string
4 urlId: string
5 commentId: string
6 userId: string
7 direction: 1 | -1
8 createdAt: string
9}
10

問題設定結構 Internal Link

FastComments 提供了一種建立問題並彙總其結果的方法。問題的一個範例(以下稱為 QuestionConfig) 可以是星級評分、滑桿,或 NPS 問題(由 type 決定)。

問題資料可以單獨彙總、合併彙總、按時間、整體、按頁面等方式彙總。

此框架具備建置客戶端小工具(由您的伺服器置於此 API 之前)、管理儀表板與報表工具所需的所有功能。

首先,我們需要定義一個 QuestionConfig。結構如下:

QuestionConfig 結構
Copy Copy
1
2type QuestionConfigType = 'nps' | 'slider' | 'star' | 'thumbs';
3
4interface QuestionConfig {
5 id: string
6 tenantId: string
7 name: string
8 question: string
9 helpText?: string
10 createdAt: string
11 createdBy: string
12 /** 只讀 - 每新增一個回應即遞增。 **/
13 usedCount: number
14 /** 表示設定最後使用(有結果留下)的日期字串。 **/
15 lastUsed?: string
16 type: QuestionConfigType
17 numStars?: number
18 min?: number
19 max?: number
20 defaultValue?: number
21 labelNegative?: string
22 labelPositive?: string
23 subQuestionIds?: string[]
24 alwaysShowSubQuestions?: boolean
25 reportingOrder: number
26}
27

問題結果結構 Internal Link

為了儲存問題的結果,您需要建立一個 QuestionResult。接著您可以彙總問題結果,並且將它們 與評論關聯以便進行報告。

QuestionResult 結構
Copy Copy
1
2interface QuestionResultMeta {
3 name: string
4 values: string[]
5}
6
7interface QuestionResult {
8 id: string
9 tenantId: string
10 urlId: string
11 anonUserId?: string
12 userId?: string
13 createdAt?: string
14 value: number
15 commentId?: string
16 questionId: string
17 meta?: QuestionResultMeta[]
18}
19

使用者徽章結構 Internal Link

UserBadge 是一個物件,代表在 FastComments 系統中指派給使用者的徽章。

徽章可以根據使用者的活動自動指派(例如留言數、回覆時間、資深狀態),也可以由網站管理員手動指派。

UserBadge 物件的結構如下:

UserBadge 結構
Copy Copy
1
2export interface UserBadge {
3 /** 此使用者徽章指派的唯一識別碼 */
4 id: string
5 /** 此徽章指派給的使用者 ID */
6 userId: string
7 /** 租戶徽章目錄中的徽章定義 ID */
8 badgeId: string
9 /** 建立/指派此徽章的租戶 ID */
10 fromTenantId: string
11 /** 此徽章的建立時間(自 epoch 起的毫秒數) */
12 createdAt?: number
13 /** 使用者收到此徽章的時間(自 epoch 起的毫秒數) */
14 receivedAt?: number
15 /**
16 * 徽章類型:
17 * 0=CommentCount, 1=CommentUpVotes, 2=CommentReplies, 3=CommentsPinned,
18 * 4=Veteran, 5=NightOwl, 6=FastReplyTime, 7=ModeratorCommentsDeleted,
19 * 8=ModeratorCommentsApproved, 9=ModeratorCommentsUnapproved, 10=ModeratorCommentsReviewed,
20 * 11=ModeratorCommentsMarkedSpam, 12=ModeratorCommentsMarkedNotSpam, 13=RepliedToSpecificPage,
21 * 14=Manual
22 */
23 type: number
24 /** 對於基於門檻的徽章,此為門檻值 */
25 threshold?: number
26 /** 徽章的名稱/標籤 */
27 name?: string
28 /** 徽章的詳細說明 */
29 description?: string
30 /** 徽章上顯示的文字 */
31 displayLabel?: string
32 /** 徽章上顯示圖片的 URL */
33 displaySrc?: string
34 /** 徽章的背景顏色(十六進位碼) */
35 backgroundColor?: string
36 /** 徽章的邊框顏色(十六進位碼) */
37 borderColor?: string
38 /** 徽章的文字顏色(十六進位碼) */
39 textColor?: string
40 /** 用於樣式的額外 CSS 類別 */
41 cssClass?: string
42 /** 對於資深使用者徽章,此為時間門檻(毫秒) */
43 veteranUserThresholdMillis?: number
44 /** 此徽章是否顯示在使用者的留言上 */
45 displayedOnComments: boolean
46 /** 徽章的顯示順序 */
47 order?: number
48 /** 若有設定,此徽章僅顯示在符合 urlId 的頁面上。全域徽章則為 Null。 */
49 urlId?: string | null
50}
51

使用者徽章進度結構 Internal Link

UserBadgeProgress 是一個物件,表示使用者在 FastComments 系統中獲取各種徽章的進度。

此追蹤有助於根據使用者在您的社群中的活動與參與來決定何時應該自動授予徽章。

UserBadgeProgress 物件的結構如下:

UserBadgeProgress 結構
Copy Copy
1
2export interface UserBadgeProgress {
3 /** 此進度記錄的唯一識別碼 */
4 id: string
5 /** 此進度記錄所屬的租戶 ID */
6 tenantId: string
7 /** 此進度記錄所追蹤的使用者 ID */
8 userId: string
9 /** 使用者在系統中的第一則評論的 ID */
10 firstCommentId?: string
11 /** 使用者第一則評論的日期(自 epoch 起的毫秒數) */
12 firstCommentDate?: number
13 /** 根據使用者活動自動計算的信任係數 */
14 autoTrustFactor?: number
15 /** 由管理員手動設定的信任係數 */
16 manualTrustFactor?: number
17 /** 包含各種指標的詳細進度物件,鍵與 BadgeType enum 相符 */
18 progress: {
19 /** 0: CommentCount - 使用者發表評論的數量 */
20 '0'?: number
21 /** 1: CommentUpVotes - 使用者收到的讚數 */
22 '1'?: number
23 /** 2: CommentReplies - 使用者發表的回覆數 */
24 '2'?: number
25 /** 3: CommentsPinned - 使用者被固定的評論數 */
26 '3'?: number
27 /** 4: Veteran - 使用者帳戶年齡 */
28 '4'?: number
29 /** 5: NightOwl - 使用者在夜間時段發文的次數 */
30 '5'?: number
31 /** 6: FastReplyTime - 平均回覆時間(毫秒) */
32 '6'?: number
33 /** 7: ModeratorCommentsDeleted - 對於管理員徽章,刪除的評論數 */
34 '7'?: number
35 /** 8: ModeratorCommentsApproved - 對於管理員徽章,核准的評論數 */
36 '8'?: number
37 /** 9: ModeratorCommentsUnapproved - 對於管理員徽章,未核准的評論數 */
38 '9'?: number
39 /** 10: ModeratorCommentsReviewed - 對於管理員徽章,已審核的評論數 */
40 '10'?: number
41 /** 11: ModeratorCommentsMarkedSpam - 對於管理員徽章,被標記為垃圾評論的數量 */
42 '11'?: number
43 /** 12: ModeratorCommentsMarkedNotSpam - 對於管理員徽章,被標記為非垃圾評論的數量 */
44 '12'?: number
45 /** 13: RepliedToSpecificPage - 每個頁面的回覆數量 */
46 '13'?: Record<string, number>
47 }
48}
49

總結

我們希望您覺得我們的 API 文件詳盡且易於理解。如果您發現任何缺漏,請在下方告知我們。