The commenting API for live discussions

Comments, moderation, and social feeds through one REST API and SDKs for 10+ languages. Fetch, post, and moderate from your backend, then stream new activity to every reader in realtime over WebSockets.

One platform, three APIs

FastComments is more than comments. Build discussions, moderation, and social feeds on the same API and SDK suite.

Comments API

Threaded comments and live chat. Fetch, post, vote, pin, reply, and search, with SSO and realtime updates built in.

Moderation API

A dedicated moderation surface with 40+ endpoints. Approve, flag, block, ban, lock, and audit, backed by automatic spam filtering.

Social Feed API

Build activity and social feeds with posts, media, reactions, and follows, then push new posts to every client live.

Call the API from any stack

cURL and typed SDKs for Node, Python, PHP, Ruby, Go, Java, Rust, Swift, and C++. Over 200 endpoints cover comments, votes, pages, SSO users, feed posts, moderation, and notifications, all behind a single API key.

Installnpm install fastcomments-sdk
import { createFastCommentsSDK } from 'fastcomments-sdk/server';

const sdk = createFastCommentsSDK({
  apiKey: 'your-api-key',               // server-side only
  basePath: 'https://fastcomments.com'  // optional (default)
});

// Fetch comments for a page
const { comments } = await sdk.publicApi.getCommentsPublic({
  tenantId: 'your-tenant-id',
  urlId: 'page-url-id'
});

// Post a comment
await sdk.publicApi.createCommentPublic({
  tenantId: 'your-tenant-id',
  broadcastId: crypto.randomUUID(),
  createComment: {
    urlId: 'page-url-id',
    url: 'https://example.com/post',
    comment: 'Hello from the API!',
    commenterName: 'Alice'
  }
});
# Fetch comments for a page
curl -s 'https://fastcomments.com/api/v1/comments?tenantId=your-tenant-id&urlId=page-url-id' \
  -H 'x-api-key: YOUR_API_KEY'
Installpip install fastcomments
import client
from client.api.public_api import GetCommentsPublicOptions

configuration = client.Configuration(host="https://fastcomments.com")
with client.ApiClient(configuration) as api_client:
    api = client.PublicApi(api_client)
    response = api.get_comments_public(
        "your-tenant-id",
        "page-url-id",
        GetCommentsPublicOptions(page=0, limit=30),
    )
    for comment in response.comments:
        print(comment.commenter_name, comment.comment)
Installcomposer require fastcomments/fastcomments-php
<?php
require_once(__DIR__ . '/vendor/autoload.php');

$api = new FastComments\Client\Api\PublicApi(new GuzzleHttp\Client());

$result = $api->getCommentsPublic('your-tenant-id', 'page-url-id', [
    'page'  => 0,
    'limit' => 30,
]);

foreach ($result->getComments() as $comment) {
    echo $comment->getCommenterName() . ': ' . $comment->getComment() . PHP_EOL;
}
Installgem install fastcomments
require 'fastcomments-client'

api = FastCommentsClient::PublicApi.new
result = api.get_comments_public('your-tenant-id', 'page-url-id', { page: 0, limit: 30 })

result.comments.each do |comment|
  puts "#{comment.commenter_name}: #{comment.comment}"
end
Installgo get github.com/fastcomments/fastcomments-go
package main

import (
	"context"
	"fmt"
	openapiclient "github.com/fastcomments/fastcomments-go/client"
)

func main() {
	client := openapiclient.NewAPIClient(openapiclient.NewConfiguration())

	resp, _, err := client.PublicAPI.
		GetCommentsPublic(context.Background(), "your-tenant-id").
		UrlId("page-url-id").Page(0).Limit(30).Execute()
	if err != nil {
		panic(err)
	}
	for _, c := range resp.Comments {
		fmt.Printf("%s: %s\n", c.GetCommenterName(), c.GetComment())
	}
}
import com.fastcomments.invoker.ApiClient;
import com.fastcomments.invoker.Configuration;
import com.fastcomments.api.PublicApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://fastcomments.com");

PublicApi api = new PublicApi(client);
var result = api.getCommentsPublic("your-tenant-id", "page-url-id")
                .page(0)
                .limit(30)
                .execute();
System.out.println(result.getComments());
use fastcomments_sdk::client::apis::configuration::Configuration;
use fastcomments_sdk::client::apis::public_api::{get_comments_public, GetCommentsPublicParams};

let config = Configuration::new();
let params = GetCommentsPublicParams {
    tenant_id: "your-tenant-id".to_string(),
    url_id: "page-url-id".to_string(),
    page: Some(0),
    limit: Some(30),
    ..Default::default()
};
let result = get_comments_public(&config, params).await.unwrap();
for comment in result.comments {
    println!("{:?}: {:?}", comment.commenter_name, comment.comment);
}
import FastCommentsSwift

var options = PublicAPI.GetCommentsPublicOptions()
options.page = 0
options.limit = 30

let result = try await PublicAPI.getCommentsPublic(
    tenantId: "your-tenant-id",
    urlId: "page-url-id",
    options: options
)
print(result.comments ?? [])
#include "FastCommentsClient/api/PublicApi.h"
#include "FastCommentsClient/ApiClient.h"
#include "FastCommentsClient/ApiConfiguration.h"

using namespace org::openapitools::client::api;

auto config = std::make_shared<ApiConfiguration>();
config->setBaseUrl(utility::conversions::to_string_t("https://fastcomments.com"));

PublicApi publicApi(std::make_shared<ApiClient>(config));

auto resp = publicApi.getCommentsPublic(
    utility::conversions::to_string_t("your-tenant-id"),
    utility::conversions::to_string_t("page-url-id")
).get();

Subscribe to the live feed

Open one connection and receive every new comment, edit, vote, and presence update the moment it happens. No events are missed: on reconnect the event log is re-fetched to replay anything sent while the client was offline. Native WebSocket subscribers ship for Node, React Native, Java, Swift, and C++. Every other language stays realtime by polling the event log.

Installnpm install fastcomments-sdk
import { subscribeToChanges, LiveEventType } from 'fastcomments-sdk/browser';

const config = { tenantId: 'your-tenant-id', urlId: 'page-url-id' };

const subscription = subscribeToChanges(
  config,
  'your-tenant-id',   // tenantIdWS
  'page-url-id',      // urlIdWS
  'user-session-id',  // userIdWS (from the getComments response)
  (event) => {
    if (event.type === LiveEventType.new_comment) {
      console.log('New comment:', event.comment?.comment);
    }
    return true;      // event handled
  },
  (isConnected) => console.log(isConnected ? 'connected' : 'disconnected')
);

// later: subscription.close();
Installnpm install fastcomments-react-native-sdk
import React, { useState } from 'react';
import { FastCommentsLiveCommenting } from 'fastcomments-react-native-sdk';
import { FastCommentsCommentWidgetConfig } from 'fastcomments-typescript';

export default function Comments() {
  // <FastCommentsLiveCommenting> subscribes to the live feed automatically.
  const [config] = useState<FastCommentsCommentWidgetConfig>({
    tenantId: 'your-tenant-id',
    urlId: 'page-url-id',
    showLiveRightAway: true,
    countAll: true,
  });

  return <FastCommentsLiveCommenting config={config} />;
}
import com.fastcomments.pubsub.LiveEventSubscriber;
import com.fastcomments.pubsub.SubscribeToChangesResult;
import com.fastcomments.core.CommentWidgetConfig;
import com.fastcomments.model.LiveEventType;

CommentWidgetConfig config = new CommentWidgetConfig();
config.tenant = "your-tenant-id";
config.urlId = "page-url-id";

LiveEventSubscriber subscriber = new LiveEventSubscriber();
SubscribeToChangesResult result = subscriber.subscribeToChanges(
    config,
    "your-tenant-id",   // tenantIdWS
    "page-url-id",      // urlId
    "page-url-id",      // urlIdWS
    "my-presence-id",   // userIdWS
    null,               // canSeeCommentsCallback (optional)
    (event) -> {
        if (event.getType() == LiveEventType.NEW_COMMENT) {
            System.out.println("New comment: " + event.getComment().getId());
        }
    }
);
// later: result.close();
import FastCommentsSwift

let config = LiveEventConfig(
    tenantId: "your-tenant-id",
    urlId: "page-url-id",
    urlIdWS: "page-url-id",   // URL-safe id for the WS server
    userIdWS: "my-presence-id"
)

let subscriber = LiveEventSubscriber()
let result = subscriber.subscribeToChanges(config: config) { event in
    if event.type == .newComment, let comment = event.comment {
        print("New comment: \(comment.id ?? "")")
    }
}
// later: result?.close()
#include <fastcomments/live/live_stream.hpp>
#include <iostream>

using namespace fastcomments::live;

LiveStreamConfig cfg;
cfg.wsBaseUrl = "wss://fastcomments.com";   // no trailing slash

LiveStream stream(cfg);
stream.onEvent([](const LiveEvent& ev) {
    if (ev.type == EventType::NewComment) {
        std::cout << "New comment at " << ev.timestamp << std::endl;
    }
});

stream.subscribe("your-tenant-id", "page-url-id", "my-presence-id").wait();
// later: stream.close().wait();
Installpip install fastcomments
import time
import client

configuration = client.Configuration(host="https://fastcomments.com")
with client.ApiClient(configuration) as api_client:
    api = client.PublicApi(api_client)
    start_time = int(time.time() * 1000)  # ms epoch
    while True:
        result = api.get_event_log(
            "your-tenant-id", "page-url-id", "my-user-id", start_time
        )
        for event in result.events:
            print("event:", event.data)
            start_time = int(event.created_at.timestamp() * 1000) + 1
        time.sleep(2)
# startTime = epoch millis to replay from; advance it past the last event you saw
curl -s 'https://fastcomments.com/api/v1/event-log/your-tenant-id?urlId=page-url-id&userIdWS=my-user-id&startTime=1720560000000' \
  -H 'x-api-key: YOUR_API_KEY'

Native mobile SDKs, ready to drop in

Skip building and maintaining your own comment UI. Our dedicated, maintained SDKs for React Native, Android, and iOS ship native UI components for threaded comments, live chat, and feeds. Drop in a view, pass a config, and you are done.

React Native

npm: fastcomments-react-native-sdk

Native components, no webview. Drop in FastCommentsLiveCommenting, FastCommentsLiveChat, or FastCommentsFeed and pass a config.

See the live demo

Android

com.fastcomments:sdk

Native Android UI components. Add FastCommentsView to your layout for threaded comments, voting, notifications, and feeds. Android 8.0+.

View on GitHub

iOS

Swift Package: FastCommentsUI

A native SwiftUI library for threaded comments, social feeds, and live chat. iOS 16+ and macOS 14+.

View on GitHub

The parts you would otherwise build yourself

200+ REST endpoints

One API key, one base URL. Everything the dashboard does, your code can do too.

SDKs for 10+ languages

Typed clients for Node, Python, PHP, Ruby, Go, Java, Rust, Swift, C++, and more, so you build in your stack instead of ours.

Realtime over WebSockets

New comments reach every reader the moment they post, with no refresh and no polling. If a reader reconnects, missed events are replayed from the log.

Moderation, SSO, and spam protection

Single sign-on, comment moderation, and spam filtering are built in, so the hard parts are handled before you write a line.

Hosted and scaled for you

We run the storage and the realtime infrastructure across a global network. You call the API and ship.

What you can build

One API and SDK suite behind comment threads, chat, and live activity across web, mobile, and server apps.

Live chat rooms

Stream messages to everyone in the room in realtime, with presence counts and typing activity.

Comment threads

Add nested, votable comment sections to articles, products, and posts with a few API calls.

Activity feeds

Post to a feed and push new items and reactions to connected clients as they arrive.

Q&A and polls

Collect questions, answers, votes, and poll results, then rank and display them live.

Live in three steps

1

Get your API key

Start a free trial and grab your tenant ID and API key from the dashboard.

2

Install the SDK

Add the SDK for your language, or call the REST API directly with cURL and your x-api-key header.

3

Fetch, post, and go live

Load comments, post from your backend, and subscribe to changes to stream updates to every reader.

Globally distributed and highly available

FastComments runs across multiple regions on our own infrastructure. Writes replicate between regions, nodes fail over automatically, and readers are served from the location nearest them.

Multi-master, multi-region

Writes are accepted in more than one region and replicated between them, so there is no single point of failure.

Our own edge network

Comments and media are served from our own global CDN and DNS, delivered from the location nearest your users. No third-party CDN.

Automatic failover

Redundant nodes fail over on their own, so traffic keeps flowing through an outage. Backed by 99.99% uptime.

Regional data residency

Run in the US or the EU. The EU region at eu.fastcomments.com keeps data in-region for compliance.

Join Our Happy Customers

Thousands of satisfied customers trust us for our exceptional service, reliability, and innovative solutions. Join our growing community and experience the difference today!

Get Started

Commenting API FAQ

Do I have to use the FastComments widget?

No. The widget is optional. You can build your entire commenting experience on the REST API and SDKs and render everything yourself.

Which languages have an SDK?

Node, Python, PHP, Ruby, Go, Java, Rust, Swift, C++, and Nim, plus a React Native SDK for mobile. Any language can also call the REST API directly.

How does realtime work?

Clients open a WebSocket and receive new comments, edits, votes, and presence updates as events, so there is no refresh and no polling. No events are missed: if a client disconnects, it re-fetches the event log on reconnect to replay anything sent while it was offline.

Do I need to run my own WebSocket server?

No. FastComments hosts the realtime infrastructure. Your client subscribes with the SDK, and we deliver the events.

How do languages without a native subscriber stay live?

They poll the event log endpoint, which returns every change since a timestamp. The Node, React Native, Java, Swift, and C++ SDKs include a native WebSocket subscriber instead.

How does pagination work?

For comments specifically, FastComments pre-calculates pagination on every write for optimal load times, so even very large threads paginate fast.

Is there a free trial?

Yes. Start a free trial with full access to the API and SDKs, no credit card required. After the trial, paid plans scale with your traffic.

Where are the API docs?

The full REST API and SDK reference lives at docs.fastcomments.com, where every endpoint, parameter, and response is documented.

Can I keep data in the EU?

Yes. FastComments serves an EU region at eu.fastcomments.com, and the SDKs support routing to it.

Start building in minutes

Start a free trial, grab your API key, and add live discussions to your app today.