LogoFastComments.com

The FastComments API

FastComments provides an API for searching and fetching data in your account.

In this documentation, you will find all supported resources by the API documented with their request and response types.

API Resources Internal Link

The FastComments API exposes the following resources to you:

  • Comments
  • Pages
  • SSO Users
  • Votes

Pages and Votes are currently read-only.

Resource Usage

It should be noted that fetching data from the API is counted as usage on your account.

Each resource will list what that usage is in its own section.

If a resource says "1 Page Load: = 1000 Votes Max", this means that a request that returns 1000 votes will count as one page load (or credit) on your account. Your account has a limited number of these based on its tier (the same as page loads). If the API returns 1,500 Vote objects, this would count as two page loads on your account. If you make two API calls, and each return 10 Votes, that also counts as two page loads as they are separate requests.

Note!

We suggest reading the Pages documentation first, to help limit confusion when determining what values to pass for urlId in the Comment API.

Comment Structure Internal Link

A Comment object represents a comment left by a user.

The relationship between parent and child comments is defined via parentId;

The structure for the Comment object is as follows:

Comment Structure
1
2interface Comment {
3 id: string;
4 /** The user that wrote the comment. Created automatically when saving a comment with a name/email. **/
5 userId?: string|null;
6 /** A "cleaned" version of the urlId you passed us. When saving, you specify this field, but when you fetch the comment back this will be "cleaned" and your original value moved to "urlIdRaw". **/
7 urlId: string;
8 /** READONLY: The original urlId you passed us. **/
9 urlIdRaw?: string;
10 /** The URL to the location that this comment is visible, like a blog post. **/
11 url: string;
12 /** The title of the page this comment was on. **/
13 pageTitle?: string;
14 /** The commenter's name. Always required. If not available, set to something like "Anonymous". **/
15 commenterName: string;
16 /** The commenter's email. Required if anonymous commenting is off. **/
17 commenterEmail?: string;
18 /** The commenter's link (for example, their blog). **/
19 commenterLink?: string;
20 /** The commenter's raw comment. **/
21 comment: string;
22 /** The locale the comment is in. If not provided, will be derived from the language accept HTTP header. **/
23 locale?: 'en_us' | 'es_es' | 'fr_fr' | 'pl_pl' | 'de_de' | 'it_it' | 'ru_ru' | 'ja_jp';
24 /** READONLY: The commenter's comment parsed into HTML. **/
25 commentHTML?: string;
26 /** If we're replying to a comment, this is the ID that we are replying to. **/
27 parentId?: string|null;
28 /** The date the comment was left, in UTC epoch. **/
29 date: number;
30 /** The "karma" of the comment (= votes up + votes down). **/
31 votes?: number;
32 /** Is the user and this comment verified? **/
33 verified: boolean;
34 /** The user's avatar. **/
35 avatarSrc?: string;
36 /** READONLY: Does the comment contain images? **/
37 hasImages?: boolean;
38 /** READONLY: Does the comment contain links? **/
39 hasLinks?: boolean;
40 /** READONLY: Is the comment by an admin? **/
41 isByAdmin?: boolean;
42 /** READONLY: Is the comment by a moderator? **/
43 isByModerator?: boolean;
44 /** Is the comment pinned? **/
45 isPinned?: boolean;
46 /** The "display label" for the comment - for example "Admin", "Moderator", or something like "VIP User". **/
47 displayLabel?: string;
48 /** A star rating. **/
49 rating?: number;
50 /** Whether or not notifications were sent for this comment for commenters. To prevent notifications being sent on imports, set this to true. **/
51 notificationSentForParent?: boolean;
52 /** Whether or not notifications were sent for this comment for tenant users. To prevent notifications being sent on imports, set this to true. **/
53 notificationSentForParentTenant?: boolean;
54 /** READONLY: The @mentions written in the comment that were successfully parsed. **/
55 mentions?: CommentUserMention[]
56}
57

Some of these fields are marked READONLY - these are returned by the API but cannot be set.

When users are tagged in a comment, the information is stored in a list called mentions. Each object in that list has the following structure.

The Comment Mentions Object
External Link
1
2interface CommentUserMention {
3 /** The user id. For SSO users, this will have your tenant id prefixed. **/
4 id: string
5 /** The final @mention tag text, including the @ symbol. **/
6 tag: string
7 /** The original @mention tag text, including the @ symbol. **/
8 rawTag: string
9 /** What type of user was tagged. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** If the user opts out of notifications, this will still be set to true. **/
12 sent: boolean
13}
14

GET /api/v1/comments Internal Link

Resource: Comment as GET /api/v1/comments Credit Cost: 10

Comments must be fetched by-page. You can fetch comments for all pages at once, but use caution.

Comments cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/comments?tenantId=demo&page=0&urlId=test&API_KEY=DEMO_API_SECRET&direction=MR'
4
Comments Request Structure
1
2interface CommentsRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5 /** The urlId (page url, or article id) the comments are associated with. **/
6 urlId: string;
7 /** The page to fetch, starting with 0. Pass -1 for all comments. **/
8 page: number;
9 /** The sort direction. Default is MR (Most Relevant). Other options are OF (Oldest First) and NF (Newest First). **/
10 direction: 'MR' | 'OF' | 'NF';
11}
12
Comments Response Structure
1
2interface CommentsResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id' | 'missing-date';
6 /** Included on failure. **/
7 reason?: string;
8 /** The comments! **/
9 comments: Comment[];
10}
11

Helpful Tip

The Comment API requires a urlId. You can call the Pages API first, to see what the urlId values available to you look like.

POST /api/v1/comments Internal Link

Resource: Comment as POST /api/v1/comments Credit Cost: 10

This API endpoint provides the ability to create comments.

Common use cases are custom UIs, integrations, or imports.

Notes:

  • This API will automatically create user objects in our system.
  • Trying to save two comments with different emails, but the same username, will result in an error for the second comment.
  • If you are specifying parentId, and a child comment has notificationSentForParent as false, we will send notifications for the parent comment. This is done every hour (we batch the notifications together to decrease the number of emails sent).
  • This API can be "live" if desired.
  • Comments created via this API will show up in the Analytics and Moderation pages of the admin app.
  • "bad words" are still masked in the commenter names and comment text if the setting is turned on.
  • Comments created via this API can still be checked for spam if desired.
Comment POST cURL Example
1
2curl --request POST \
3 --url 'https://fastcomments.com/api/v1/comments?tenantId=demo&API_KEY=DEMO_API_SECRET&isLive=true&doSpamCheck=true' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "urlId": "some-place",
7 "comment": "some-comment",
8 "commenterName": "some-commenter-name",
9 "commenterEmail": "fordperfect@spaceship.com",
10 "comment": "some comment",
11 "votes": 1,
12 "verified": true,
13 "reviewed": true,
14 "notificationSentForParent": true,
15 "notificationSentForParentTenant": true,
16 "avatarSrc": "https://static.fastcomments.com/1605337537848-DSC_0841.JPG",
17 "isSpam": false,
18 "approved": true,
19 "locale": "en_us",
20 "date": 1622644382148
21}'
22
Comment POST Request Structure
1
2// Note that urlId is not here - it is in the request body.
3interface CommentPostQueryParams {
4 tenantId: string;
5 API_KEY: string;
6 doSpamCheck?: 'true' | 'false';
7 isLive?: 'true' | 'false';
8}
9
Comment POST Response Structure
1
2
3interface CommentPostResponse {
4 status: 'success' | 'failed';
5 /** Included on failure. **/
6 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id' | 'empty-comment';
7 /** Included on failure. **/
8 reason?: string;
9 /** The created comment. **/
10 comment?: Comment;
11 /** The associated user, which may or may not have already existed. **/
12 user?: User;
13}
14

HashTag Structure Internal Link

A HashTag object represents a tag that can be left by a user. HashTags can be used to link to an external piece of content or to tie related comments together.

The structure for the HashTag object is as follows:

HashTag Structure
1
2interface HashTag {
3 /** Should start with the "#" or desired character. **/
4 tag: string;
5 /** An optional URL that the hashtag can point to. Instead of filtering comments by hashtag, the UI will redirect to this upon click. **/
6 url?: string;
7 /** READONLY **/
8 createdAt: string;
9}
10

Notes:

  • In some of the API endpoints you will see that the hashtag is used in the URL. Remember to URI-Encoded values. For example, # should instead be represented as %23.
  • Some of these fields are marked READONLY - these are returned by the API but cannot be set.

GET /api/v1/hash-tags Internal Link

Resource: HashTag as GET /api/v1/hash-tags Credit Cost: 1

This API uses pagination, provided by the page query parameter. HashTags are returned in pages of 100, ordered by tag.

HashTag cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/hash-tags?tenantId=demo&page=0&API_KEY=DEMO_API_SECRET'
4
HashTag Request Structure
1
2interface HashTagsRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5 /** The page to fetch, starting with 0. **/
6 page: number;
7}
8
HashTag Response Structure
1
2interface HashTagsResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key';
6 /** Included on failure. **/
7 reason?: string;
8 /** The hashtags! **/
9 hashTags: HashTag[];
10}
11

PATCH /api/v1/hash-tags/:tag Internal Link

Resource: HashTag as PATCH /api/v1/hash-tags/:tag Credit Cost: 1

This route provides the ability to update a single HashTag.

HashTag Update cURL Example
1
2curl --request PATCH \
3 --url 'https://fastcomments.com/api/v1/hash-tags/%23example_hash_tag?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "url": "https://example.com/some-`page`"
7}'
8
HashTag Update Request Structure
1
2interface HashTagPatchQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
HashTag Update Response Structure
1
2interface HashTagPatchResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-hash-tag' | 'tag-does-not-exist' | 'url-too-long' | 'invalid-tag' | 'already-exists';
6 /** Included on failure. **/
7 reason?: string;
8 hashTag?: HashTag; // We return the complete updated hashtag on success.
9}
10

POST /api/v1/hash-tags Internal Link

Resource: HashTag as POST /api/v1/hash-tags Credit Cost: 1

This route provides the ability to add a single HashTag.

HashTag Create cURL Example
1
2curl --request PATCH \
3 --url 'https://fastcomments.com/api/v1/hash-tags?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "tag": "#example",
7 "url": "https://example.com/some-page"
8}'
9
HashTag Create Request Structure
1
2interface HashTagPostQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
HashTag Create Response Structure
1
2interface HashTagPostResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-hash-tag' | 'tag-does-not-exist' | 'url-too-long' | 'invalid-tag';
6 /** Included on failure. **/
7 reason?: string;
8 hashTag?: HashTag; // We return the complete created hashtag on success.
9}
10

POST /api/v1/hash-tags/bulk Internal Link

Resource: HashTag as POST /api/v1/hash-tags/bulk Credit Cost: 1

This route provides the ability to add up to 100 HashTag objects at once.

HashTag Bulk Create cURL Example
1
2curl --request PATCH \
3 --url 'https://fastcomments.com/api/v1/hash-tags/bulk?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "tags": [
7 {
8 "tag": "#example",
9 "url": "https://example.com/some-page"
10 }
11 ]
12}'
13
HashTag Bulk Create Request Structure
1
2interface HashTagPostQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
HashTag Bulk Create Response Structure
1
2interface HashTagBulkPostResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-hash-tag' | 'tag-does-not-exist' | 'url-too-long' | 'invalid-tag';
6 /** Included on failure. **/
7 reason?: string;
8 results?: HashTagPostResponse[]; // We return a list of HashTagPostResponse objects for each provided tag.
9}
10

DELETE /api/v1/hash-tags/:tag Internal Link

Resource: HashTag as DELETE /api/v1/hash-tags/:tag Credit Cost: 1

This route provides the removal of a HashTag user by the provided tag.

Note that unless automatic HashTag creation is disabled, hashtags can be re-created by a user providing the hashtag when commenting.

HashTag Removal cURL Example
1
2curl --request DELETE \
3 --url 'https://fastcomments.com/api/v1/hash-tags/%23example_hash_tag?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
HashTag Removal Request Structure
1
2interface HashTagDeleteQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
HashTag Removal Response Structure
1
2interface HashTagDeleteResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-hash-tag' | 'tag-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8}
9

Page Structure Internal Link

A Page object represents the page that many comments may belong to. This relationship is defined by urlId.

A Page stores information such as the page title, comment count, and urlId.

The structure for the Page object is as follows:

Page Structure
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 /** Setting this to null means all SSO users can see the page. An empty list means it is closed to call users. **/
11 accessibleByGroupIds?: string[] | null;
12}
13

GET /api/v1/pages Internal Link

Resource: Page as GET /api/v1/pages Credit Cost: 10

You can currently only fetch all pages (or a single page via /by-url-id) associated with your account. If you'd like more fine-grained searching, reach out to us.

Pages cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/pages?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
Pages Request Structure
1
2interface PagesRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
Pages Response Structure
1
2interface PagesResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key';
6 /** Included on failure. **/
7 reason?: string;
8 pages: Page[]
9}
10

Helpful Tip

The Comment API requires a urlId. You can call the Pages API first, to see what the urlId values available to you look like.

GET /api/v1/pages/by-url-id Internal Link

Resource: Page as GET /api/v1/pages/by-url-id Credit Cost: 1

Individual pages can be fetched by their corresponding urlId. This can be useful for looking up page titles or comment counts.

Page by URL ID cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/pages/by-url-id?tenantId=demo&API_KEY=DEMO_API_SECRET&urlId=example-id-or-url'
4
Page By URL ID Request Structure
1
2interface PagesRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5 urlId: string;
6}
7
Page by URL ID Response Structure
1
2interface PagesResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id';
6 /** Included on failure. **/
7 reason?: string;
8 page?: Page[] | null;
9}
10

Helpful Tip

Remember to URI Encode values like the urlId.

PATCH /api/v1/pages/:id Internal Link

Resource: Page as PATCH /api/v1/pages/:id Credit Cost: 1

This route provides the ability to update a single Page.

Page Update cURL Example
1
2curl --request PATCH \
3 --url 'https://fastcomments.com/api/v1/pages/my-page-id?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "url": "https://example.com/some-page"
7}'
8
Page Update Request Structure
1
2interface PagePatchQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
Page Update Response Structure
1
2interface PagePatchResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id' | 'missing-id' | 'page-does-not-exist' | 'empty-request' | 'internal' | 'invalid-input' | 'invalid-title' | 'extra-params' | 'accessible-by-group-ids-not-array' | 'too-many-group-ids' | 'group-id-too-large';
6 /** Included on failure. **/
7 reason?: string;
8 user?: Page; // We return the complete updated page on success.
9}
10

Note

Some parameters in the Page object get automatically updated. These are the counts and title attributes. Counts cannot be updated via the API since they are calculated values. The page title can be set via the API, but would get overwritten if the comment widget is used on a page with the same urlId and a different page title.

POST /api/v1/pages Internal Link

Resource: Page as POST /api/v1/pages Credit Cost: 1

This API endpoint provides the ability to create pages.

A common use cases is access control.

Notes:

  • If you've commented on a comment thread, or called the API to create a Comment, you've already created a Page object! You can try fetching it via the /by-url-id Page route, passing in the same urlId passed to the comment widget.
  • The Page structure contains some calculated values. Currently, these are commentCount and rootCommentCount. They are populated automatically and cannot be set by the API. Attempting to do so will cause the API to return an error.
Page POST cURL Example
1
2curl --request POST \
3 --url 'https://fastcomments.com/api/v1/pages?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "title": "Test Page",
7 "url": "some0-url",
8 "urlId": "page2",
9 "accessibleByGroupIds": ["SOME_GROUP_ID"]
10}'
11
Page POST Request Structure
1
2interface PagePostQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
Page POST Response Structure
1
2
3interface PagePostResponse {
4 status: 'success' | 'failed';
5 /** Included on failure. **/
6 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id' | 'empty-request' | 'internal' | 'invalid-input' | 'invalid-title' | 'extra-params' | 'accessible-by-group-ids-not-array' | 'too-many-group-ids' | 'group-id-too-large';
7 /** Included on failure. **/
8 reason?: string;
9 /** The created page. **/
10 page?: Page;
11}
12

DELETE /api/v1/pages/:id Internal Link

Resource: Page as DELETE /api/v1/pages/:id Credit Cost: 1

This route provides the removal of a single page by id.

Note that interacting with the comment widget for a page with the same urlId will simply recreate the Page seamlessly.

Page Removal cURL Example
1
2curl --request DELETE \
3 --url 'https://fastcomments.com/api/v1/pages/some-page-id?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
Page Removal Request Structure
1
2interface PageDeleteQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
Page Removal Response Structure
1
2interface PageDeleteResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-id' | 'page-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8}
9

SSOUser Structure Internal Link

FastComments provides an easy to use SSO solution. Updating a user's information with the HMAC-based integration is as simple as having the user load the page with an updated payload.

However, it may be desirable to manage a user outside that flow, to improve consistency of your application.

The SSO User API provides a way to CRUD objects that we call SSOUsers. These objects are different from regular Users and kept separate for type safety.

The structure for the SSOUser object is as follows:

SSOUser Structure
1
2interface SSOUser {
3 id: string;
4 username: string;
5 websiteUrl: string;
6 email: string;
7 signUpDate: number;
8 createdFromUrlId: string;
9 loginCount: number;
10 avatarSrc: string;
11 optedInNotifications: boolean;
12 displayLabel?: string;
13 displayName?: string;
14 isAccountOwner?: boolean;
15 isAdminAdmin?: boolean;
16 isCommentModeratorAdmin?: boolean;
17 /** If null, Access Control will not be applied to the user. If an empty list, this user will not be able to see any pages or @mention other users. **/
18 groupIds?: string[] | null;
19}
20

Access Control

Users can be broken into groups. This is what the groupIds field is for, and is optional.

@Mentions

By default @mentions will use username to search for other sso users when the @ character is typed. If displayName is used, then results matching username will be ignored when there is a match for displayName, and the @mention search results will use displayName.

GET /api/v1/sso-users Internal Link

Resource: SSOUser as GET /api/v1/sso-users Credit Cost: 10

This route returns all SSO Users on your account.

SSOUsers cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/sso-users?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
SSOUsers Request Structure
1
2interface SSOUsersRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUsers Response Structure
1
2interface SSOUsersResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key';
6 /** Included on failure. **/
7 reason?: string;
8 users: SSOUser[]
9}
10

GET /api/v1/sso-users/by-id/:id Internal Link

Resource: SSOUser as GET /api/v1/sso-users/by-id/:id Credit Cost: 1

This route returns a single SSO user by their id.

SSOUser By ID cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/sso-users/by-id/xyz?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
SSOUser Request Structure
1
2interface SSOUserRequestByIdQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUser Response Structure
1
2interface SSOUserByIdResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-id' | 'user-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8 user: SSOUser;
9}
10

GET /api/v1/sso-users/by-email/:email Internal Link

Resource: SSOUser as GET /api/v1/sso-users/by-id/:id Credit Cost: 1

This route returns a single SSO user by their email.

SSOUser By Email cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/sso-users/by-email/someone@somewhere.com?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
SSOUser Request Structure
1
2interface SSOUserRequestByEmailQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUser Response Structure
1
2interface SSOUserByEmailResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-email' | 'user-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8 user: SSOUser;
9}
10

PATCH /api/v1/sso-users/:id Internal Link

Resource: SSOUser as PATCH /api/v1/sso-users/:id Credit Cost: 1

This route provides the ability to update a single SSO user.

SSOUser Update cURL Example
1
2curl --request PATCH \
3 --url 'https://fastcomments.com/api/v1/sso-users/my-user-id?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "username": "notfordperfect"
7}'
8
SSOUser Update Request Structure
1
2interface SSOUserPatchQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUser Update Response Structure
1
2interface SSOUserPatchResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'empty-request' | 'invalid-input' | 'missing-id' | 'user-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8 user?: SSOUser; // We return the complete updated user on success.
9}
10

POST /api/v1/sso-users Internal Link

Resource: SSOUser as POST /api/v1/sso-users Credit Cost: 1

This route provides the creation of a single SSO user.

Trying to create two users with the same ID will result in an error.

SSOUser Creation cURL Example
1
2curl --request POST \
3 --url 'https://fastcomments.com/api/v1/sso-users?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "id": "my-user-id",
7 "username": "fordperfect",
8 "displayName": "Ford Perfect",
9 "email": "fordperfect@galaxy.com",
10 "groupIds": ["some-optional-group-id"]
11}'
12

In this example we specify groupIds for access control, but this is optional.

SSOUser Creation Request Structure
1
2interface SSOUserPostQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUser Creation Response Structure
1
2interface SSOUserPostResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'empty-request' | 'invalid-input' | 'missing-id' | 'user-exists';
6 /** Included on failure. **/
7 reason?: string;
8 user?: SSOUser; // We return the created user on success.
9}
10

Integration Note

Data passed by the API can be overridden simply by passing a different SSO User HMAC payload. For example, if you set a username via the API, but then pass a different one via the SSO flow on page load, we will automatically update their username.

We will not update user parameters in this flow unless you explicitly specify them or set them to null (not undefined).

PUT /api/v1/sso-users/:id Internal Link

Resource: SSOUser as PUT /api/v1/sso-users Credit Cost: 1

This route provides the ability to update a single SSO user.

SSOUser Update cURL Example
1
2curl --request PUT \
3 --url 'https://fastcomments.com/api/v1/sso-users/my-user-id?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "username": "fordperfect",
7 "displayName": "Ford Perfect",
8 "email": "fordperfect@galaxy.com",
9 "groupIds": ["some-optional-group-id"]
10}'
11

In this example we specify groupIds for access control, but this is optional.

SSOUser Update Request Structure
1
2interface SSOUserPutQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUser Update Response Structure
1
2interface SSOUserPutResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'empty-request' | 'invalid-input' | 'missing-id' | 'user-exists';
6 /** Included on failure. **/
7 reason?: string;
8 user?: SSOUser; // We return the update user on success.
9}
10

DELETE /api/v1/sso-users/:id Internal Link

Resource: SSOUser as DELETE /api/v1/sso-users/:id Credit Cost: 1

This route provides the removal of a single SSO user by their email.

Note that loading the comment widget again with a payload for this user will simply recreate the user seamlessly.

SSOUser Removal cURL Example
1
2curl --request DELETE \
3 --url 'https://fastcomments.com/api/v1/sso-users/xyz?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
SSOUser Removal Request Structure
1
2interface SSOUsersDeleteQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
SSOUser Removal Response Structure
1
2interface SSOUsersResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-id' | 'user-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8 user?: SSOUser; // We return the removed user on success.
9}
10

Vote Structure Internal Link

A Vote object represents a vote left by a user.

The relationship between comments and vote is defined via commentId;

The structure for the Vote object is as follows:

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

GET /api/v1/votes Internal Link

Resource: Vote as GET /api/v1/votes Credit Cost: 10

Votes must be fetched by urlId.

Types of Votes

There are three types of votes:

  • Authenticated Votes, which are applied to the corresponding comment.
  • Authenticated Votes, which are pending verification, and thus are not yet applied to the comment.
  • Anonymous Votes, which are applied to the corresponding comment.

These are returned in separate lists in the API to reduce confusion.

Votes cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/votes?tenantId=demo&API_KEY=DEMO_API_SECRET&urlId=test'
4
Votes Request Structure
1
2interface VotesRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5 urlId: string;
6}
7
Votes Response Structure
1
2interface VotesResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id';
6 /** Included on failure. **/
7 reason?: string;
8 /** Authorized, verified votes, applied to their corresponding comments. **/
9 appliedAuthorizedVotes: Vote[];
10 /** Anonymous votes, applied to their corresponding comments. **/
11 appliedAnonymousVotes: Vote[];
12 /** Votes pending verification, not yet applied to their corresponding comments. **/
13 pendingVotes: Vote[];
14}
15

DomainConfig Structure Internal Link

A DomainConfig object represents configuration for a domain for a tenant.

The structure for the DomainConfig object is as follows:

Domain Config Structure
1
2interface DomainConfig {
3 /** A domain, not a URL, like "fastcomments.com" or "www.example.com". Subdomain may be included if limiting to a subdomain is desired. Max 1000 characters. **/
4 domain: string;
5 /** The From-Name used when sending emails. **/
6 emailFromName?: string;
7 /** The From-Email used when sending emails. Ensure SPF is setup to allow mail.fastcomments.com to send emails as the domain used in this attribute. **/
8 emailFromEmail?: string;
9 /** READONLY. When the object was created. **/
10 createdAt: string;
11 /** The logo related to this domain. Used in emails. Use HTTPS. **/
12 logoSrc?: string;
13 /** A smaller logo related to this domain. Use HTTPS. **/
14 logoSrc100px?: string;
15 /** SSO ONLY. The URL used in the footer of every email sent. Supports a "[userId]" variable. **/
16 footerUnsubscribeURL?: string;
17 /** SSO ONLY. The headers used in of every email sent. Useful for example for setting unsubscribe related headers to improve delivery. The List-Unsubscribe entry in this Record, if it exists, supports a "[userId]" variable. **/
18 emailHeaders?: Record<string, string>;
19 /** Disable all unsubscribe links. Not recommended, may hurt delivery rates. **/
20 disableUnsubscribeLinks?: boolean;
21 /** DKIM Configuration. **/
22 dkim?: DomainConfigDKIM;
23}
24
DKIM Config Structure
1
2interface DomainConfigDKIM {
3 /** The domain name in your DKIM record. **/
4 domainName: string;
5 /** The DKIM key selector to use. **/
6 keySelector: string;
7 /** Your private key. Start with -----BEGIN PRIVATE KEY----- and end with -----END PRIVATE KEY----- **/
8 privateKey: string;
9}
10

For Authentication

Domain Configuration is used to determine which sites can host the FastComments widget for your account. This is a basic form of authentication, meaning adding or removing any Domain Configurations can impact the availability of your FastComments installation in production.

Don't remove or update the domain property of a Domain Config for a domain that is currently in use unless disabling that domain is intended.

This has the same behavior as removing a domain from /auth/my-account/configure-domains.

Also note that removing a domain from the My Domains UI will remove any corresponding configuration for that domain that may have been added via this UI.

For Email Customization

The unsubscribe link in the email footer, and the one-click-unsubscribe feature offered by many email clients, can be configured via this API by defining footerUnsubscribeURL and emailHeaders, respectively.

For DKIM

After defining your DKIM DNS records, simply update the DomainConfig with your DKIM configuration using the defined structure.

GET /api/v1/domain-configs Internal Link

Resource: Comment as GET /api/v1/domain-configs Credit Cost: 1

This API provides the ability to fetch all DomainConfig objects for a tenant.

DomainConfig GET cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/domain-configs?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
DomainConfig GET Request Structure
1
2interface GetDomainConfigsRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
DomainConfig GET Response Structure
1
2interface GetDomainConfigsResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key';
6 /** Included on failure. **/
7 reason?: string;
8 /** The configurations! **/
9 configurations: DomainConfig[] | null;
10}
11

GET /api/v1/domain-configs/:domain Internal Link

Resource: DomainConfig as GET /api/v1/domain-configs/:domain Credit Cost: 1

Individual DomainConfigs can be fetched by their corresponding domain.

Domain Config by Domain cURL Example
1
2curl --request GET \
3 --url 'https://fastcomments.com/api/v1/domain-configs/example.com?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
Domain Config by Domain Request Structure
1
2interface DomainConfigsByDomainRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
Domain Config by Domain Response Structure
1
2interface DomainConfigResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'internal' | 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-url-id' | 'missing-domain' | 'update-would-create-duplicate' | 'domain-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8 configuration?: DomainConfig | null;
9}
10

POST /api/v1/domain-configs Internal Link

Resource: DomainConfig as POST /api/v1/domain-configs Credit Cost: 1

This API endpoint provides the ability to create domain configurations.

Adding configuration for a domain authorizes that domain for the FastComments account.

Common use cases of this API are initial setup, if many domains are desired to be added, or custom configuration for sending emails.

DomainConfig POST cURL Example
1
2curl --request POST \
3 --url 'https://fastcomments.com/api/v1/domain-configs?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "domain": "example.com",
7 "emailFromName": "some from name",
8 "emailFromEmail": "some@test.com",
9 "logoSrc": "https://example.com/my-logo-big.png",
10 "logoSrc100px": "https://example.com/my-logo-100px.png",
11 "footerUnsubscribeURL": "http://example.com/unsubscribe-ui",
12 "emailHeaders": {
13 "List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
14 "List-Unsubscribe": "<https://example.com/opt-out/[userId]>"
15 }
16}'
17
DomainConfig POST Request Structure
1
2interface DomainConfigPostQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
DomainConfig POST Response Structure
1
2
3interface DomainConfigPostResponse {
4 status: 'success' | 'failed';
5 /** Included on failure. **/
6 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'empty-request' | 'internal' | 'invalid-input' | 'missing-domain' | 'configuration-exists-for-domain' | 'domain-too-long' | 'domain-invalid';
7 /** Included on failure. **/
8 reason?: string;
9 /** The created configuration. **/
10 configuration?: DomainConfig;
11}
12

PATCH /api/v1/domain-configs/:domain Internal Link

Resource: DomainConfig as PATCH /api/v1/domain-configs/:domain Credit Cost: 1

This API endpoint provides the ability to update a domain configuration by only specifying the domain and the attribute to update.

DomainConfig PATCH cURL Example
1
2curl --request PATCH \
3 --url 'https://fastcomments.com/api/v1/domain-configs/example.com?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "emailFromName": "Some New From Name",
7}'
8
DomainConfig PATCH Request Structure
1
2interface DomainConfigPatchQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
DomainConfig PATCH Response Structure
1
2
3interface DomainConfigPatchResponse {
4 status: 'success' | 'failed';
5 /** Included on failure. **/
6 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'empty-request' | 'internal' | 'invalid-input' | 'missing-domain' | 'domain-does-not-exist' | 'update-would-create-duplicate' | 'domain-too-long' | 'domain-invalid';
7 /** Included on failure. **/
8 reason?: string;
9 /** The updated configuration. **/
10 configuration?: DomainConfig;
11}
12

PUT /api/v1/domain-configs/:domain Internal Link

Resource: DomainConfig as PUT /api/v1/domain-configs/:domain Credit Cost: 1

This API endpoint provides the ability to replace a domain configuration.

DomainConfig PUT cURL Example
1
2curl --request PUT \
3 --url 'https://fastcomments.com/api/v1/domain-configs/example.com?tenantId=demo&API_KEY=DEMO_API_SECRET' \
4 --header 'Content-Type: application/json' \
5 --data '{
6 "domain": "new-domain-example.com",
7 "emailFromName": "some from name",
8 "emailFromEmail": "some@test.com",
9 "logoSrc": "https://example.com/my-logo-big.png",
10 "logoSrc100px": "https://example.com/my-logo-100px.png",
11 "footerUnsubscribeURL": "http://example.com/unsubscribe-ui",
12 "emailHeaders": {
13 "List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
14 "List-Unsubscribe": "<https://example.com/opt-out/[userId]>"
15 }
16}'
17
DomainConfig PUT Request Structure
1
2interface DomainConfigPutQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
DomainConfig PUT Response Structure
1
2
3interface DomainConfigPutResponse {
4 status: 'success' | 'failed';
5 /** Included on failure. **/
6 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'empty-request' | 'internal' | 'invalid-input' | 'missing-domain' | 'domain-does-not-exist' | 'update-would-create-duplicate' | 'domain-too-long' | 'domain-invalid';
7 /** Included on failure. **/
8 reason?: string;
9 /** The updated configuration. **/
10 configuration?: DomainConfig;
11}
12

DELETE /api/v1/domain-configs/:domain Internal Link

Resource: DomainConfig as DELETE /api/v1/domain-configs/:domain Credit Cost: 1

This route provides the removal of a single DomainConfig by id.

  • Note: Removing a DomainConfig will un-authorize that domain from using FastComments.
  • Note: Re-adding a domain via the UI will recreate the object (with just domain populated).
DomainConfig Removal cURL Example
1
2curl --request DELETE \
3 --url 'https://fastcomments.com/api/v1/domain-configs/example.com?tenantId=demo&API_KEY=DEMO_API_SECRET'
4
DomainConfig Removal Request Structure
1
2interface DomainConfigRequestQueryParams {
3 tenantId: string;
4 API_KEY: string;
5}
6
DomainConfig Removal Response Structure
1
2interface DomainConfigDeleteResponse {
3 status: 'success' | 'failed';
4 /** Included on failure. **/
5 code?: 'missing-tenant-id' | 'invalid-tenant-id' | 'invalid-api-key' | 'missing-api-key' | 'missing-domain' | 'domain-config-does-not-exist';
6 /** Included on failure. **/
7 reason?: string;
8}
9

In Conclusion

We hope you've found our API documentation thorough and easy to understand. If you find any gaps, let us know below.