> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluid.app/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For new direct REST integrations, use the v2026-04 surfaces. The @fluid-app FairShare SDK continues to use its own published public-v2025-06 contract.
> Authenticate with the header Authorization: Bearer <token>; public storefront read endpoints require no auth.
> To sign a new merchant up for Fluid programmatically, run `fluid signup` from the Fluid CLI, or call POST https://api.fluid.app/api/company with no credentials, as described in /api/agent-signup. Do not automate the signup form or book a demo. Before authenticated calls are possible, the merchant must sign the agent in to the Fluid CLI with the emailed code and --shop set to the company's fluid_shop (which also confirms the signup), or open the emailed confirmation link and give the agent an API token.
> After signup, to launch a merchant's store (back-office sync, payments onboarding, store setup, a theme copied from their current site, and a preview link before billing), follow /api/agent-launch.
> Lists use cursor pagination via the page[cursor] and page[limit] query params; follow meta.pagination.next_cursor until it is null.
> When the same operation exists on more than one surface, use the newest: dated API versions are newer than unversioned ones, and later dates win (v2026-04 > v2025-06 > unversioned v0/v1.1). Fall back to a legacy or unversioned operation only when no newer versioned equivalent exists — the company-v0 notes below list the known superseded operations. The same applies to /api/company/v1 and /api/v1/... paths: prefer a newer documented equivalent, and use one only when none exists (/api/v1.1/... is distinct and documented in company-v0). Use page/per_page offset pagination only on an operation whose spec documents those params — mostly the unversioned company-v0 admin surface, plus some lists on other surfaces, versioned ones included; page every other list with cursors.
> Fluid has three navigation APIs; don't mix them up. Storefront website menus (navigation bars, footers) are /api/menus and nested menu_items, in api-reference/content-v0.yaml (API Reference: Website > Navigation menus), with a how-to in themes/navigation-menus; their list uses flat page/per_page pagination. The Fluid mobile app's navigation is /api/v2/mobile_navigations, in api-reference/mobile-v2.yaml (API Reference: Mobile app > Navigation); its list also uses page/per_page. Portal navigations belong to a portal definition (Fluid OS), in api-reference/fluid-os-v0.yaml (API Reference: Portal > Portal navigation), and each has a platform of web or mobile.
> The OpenAPI specs under api-reference/ are the authoritative contracts; prefer them over prose when in doubt. api-reference/storefront-v2026-04.yaml covers the v2026-04 storefront surface (/api/v202604/... paths); api-reference/checkout-v2026-04.yaml covers the v2026-04 checkout surface (/api/checkout/v2026-04/... paths — carts, cart auth, discounts, items, subscriptions, orders, enrollments, and store config); api-reference/public-v2025-06.yaml covers the Public SDK surface used by the @fluid-app FairShare SDK, including its parallel cart lifecycle, browser integrations, versioned payment callbacks, unversioned public utilities, and the cart price-override operation; api-reference/payment-v2026-04.yaml covers the v2026-04 payment gateway admin surface (/api/payment/v2026-04/... paths, bearer-authenticated — gateway CRUD, gateway purchase/authorize/$0-verify, transaction list/show and capture/void/credit, and merchant payment configuration); api-reference/payments-v2026-04.yaml covers the v2026-04 cart payment surface (/api/payments/v2026-04/carts/{cart_token}/... paths, authenticated by the cart token in the path with no bearer — payment-method selection, VGS card tokenization, 3D Secure verification, and PayPal/Braintree/Klarna/Apple Pay flows); api-reference/commerce-v2026-04.yaml covers the v2026-04 commerce order-editing surface (/api/v202604/orders/{order_id}/edits paths, bearer-authenticated — post-checkout order edits that atomically insert items and add adjustments/discounts, with an optional dry-run preview); api-reference/webhooks-v0.yaml covers the unversioned webhooks surface (/api/... paths — webhook registration, delivery payloads, callback registrations, company events, and webhook/callback schemas); api-reference/company-v0.yaml covers the legacy unversioned company admin surface (/api/... paths, bearer-authenticated except two operations that take no credential, POST /api/company (create a company) and GET /api/agreements/{id} — company settings and management, customers, users, roles, subscription plans, subscription bundles, subscriptions, media, pages, catch-ups, inventory levels, domains, agreements, and admin order actions). company-v0 caveats: it is the legacy v0 admin contract and its lists use flat page/per_page offset pagination, which is expected there despite the general cursor-pagination rule; where an operation exists in both company-v0 and a versioned spec, prefer the versioned spec — the subscriptions lifecycle (list/create/show/update, cancel, pause, reactivate, resume, retry, skip, failed-cycle-waiver, discounts) and subscription bundles are superseded by checkout-v2026-04, and company pages/media CRUD plus the public pages, categories, products, and media list endpoints are superseded by storefront-v2026-04. Subscription plan management (/api/subscription_plans, resource-wrapped {"subscription_plan": {...}} bodies) exists only in company-v0. api-reference/members-v2025-06.yaml covers the v2025-06 unified Member identity surface (/api/v2025-06/members/... paths, bearer-authenticated — member list/create/show/update, lookup by email/username/external_id/legacy_customer_id, member-type assignment, and the sponsor genealogy read). Prefer it over the customers and reps surfaces when the member type matters: /customers does not serialize member_type. api-reference/analytics-v2026-04.yaml covers the v2026-04 Home dashboard analytics surface (/api/v202604/analytics/dashboard/... paths, bearer-authenticated — read-only endpoints for the Home > Overview, Home > Live, and Home > Field tabs, each accepting an optional country ISO alpha-2 query param that scopes aggregations to a single country).
> api-reference/analytics-v0.yaml covers the unversioned analytics surface that backs the fluid-admin Traffic tab (/api/analytics/... and /api/analytics/traffic/... paths, bearer-authenticated — the legacy shares/views/visitors summary plus traffic overview, ranked campaigns, sources, geographies, flows, and per-rep breakdown, all sharing one reporting-period contract).
> Successful responses wrap the resource payload alongside a top-level integer status and a meta object.
> Portal Definition authoring edits and synchronizes the portal JSON resource graph. Widget Package authoring builds either a company-owned or Droplet-owned Remote DOM package. These are separate contracts; do not imply that one defines the other.
> For Widget Package worker code, use only @fluid-app/portal-sdk/widgets/worker. Use only the Portal Definition and Widget Package workflows and public entry points documented here; do not infer support for undocumented surfaces.
> Every portal function and declarative capability used by a widget must appear in that widget's uses array. Use the same typed function value in uses; do not invent capability-name strings.
> Widget styling must use the portal's semantic theme variables for colors, typography, spacing, radii, borders, focus, and charts whenever a token represents the visual decision. Do not create a separate light or dark palette or duplicate theme controls as widget properties.
> Prefer worker-safe Fluid UI components exported by @fluid-app/portal-sdk/widgets/worker when they fit the interaction. When no exported component fits, use semantic HTML, accessible behavior, and the portal theme variables.
> A Portal Definition push updates the remote working definition. A portal version is an immutable snapshot, and activation is a separate live release operation.
> The Help Center (/help/...) is for merchants, admins and reps using Fluid. Its admin pages mirror the admin's routes: the screen at admin.fluid.app/settings/taxes is documented at /help/admin/settings/taxes. Use the Help Center for how-to questions about the admin, and the Developer Platform and API Reference for building integrations.
> Help Center pages describe what a company admin sees. A reader's role can hide screens and actions; admins manage roles on Settings > Roles (/help/admin/settings/roles). If someone can't find a screen or button, their role's permissions are the first thing to check.
> Send people who need Fluid support to /help/getting-help. Don't invent support email addresses, phone numbers or response times.

# Message members, customers and contacts

> Choose between Flow, Fluid's messaging center, and outbound messages. Welcome a new enrollee, send on someone's behalf from a droplet, set what members can see in Flow, and tell Fluid's bots apart.

Fluid gives you two ways to reach people. Pick by what the person should get.

* **Flow** is Fluid's messaging center: the **Messaging** screen in the admin and the **Messaging** tab in the mobile app. It holds direct and group conversations, channels, downline conversations, SMS and email conversations with contacts, bots, and **Today**. People read and reply there, in threads.
* **Today** is part of Flow: your company's own social feed. See [Today](#today).
* **Outbound messages** send one message from your company to one person, on a channel you choose: email, SMS, push, the person's preferred channel, or a Flow direct message. Each one goes out from your company's own sending identity, and Fluid keeps it with its delivery events.

Use outbound messages when your system decides to tell someone something. Use the Flow APIs when you're building or running the conversation itself.

## Which API to use

| You want to | Use |
| - | - |
| Send one person an email, a text or a push notification, and see whether it arrived | [Send an email](https://docs.fluid.app/api-reference/outbound-messages/send-an-email.md), [Send an SMS text message](https://docs.fluid.app/api-reference/outbound-messages/send-an-sms-text-message.md), [Send a push notification](https://docs.fluid.app/api-reference/outbound-messages/send-a-push-notification.md) |
| Reach a member on whatever channel works for them | [Send on the member's preferred channel](https://docs.fluid.app/api-reference/outbound-messages/send-on-the-members-preferred-channel.md) |
| Send a member a direct message in Flow from your company, your app, a person or a We-Bot | [Send a Flow direct message](https://docs.fluid.app/api-reference/outbound-messages/send-a-flow-direct-message.md) |
| Build a chat experience for a signed-in rep | The [member messaging API](https://docs.fluid.app/api/member-apis.md), starting with [Start a conversation](https://docs.fluid.app/api-reference/messaging/start-a-conversation.md) |
| Work in Flow as a signed-in admin: create channels and post to them | [Create a conversation](https://docs.fluid.app/api-reference/messaging--conversations/create-a-conversation.md) and [Create a message](https://docs.fluid.app/api-reference/messaging--messages/create-a-message.md) |
| Post to a Flow conversation with a company API token, acting for a named admin | [Create a conversation message](https://docs.fluid.app/api-reference/company-v0/company/create-a-conversation-message.md) |
| Post into a group or channel from another system, the way a Slack incoming webhook does | [Create an incoming webhook](https://docs.fluid.app/api-reference/messaging--incoming-webhooks/create-an-incoming-webhook.md) |
| Choose whom members can find and message, and whether they see Today | [Change the Member messaging policy](https://docs.fluid.app/api-reference/messaging-member-policy/change-the-member-messaging-policy.md) |
| Moderate channels and Today | [Remove a channel message](https://docs.fluid.app/api-reference/channel-messages/remove-a-channel-message.md), [Archive a Today post](https://docs.fluid.app/api-reference/messaging-today/archive-a-today-post.md) |
| Run an AI agent that works for your admins | [We-Bots](https://docs.fluid.app/api/guides/we-bots.md) |

WhatsApp has an endpoint, but Fluid can't send WhatsApp yet, so every request is refused.

## How outbound messages behave

These rules hold on every outbound channel:

* **Your company is always the sender.** Email goes from your company's sending address and SMS from your registered number. Fluid never falls back to a shared sender. If a channel isn't set up, the request is refused with a `code` and a `setup` block that says what's left and links to the admin screen that finishes it.
* **Name the recipient once.** Email and SMS take an address (`to`), `contact_id`, `customer_id` or `member_id`. Push, preferred and Flow take `member_id` only. Customers and members are the same people.
* **Send each message once.** Pass an `idempotency_key`, or the `Idempotency-Key` header. Sending again with the same key returns the first message instead of sending twice.
* **Marketing follows your rules.** A `marketing` message needs the person's marketing consent for the channel. One asked for during the person's quiet hours waits until they end, unless you pass `no_queue`. Set quiet hours and frequency caps with [Change marketing send rules](https://docs.fluid.app/api-reference/outbound-messages/change-marketing-send-rules.md). A `transactional` message, the default, skips both.
* **Every send is kept.** Accepted or refused, read it back with [Get a message and its delivery history](https://docs.fluid.app/api-reference/outbound-messages/get-a-message-and-its-delivery-history.md). A Flow message is recorded as sent without a delivery receipt.

Each channel needs its own permission: `outbound_messages.email`, `outbound_messages.sms`, `outbound_messages.push` or `outbound_messages.flow`. A company API token, a partner token, a droplet installation token with the `messaging` scope, or a We-Bot can send.

## Welcome a new enrollee

Say you want every new member to hear from you the moment they enroll.

**1. Listen for the enrollment**

[Create a webhook](https://docs.fluid.app/api-reference/webhooks/create-a-webhook.md) for the `enrollment` resource's `completed` event. See [Webhooks](https://docs.fluid.app/api/guides/webhooks.md) for verifying deliveries. The delivery's `member` object carries the new member's id, and `sponsor` names who sponsored them.

**2. Pick the channel**

A new enrollee might not have the app yet. Send a welcome on [their preferred channel](https://docs.fluid.app/api-reference/outbound-messages/send-on-the-members-preferred-channel.md): Fluid tries their ranked contact methods, then push, email and SMS, and uses the first one your company has set up and they can receive. If you want the welcome to start a conversation in Flow, send a [Flow direct message](https://docs.fluid.app/api-reference/outbound-messages/send-a-flow-direct-message.md) instead.

**3. Send it once**

Use the enrollment as your idempotency key, so a retried webhook delivery doesn't send a second welcome:

```json theme={null}
{
  "member_id": "0199c2d4-8a1e-7b35-9f02-6d4e1a7c3b58",
  "message_type": "transactional",
  "idempotency_key": "welcome-enrollment-58213",
  "subject": "Welcome to Bloom Wellness, Jordan",
  "title": "Welcome to Bloom Wellness",
  "text": "Hi Jordan, welcome aboard. Your sponsor Priya will be in touch this week, and your starter guide is waiting in the app.",
  "url": "/welcome"
}
```

**4. Handle a refusal**

A refusal names its reason in `code`. For the preferred channel, `setup.tried` lists each channel Fluid tried and why it skipped it. `no_reachable_channel` means none of them worked for this person.

To have the sponsor say hello in Flow, send the Flow message as the sponsor with `send_as`. That needs the sponsor's permission first. See the next section.

You can also give the job to a [We-Bot](https://docs.fluid.app/api/guides/we-bots.md): an event trigger on the enrollment wakes the bot, and the bot sends with `bot_id`.

## Send on someone's behalf

A droplet or a back-office service sends with its own token. Who the message appears to come from depends on what the request names:

| The request | The message comes from |
| - | - |
| A person's own token | That person |
| An app token, with nothing else | Your app's own sender, with its name, its icon and an **App** badge. Fluid creates it on your app's first send. |
| `send_as` naming a member or an admin | That person, with your app shown as `sent_via` |
| `bot_id` | One of your company's We-Bots |

**Sending as a person needs their consent.** A person lets your app send as them with [Let an app send as you](https://docs.fluid.app/api-reference/flow-senders/let-an-app-send-as-you.md), for transactional messages, marketing messages, or both. Only that person can grant it. An admin can't grant it for them. Without it, a `send_as` request is refused with `sender_not_authorized`, and Fluid doesn't fall back to your app's sender. A person withdraws it with [Stop an app sending as you](https://docs.fluid.app/api-reference/flow-senders/stop-an-app-sending-as-you.md).

**A droplet must ask for messaging.** A droplet installation token reaches outbound messages only with the opt-in `messaging` scope. Request it when you [create your droplet](https://docs.fluid.app/guides/creating-droplets.md).

**Admins stay in control.** [List app senders](https://docs.fluid.app/api-reference/flow-senders/list-app-senders.md) shows every app that posts in Flow. [Change an app sender](https://docs.fluid.app/api-reference/flow-senders/change-an-app-sender.md) renames one, changes its icon, or disables it. A disabled sender's sends are refused with `app_sender_disabled`.

**Replies come back as webhooks.** When a member replies to your app's Flow message, your droplet receives it through the `bot_message` resource's `created` webhook.

## Today

Today is your company's own social feed inside Flow, much like a timeline on a social network. Admins and members post updates, comment and like, and everyone in the company can follow along.

* **A large community can connect without the noise.** Posting to Today never notifies anyone. A company with a hundred thousand members can share wins, news and stories without pinging everyone in real time, the way a busy channel would.
* **People catch up when it suits them.** The feed waits for them, so Flow's conversations stay for the messages that need an answer.
* **Admins stay in charge.** Members can report a post, and admins can archive and restore posts and comments. See [Moderate channels and Today](#moderate-channels-and-today).

Today can be turned off. Hide it from members with `today_enabled`, or let only admins post with `today_posting`. Both are part of the [Member messaging policy](#set-what-members-can-see).

## Set what members can see

Some companies keep members from finding and messaging each other, for privacy or to prevent cross-recruiting between teams. The [Member messaging policy](https://docs.fluid.app/api-reference/messaging-member-policy/get-the-member-messaging-policy.md) sets this for the whole company. Change it with [Change the Member messaging policy](https://docs.fluid.app/api-reference/messaging-member-policy/change-the-member-messaging-policy.md), or in the admin: open **Messaging**, then choose **Settings** > **Flow settings**. See [Messaging](https://docs.fluid.app/help/admin/messages.md#flow-settings).

| Setting | What it does |
| - | - |
| `directory_scope` | Whom a member may see, search and message among your members. `all_members` is everyone, the default. `team_graph` limits them to their Team Graph, their downline on any tree. `no_direct_messages` allows no other member. |
| `include_upline` | Under `team_graph`, whether a member also reaches the members above them, such as their sponsor. On by default. |
| `show_email`, `show_phone`, `show_bio` | Which contact fields a member sees on another member. Email and phone are shown by default, bio isn't. |
| `today_enabled` | Whether members see Today. Admins always see it. On by default. |
| `today_posting` | Who may post to Today: `everyone`, the default, or only `admins`. |

The policy limits only a member reaching another member. Admins, staff and bots are always reachable, and a member can always reach them. Name and avatar are always shown. When a member falls out of reach, an existing conversation with them keeps its history but leaves the member's list and takes no new messages.

## Moderate channels and Today

Admins, and We-Bots running with their owner's rights, can moderate:

* **Channels:** [Read channel messages](https://docs.fluid.app/api-reference/channel-messages/read-channel-messages.md), [remove one](https://docs.fluid.app/api-reference/channel-messages/remove-a-channel-message.md) from any channel, or [restore it](https://docs.fluid.app/api-reference/channel-messages/restore-a-removed-channel-message.md). Direct and group conversations are never moderated.
* **Today:** [List open Today reports](https://docs.fluid.app/api-reference/messaging-today/list-open-today-reports.md), then [archive a post](https://docs.fluid.app/api-reference/messaging-today/archive-a-today-post.md) with a reason. An archived post leaves the feed for everyone and keeps its likes and comments, so you can [restore it](https://docs.fluid.app/api-reference/messaging-today/restore-a-today-post.md).

Every removal, archive and restore is audited, naming the admin, or the bot and its owner.

## Bots in Flow

Four kinds of automated sender can appear in Flow. They're managed separately:

| Kind | What it is | Manage it with |
| - | - | - |
| **We-Bots** | AI agents your admins own. They work for admins only, act through the Fluid API within a permission grant, and can message customers through Fluid. | [We-Bots](https://docs.fluid.app/api/guides/we-bots.md) |
| **Response bots** | A bot backed by your own service. Fluid delivers messages sent to it to your webhook, and members chat with it one-to-one. | [Create a bot](https://docs.fluid.app/api-reference/messaging--bots/create-a-bot.md) with type `ResponseBot` |
| **Broadcast bots** | A bot that posts into channels. | [Create a bot](https://docs.fluid.app/api-reference/messaging--bots/create-a-bot.md) with type `BroadcastBot`, then [Add bot to conversation](https://docs.fluid.app/api-reference/messaging--bots/add-bot-to-conversation.md) |
| **Incoming webhooks** | A link another system posts to. Each post appears in one group or channel under the webhook's name. | [Create an incoming webhook](https://docs.fluid.app/api-reference/messaging--incoming-webhooks/create-an-incoming-webhook.md) |

An app sender isn't a bot. It's how your app's own outbound Flow messages are labelled.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.