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.addressfor 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, once available; absent on Telegram and iMessage): until when free-form messages may be sent. After it, only a template. Every event repeats it inconversation.window_open_until.opted_in: the contact wrote first, joined the sandbox, or you recorded their consent.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, usePOST /v1/messages with a sender and an address on that sender’s channel. On Telegram that works only for people who already started your bot; Flow’s iMessage lines are reply-only, so they cannot write first.
curl
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.
Related
- Capabilities: what the conversation’s channel can show right now.
- List conversations and list a conversation’s messages.