Skip to main content
A conversation is one sender talking with one contact; your agent always replies into a conversation, so the channel is already decided.
TypeScript
curl

The objects

IDs are a prefix plus a ULID, so they sort by creation time.

One channel per conversation

  • There is no cross-channel identity. The same person on Telegram and on WhatsApp is two contacts and two conversations. Flow never guesses that they are the same person, and never moves a conversation to another channel.
  • Never assume a phone number. A Telegram contact has a user ID, a WhatsApp contact may have only a username, and an iMessage handle may be an email address. Read contact.address for what the channel gives.
  • Reply where they wrote. Each event carries conversation.channel, so one agent can serve every channel with the same code.

What a conversation tells you

  • window_open_until (WhatsApp only; absent on Telegram and iMessage): until when free-form messages may be sent. After it, only a template. Every event repeats it in conversation.window_open_until.
  • type: direct (one contact, in contact) or group. Read a missing type as direct.
  • group (group conversations only): the group chat’s name, when it has one, and its participants, each a contact. A group has no contact; each inbound message’s from says who wrote. Group chats reach your app only from dedicated iMessage lines people add to them, and the API cannot create a group or change who is in it. See iMessage.
  • opted_in: the contact wrote first, joined the sandbox, or you recorded their consent. Always true on groups.
  • metadata: up to 20 string pairs of your own (for example your user ID), kept with the conversation.

Starting a conversation

Most conversations start when the person writes first. To write first, use POST /v0/messages: a basic or template message, with kind saying which, plus a sender and an address on that sender’s channel. On Telegram that works only for people who already started your bot. iMessage lines reply only unless writing first is switched on for the line (imessage.can_initiate, available on request for dedicated lines). A start always makes a direct conversation.
curl
Any other kind answers 422 unsupported_content with param kind: start with a basic message or a template, then send the other kinds into the conversation. to takes exactly one of contact, phone, telegram_user_id or handle. Starting a conversation spends the sender’s new-contact budget, and each channel has its own rule for who may be messaged first. See The send gate.