Skip to content

API Reference — Comments

Generate the character's public-comment activity: a top-level comment on a post, and threaded replies to people who reply underneath it. You report the post (and any incoming reply); the API returns the words the character should say. The connector posts the returned text — FluidTalk generates the comment and tracks the relationship, it never touches the platform itself.

All routes are under the production base URL:

https://api-talk.fluidvip.com/api/v1/characters

Every response is wrapped in the standard envelope — the real payload is under data, alongside a request_id (also returned as the X-Request-Id header). The shapes below describe the inner data. See Errors for the envelope and error model.

MethodPathPurpose
POST/commentsGenerate a top-level comment for a post
POST/comments/replyGenerate a threaded reply to a reply

Authentication. Send your per-character connector token in the X-Connector-Token header. The token is the character — there is no character_id; you name the platform in each request body and the bound workflow is selected for you. See Authentication.

One persona everywhere

Comments are cross-surface aware. The same lead who comments and DMs is one Person, so the character stays consistent and remembers across surfaces (DM ↔ comments) and across multiple posts and threads. recognized_lead and the aware summary reflect what the character already knows about this Person from elsewhere. See Concepts.


The post object

Both endpoints take an optional post object that gives the character context about what it is commenting on. Image URLs are described via vision, so the character can reference what is actually shown.

FieldTypeDescription
captionstringThe post's caption text.
image_urlsstring[]URLs of the post's images. Each is described via vision so the comment can react to the picture, not just the words.
author_handlestringThe @username of whoever authored the post.

On POST /comments the post object carries the post being commented on. On POST /comments/reply it is optional — pass it only when the thread is new and the character hasn't seen this post yet.


POST /comments

Generate a top-level public comment for a post. You post the returned text on the platform.

Request body

NameTypeRequiredDescription
platformstringYesThe platform the post is on, e.g. "instagram". Selects the bound workflow.
post_refstringYesThe platform's unique id or URL for the post. Used to track the comment thread across calls.
postobjectNoThe post object — caption, image URLs, and author handle.

Response

FieldTypeDescription
okbooleanAlways true on success.
commentstringThe comment text to post on the platform. Absent on the not-configured no-op.
awareobjectA cross-surface awareness summary — what the character already knows about this Person from DMs and other threads. Informational; treat its inner fields as illustrative, not a stable contract.
recognized_leadbooleantrue when the post author / commenter is a Person the character already knows from another surface.
thread_idstringPresent once a comment thread exists for this post. Tracked for you — you don't pass it back.
ignoredstringPresent only on the no-op ("comments not configured"); no comment is returned.
json
{
  "data": {
    "ok": true,
    "comment": "okay that light is unreal 😍 how was the pace today?",
    "aware": { "recognized": false, "known_from": [] },
    "recognized_lead": false,
    "thread_id": "thr_3f9c20a1"
  },
  "request_id": "req_8f3c2a1b"
}

Not configured is a safe no-op. If comments aren't enabled for this character on this platform, the call returns 200 with data of { "ok": true, "ignored": "comments not configured" }. No comment is generated and nothing is billed — so you can wire the call up before you turn comments on in the dashboard.

Paused characters generate nothing. If the character is paused (e.g. the account is over its plan's character limit after a downgrade), the call returns 200 with data of { "ok": true, "paused": true, "pause_reason": "plan_limit" }. No comment is generated and nothing is billed; the character resumes automatically once the plan is upgraded. See Paused characters.

Metered. Generating a comment costs model spend and is billed to the character owner's wallet. If the wallet can't cover it you get 402 payment_required before any model call (you're never charged for a refused generation). See Billing.

Examples

bash
curl -X POST https://api-talk.fluidvip.com/api/v1/characters/comments \
  -H "X-Connector-Token: ftc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "instagram",
    "post_ref": "https://instagram.com/p/Cabc123",
    "post": {
      "caption": "sunset run done 🌅",
      "image_urls": ["https://cdn.example.com/p/abc.jpg"],
      "author_handle": "ava"
    }
  }'
python
from fluidtalk import FluidTalk

ft = FluidTalk(token="ftc_live_...")

res = ft.comment(
    platform="instagram",
    post_ref="https://instagram.com/p/Cabc123",
    caption="sunset run done 🌅",
    image_urls=["https://cdn.example.com/p/abc.jpg"],
    author_handle="ava",
)

# res.comment is the text to post (None / absent when comments aren't configured)
if res.comment:
    publish_comment_on_instagram(res.comment)  # you post it on the platform
typescript
import { FluidTalk } from "fluidtalk";

const ft = new FluidTalk({ token: "ftc_live_..." });

const res = await ft.comment({
  platform: "instagram",
  postRef: "https://instagram.com/p/Cabc123",
  caption: "sunset run done 🌅",
  imageUrls: ["https://cdn.example.com/p/abc.jpg"],
  authorHandle: "ava",
});

if (res.comment) {
  await publishCommentOnInstagram(res.comment); // you post it on the platform
}

Status codes

StatuscodeWhen
200Comment generated, or a safe no-op (ignored: "comments not configured").
400invalid_requestMalformed body — e.g. missing platform or post_ref.
401invalid_tokenMissing, invalid, or revoked connector token.
402payment_requiredThe owner's wallet can't cover this generation — no model call was made. Top up. See Billing.
422validation_errorA field failed validation (e.g. post.image_urls isn't a list).
429rate_limitedRate limited; honor the Retry-After header.
500internal_errorUnexpected server error.

POST /comments/reply

Generate a reply to a reply on the character's comment. Threaded and cross-thread aware — it can fire multiple times within a thread, to the original poster or to other commenters. The character decides whether to engage, steer the person toward DMs, or stay quiet.

Request body

NameTypeRequiredDescription
platformstringYesThe platform the thread is on, e.g. "instagram".
post_refstringYesThe platform's unique id or URL for the post the thread lives under.
replier_handlestringYesThe @username of whoever replied.
reply_textstringNoWhat the replier said.
parent_comment_refstringNoThe platform's id of the comment being replied to, when you have it.
postobjectNoThe post object — pass it only when the thread is new and the character hasn't seen this post yet.

Response

FieldTypeDescription
okbooleanAlways true on success.
decisionstringWhat the character chose to do — e.g. "engage", "drive_to_dm", or "skip".
replystring | nullThe reply text to post, or null when the character chose not to reply (a "skip" decision).
reasonstringOptional short rationale for the decision.
awareobjectOptional cross-surface awareness summary — what the character already knows about this Person. Informational; treat inner fields as illustrative.
json
{
  "data": {
    "ok": true,
    "decision": "drive_to_dm",
    "reply": "ahh you're sweet 😅 dm me, i'll tell you my secret 👀",
    "reason": "warm replier, good moment to move to DMs",
    "aware": { "recognized": true, "known_from": ["dm"] }
  },
  "request_id": "req_4b19bcc3"
}

When the character decides to stay quiet, reply is null — post nothing:

json
{ "data": { "ok": true, "decision": "skip", "reply": null }, "request_id": "req_9aa97fb0" }

Metered. Like /comments, a generated reply is billed to the owner's wallet, and a wallet that can't cover it returns 402 before any model call. A "skip" decision still runs the model to make the call, so it is billed. See Billing.

Examples

bash
curl -X POST https://api-talk.fluidvip.com/api/v1/characters/comments/reply \
  -H "X-Connector-Token: ftc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "instagram",
    "post_ref": "https://instagram.com/p/Cabc123",
    "replier_handle": "mark",
    "reply_text": "haha you always make these look easy 😂",
    "parent_comment_ref": "17900000000000001"
  }'
python
res = ft.comment_reply(
    platform="instagram",
    post_ref="https://instagram.com/p/Cabc123",
    replier_handle="mark",
    reply_text="haha you always make these look easy 😂",
    parent_comment_ref="17900000000000001",
)

if res.decision != "skip" and res.reply:
    publish_reply_on_instagram(res.reply)  # you post it on the platform
typescript
const res = await ft.commentReply({
  platform: "instagram",
  postRef: "https://instagram.com/p/Cabc123",
  replierHandle: "mark",
  replyText: "haha you always make these look easy 😂",
  parentCommentRef: "17900000000000001",
});

if (res.decision !== "skip" && res.reply) {
  await publishReplyOnInstagram(res.reply); // you post it on the platform
}

Status codes

StatuscodeWhen
200Reply generated. A "skip" decision (reply: null) is still a 200.
400invalid_requestMalformed body — e.g. missing platform, post_ref, or replier_handle.
401invalid_tokenMissing, invalid, or revoked connector token.
402payment_requiredThe owner's wallet can't cover this generation — no model call was made. Top up. See Billing.
422validation_errorA field failed validation.
429rate_limitedRate limited; honor the Retry-After header.
500internal_errorUnexpected server error.

Errors

The SDKs raise typed errors — AuthError (401), PaymentRequiredError (402), PermissionError (403), NotFoundError (404), ConflictError (409), ValidationError (422), RateLimitError (429), and ApiError for anything else. See Errors for the full error model and Python / TypeScript for the typed exceptions.


  • Chat — drive a DM conversation; replies arrive as bubbles.
  • Concepts — the Person model and cross-surface awareness behind recognized_lead / aware.
  • Multi-account dedup — running several accounts of one character on a platform.
  • Billing — how generated comments and replies are metered.
  • Errors — the full error model and SDK error types.
  • API Reference index — all endpoints at a glance.

FluidTalk Characters API — part of the Fluidvip ecosystem.