Appearance
Quickstart
Go from nothing to your character replying to a real DM in a few minutes. You will get a per-character connector token, install a FluidTalk SDK, push your first inbound DM with POST /chat, read back the character's reply bubbles, and send them on your platform.
This is the fastest path. For the concepts behind it, read concepts.md; for the full method list, see the API reference.
The API generates the messages; your connector owns the platform I/O. FluidTalk writes the character's reply, fires entry events, drafts public comments, and tracks the relationship across surfaces — but it never reads or posts on Instagram, X, Reddit, Fanvue, TikTok, or anywhere else. How you connect to the platform is your concern. You push inbound, you send the output.
1. Get a connector token
Connector tokens are issued in the FluidTalk dashboard, not through the API.
- Sign up or sign in at https://talk.fluidvip.com as the account owner. Any plan works, including Free: no subscription is needed to create a token. (Team members and VAs cannot create tokens.)
- Open Characters, open your character (e.g. Ava; save it first if it is new), and go to its API tab.
- Click Create API key and copy the connector token. A token looks like
ftc_.... It stays on that tab for the account owner to show or copy any time — store it as a secret. - Make sure the character has a workflow on the platform you will drive (e.g. Instagram), in its Platforms tab. A call for a platform with no workflow returns
404.
The token is the character. There is no account-level key and no character_id field: you authenticate as one character by its token, and you name the platform in each request body. A character can run on several platforms — the same token works for all of them, and the platform you send selects the bound workflow. See authentication.md for how the token is sent.
Keep the token in an environment variable rather than in source:
bash
export FLUIDTALK_TOKEN="ftc_8f3c..."No subscription is required, but every generated turn draws on the owner's wallet, so live calls need a balance above $0 (the Free plan is pay-as-you-go: top up in the dashboard).
GET /self-testandmode: "mock"cost nothing; see testing.md. If the wallet can't cover a turn, calls return402 insufficient_tokensbefore any model call — so you are never charged for a refused turn. Top up in the dashboard. See billing.md and errors.md.
2. Install an SDK
The SDKs send your token in the X-Connector-Token header automatically, parse the { data, request_id } envelope for you, and raise typed errors. Or you can call the REST API directly with curl.
Python
bash
pip install "fluidtalk>=2"TypeScript / JavaScript
bash
npm install fluidtalk@^23. Send your first DM
A lead just messaged your character. You forward that inbound to POST /chat with the platform, the lead's handle, and their message; the character replies with a list of bubbles — short chat messages, each with a human-like delay_ms — that you send back, in order, on the platform.
The production API base is https://api-talk.fluidvip.com/api/v1/characters. A lead is identified by (platform, handle); reusing the same pair auto-resumes that conversation, so you rarely pass a session_id.
curl
bash
API="https://api-talk.fluidvip.com/api/v1/characters"
TOKEN="$FLUIDTALK_TOKEN"
curl -s -X POST "$API/chat" \
-H "X-Connector-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"platform": "instagram",
"handle": "mark",
"message": "hey, love your latest post 🔥"
}'Every endpoint returns the same envelope: the real payload is under data, and a request_id (mirrored in the X-Request-Id response header) is there for log correlation. The full response looks like this:
json
{
"data": {
"session_id": "ses_7Yb3c1a90f24",
"bubbles": [
{ "text": "omg hii 🙈", "delay_ms": 0, "image_url": null },
{ "text": "you actually looked? that means a lot lol", "delay_ms": 2600, "image_url": null }
]
},
"request_id": "req_3f9c2a7b8e1d"
}Python
python
from fluidtalk import FluidTalk
ft = FluidTalk(token="ftc_8f3c...") # base_url defaults to production
reply = ft.chat(
platform="instagram",
handle="mark",
message="hey, love your latest post 🔥",
)
# reply is the inner `data` — send each bubble in order, honoring the delay
for bubble in reply.bubbles:
# your connector waits bubble.delay_ms, then sends bubble.text on Instagram
send_dm("mark", bubble.text, delay_ms=bubble.delay_ms)
print(reply.session_id)
# -> ses_7Yb3c1a90f24TypeScript
typescript
import { FluidTalk } from "fluidtalk";
const ft = new FluidTalk({ token: "ftc_8f3c..." }); // baseUrl defaults to production
const reply = await ft.chat({
platform: "instagram",
handle: "mark",
message: "hey, love your latest post 🔥",
});
// reply is the inner `data` — send each bubble in order, honoring the delay
for (const bubble of reply.bubbles) {
// your connector waits bubble.delay_ms, then sends bubble.text on Instagram
await sendDm("mark", bubble.text, bubble.delay_ms);
}
console.log(reply.session_id);
// -> ses_7Yb3c1a90f24If the lead sent a photo, pass its URL as image_url and the character will "see" it (described via vision) before replying. Full parameters and edge cases are in reference/chat.md.
A note on bubbles: send them like a human
The reply is a list, not one blob. Send the bubbles in order and respect each delay_ms (it's a pause before that bubble) — that's what makes the character read like a person texting, not a bot pasting a paragraph.
A few cases to handle:
bubbles: []— the conversation is already closed; send nothing.- A
billingobject may ride along on the response with what the turn cost; surface a low balance to the operator. See billing.md. - Multi-account dedup — if your character runs more than one account on a platform and another account already claimed this lead,
/chatreturns{ "session_id": null, "bubbles": [], "ignored": true, "ignore_reason": "lead_claimed_by_other_account" }. Send nothing. See multi-account-dedup.md.
One coherent persona, everywhere. The lead
(instagram, mark)is one Person. The same Ava who answers Mark's DM also remembers him under her public comments, and across multiple posts and threads — the character stays consistent across surfaces. This cross-surface awareness is the headline feature; read more in concepts.md.
What next: open conversations and re-engage
Inbound DMs are only one way a conversation moves. Two more to wire up next:
Fire a trigger to start a conversation. When a lead reacts to a story, follows the account, or hits any custom entry point you configured in the dashboard, report it with POST /triggers. If there's no live chat, the character opens the conversation reacting to the event; if a chat already exists, the event becomes the next turn's stimulus.
bash
curl -s -X POST "https://api-talk.fluidvip.com/api/v1/characters/triggers" \
-H "X-Connector-Token: $FLUIDTALK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"platform": "instagram",
"handle": "mark",
"event_id": "story_reaction",
"external_event_id": "ig_evt_4471",
"context": "🔥"
}'/triggers (and /events) are idempotent on external_event_id, so a re-delivered webhook applies exactly once. See reference/triggers.md.
Pull proactive follow-ups. The character periodically queues "hey stranger" rekindles for dormant leads. Poll GET /followups, send each one on the platform, then POST /followups/{id}/ack to mark it delivered.
bash
curl -s "https://api-talk.fluidvip.com/api/v1/characters/followups?platform=instagram" \
-H "X-Connector-Token: $FLUIDTALK_TOKEN"Where to go next
- Testing your integration —
GET /self-testto check your wiring for free, thenmode: "mock"to exercise photo bubbles,402s and outreach branches with no model call and no charge. Start here before writing your connector. - Concepts — characters, platform + handle, sessions, the cross-surface Person, bubbles, triggers, follow-ups, and comment threads.
- Triggers — open conversations from story reactions, new followers, and custom entry points.
- Follow-ups — the pull-queue for proactive re-engagement: list, deliver, ack.
- Comments, Comment replies and Comment engage — generate public comments, threaded replies, and replies that join a conversation between other people.
- Multi-account dedup — run several accounts on one platform so only one ever replies to a lead.
- Billing — metered usage, the
billingobject, and handling402. - Errors — status codes, the error envelope, and typed SDK errors.
- SDK references: Python · TypeScript.