Skip to main content
Going live means sending from a dedicated sender of your own with a live key; your agent’s code does not change. The examples below assume FLOW_MESSAGING_KEY holds your live key (fk_live_...).
curl

Checklist

1

Get a live key

Sign in to the dashboard with a Flow account, switch to Live, and make an fk_live_... key on the Keys page (test keys take one call, see Keys and sign-in). Keep it on your server only, in its own variable (for example FLOW_MESSAGING_LIVE_KEY) so it does not replace your test key. Your own Telegram bot and your own WhatsApp number are self-serve; iMessage lines are arranged with the Flow team.
2

Get a dedicated sender

Telegram: POST /v0/senders with your bot’s token; it is active at once. WhatsApp: POST /v0/senders with your number’s IDs, token and app secret (see WhatsApp); it is active at once. iMessage: the Flow team connects a line to your app, and it then appears in GET /v0/senders with your live key (POST /v0/senders with "channel": "imessage" answers 501 not_implemented with any key; build meanwhile on simulated conversations of that channel).
3

Register your webhook with the live key

Webhook endpoints and their signing secrets belong to one mode: your test endpoint never receives live events. POST /v0/webhook_endpoints again with the live key and store the new whsec_... secret where your live deployment reads it; the test endpoint keeps its own secret.
4

Switch the key

Set FLOW_MESSAGING_KEY to the live key and deploy. Watch message.failed and sender.status_changed for the first days.

WhatsApp

Your own number

Connect a number in your own WhatsApp Business Account, under your own Meta app, with a live key: POST /v0/senders, or the Senders page of the dashboard. The Flow team can also connect a number for you. First, in Meta Business Manager:
  1. Create a Meta app of type Business with the WhatsApp product, and switch it to Live.
  2. Add the phone number to your WhatsApp Business Account, with an approved display name, and add a payment method in WhatsApp Manager (Meta bills its fees to you directly).
  3. Create a system user (Admin), assign it your WhatsApp Business Account (full control) and the app, and generate a token that never expires with whatsapp_business_messaging and whatsapp_business_management.
Then connect the number. Keep the token and the app secret (App settings > Basic) in environment variables, never in code or a chat:
curl
Use your number’s phone number ID (WhatsApp Manager, or App Dashboard > WhatsApp > API Setup), not the phone number itself. Add whatsapp_registration_pin (six digits) only when the number is not registered for the Cloud API yet, and display_name if you like.
  • Answer: 200 with the sender active and, only in this answer, setup: enter its callback_url and verify_token in your Meta app (App Dashboard > WhatsApp > Configuration) and subscribe the webhook_fields there, following its steps. Flow has already pointed this number’s webhooks at Flow (your other numbers keep theirs); the settings in your app make its field subscriptions apply. The verify token is shown only in this answer.
  • New token: send the number again the same way. It stays the same sender, with the same verify token.
  • Disconnect: DELETE /v0/senders/{sender_id} deletes the stored token and app secret and retires the sender. Nothing changes in your Meta app: remove Flow’s callback URL there yourself.
  • Numbers the Flow team connected are updated and disconnected by the Flow team (403 permission with channel_code whatsapp_number_managed, and 501 not_implemented on DELETE).

Numbers, quality and fees

  • Numbers: a number in your business’s own WhatsApp Business Account, or a number Flow provides.
  • Quality and tiers: the sender shows WhatsApp’s quality_rating (green, yellow, red) and its messaging tier in limits.whatsapp_tier. Replies to people who wrote first are not limited by the tier.
  • Fees: on a number Flow provides, WhatsApp’s own per-message fees (charged by Meta) are passed through. With your own WhatsApp Business Account, Meta bills its fees to your business directly, so add a payment method in WhatsApp Manager. See Pricing.

WhatsApp templates

A template is a message WhatsApp approved in advance. On WhatsApp you need one to message someone first, or to write more than 24 hours after their last message. Templates are created on your WhatsApp number, with a realistic sample for each placeholder:
curl
The answer is 201 with the template, pending until WhatsApp reviews it, its components as you sent them:
  • Always give samples. WhatsApp reviews a template with them. Put examples on the body and on a text header, one value per placeholder in order ({{1}} first), and example on a url button whose link ends in {{1}}: the end of the link, which Flow shows WhatsApp in place. Left out, Flow sends placeholder samples (x1, x2, …), which WhatsApp often rejects or moves to another category.
  • Sample limits: exactly one per placeholder; 1 to 60 characters in a header and 1 to 1024 in a body; no line breaks, tabs or more than four spaces in a row. The url sample has no spaces, and the link with it in place is at most 2000 characters.
  • Placeholders are numbered {{1}}, {{2}}, … with none skipped. A header has at most one, a footer none, and a url button’s link only {{1}}, at its end. A template that breaks these rules or the sample limits gets 400 invalid_request, and so do samples on a footer, a buttons part, a media header or text without placeholders.
  • Names use lowercase letters, digits and underscores. A name and language pair is unique per sender.
  • category is utility (updates about something the person asked for), marketing or authentication; it sets WhatsApp’s fee.
  • You receive template.status_changed when WhatsApp approves, rejects (with rejection_reason) or pauses it.
  • In the dashboard, open your WhatsApp number on the Senders page, then Templates: its New template form always sends its sample values.
  • Send it with POST /v0/conversations/{conversation_id}/template (or start a conversation with POST /v0/messages and "kind": "template"), with values for its placeholders, the url button’s by its position (from 0):

iMessage: a dedicated line

  • Get one: ask the Flow team for a line on the Dedicated plan (Pricing). They connect it to your app; it is listed in GET /v0/senders?channel=imessage with your live key. Flow’s shared line needs no setup: once your account has it (the free trial, kept on a paid plan), a live key sees it too, with your app’s live join message.
  • The person writes first: starting a conversation with a new contact is refused with 403 permission, unless writing first is switched on for the line (imessage.can_initiate). Writing first is available on request for dedicated lines, within a warm-up.
  • Add-ons on a dedicated line, arranged with the Flow team: SMS and RCS from the same number (for contacts who cannot get iMessage), and forwarding of phone calls. Group chats people add the line to reach your app as group conversations.
  • Get people to write: the sender’s address.link is the line’s opt-in link (when it has one): it opens Messages with the line and a prefilled text. Publish it on your site, receipts or QR codes. See Build an iMessage agent.

Telegram: your own bot

Create a bot with @BotFather and send its token: POST /v0/senders with channel: "telegram" and telegram_bot_token. It is connected and active at once. See Build a Telegram agent.
  • New token: after revoking a token in @BotFather, send the new one the same way. The bot stays the same sender; one Telegram rejected meanwhile is flagged until you do. Messages queued while it is flagged wait at most 72 hours, then fail with outside_window (channel_code queued_too_long).
  • Disconnect: DELETE /v0/senders/{sender_id} removes the bot’s webhook and token and retires the sender.
  • One app per bot: connecting a bot to another app moves it there and retires the old sender.

Before you launch

  • Handle outside_window, new_contact_limit and sender_throttled (see Errors). Know the sending limits and abuse signals: the same first message to many new contacts throttles a sender for 24 hours.
  • Deduplicate webhook deliveries on the event id, and use event IDs as idempotency keys.
  • Subscribe your webhook only to the event types you use.
  • Message content and media are kept for your plan’s retention period (30 days by default); store anything you need longer yourself.