Skip to main content
POST
Send text with an iMessage effect

Authorizations

Authorization
string
header
required

An API key of one app, sent as Authorization: Bearer <key>. Keys start with fk_test_ (test mode: sandbox senders and test data only) or fk_live_ (live mode). Keep live keys on your server; never ship them in an app or page.

Headers

Idempotency-Key
string

A unique string (up to 255 characters) that makes this request safe to retry. A repeat with the same key within 24 hours returns the first answer instead of acting again. See "Idempotency" in the introduction.

Required string length: 1 - 255
Flow-Version
string<date>

The API version to use, as a date. Without it, the version pinned to your app when it was created is used.

Example:

"2026-11-01"

Path Parameters

conversation_id
string
required

The conversation's ID. A conversation ID, conv_ and a ULID.

Pattern: ^conv_[0-9A-HJKMNP-TV-Z]{26}$
Example:

"conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"

Body

application/json

Text sent with an iMessage effect, sent only (POST /v0/conversations/{conversation_id}/effect; iMessage). Which effects a contact's device shows may vary.

text
string
required

The text, sent exactly as written, at most 9999 characters. Longer text is refused with 400 invalid_request.

Required string length: 1 - 9999
effect
enum<string>
required

The effect.

Available options:
slam,
loud,
gentle,
invisible_ink,
echo,
spotlight,
balloons,
confetti,
love,
lasers,
fireworks,
celebration
kind
string
default:effect

Always effect. Optional on its endpoint; required where no URL names the kind.

Allowed value: "effect"
reply_to
string

Send this as an inline reply to an earlier message in the same conversation (Telegram, WhatsApp and iMessage show it quoted). SMS has no inline replies: there it answers 422 unsupported_content with param reply_to. Refused with 404 not_found (param reply_to) when the target is not a message in this conversation, and with 400 invalid_request (param reply_to) when the target never reached the channel (for example, it failed). If the target fails after the send was accepted, the reply goes out as a normal message.

Pattern: ^msg_[0-9A-HJKMNP-TV-Z]{26}$
Example:

"msg_01JB8ZD4M6P8R0T2V4X6Z8B0C2"

metadata
object

Up to 20 string pairs of your own, kept with the object and returned unchanged. Keys up to 40 characters, values up to 500.

Response

The message passed the gate and is queued for the channel.

One message in or out of a conversation, with its kind and content and its delivery status. What you send is what the contact gets: Flow never converts a message into another kind.

id
string
required

A message ID, msg_ and a ULID.

Pattern: ^msg_[0-9A-HJKMNP-TV-Z]{26}$
Example:

"msg_01JB8ZD4M6P8R0T2V4X6Z8B0C2"

conversation
string
required

A conversation ID, conv_ and a ULID.

Pattern: ^conv_[0-9A-HJKMNP-TV-Z]{26}$
Example:

"conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"

direction
enum<string>
required

in from the contact, out from your app.

Available options:
in,
out
status
enum<string>
required
  • received: inbound from the contact.
  • queued: accepted by the gate, waiting for its turn in the conversation.
  • sent: the channel accepted it.
  • delivered: it reached the contact's device, where the channel reports this.
  • read: the contact read it, where the channel reports this.
  • failed: it could not be sent; see error.
  • unsent: you unsent it.
Available options:
received,
queued,
sent,
delivered,
read,
failed,
unsent
content
object
required

A message's content: one kind object, in either direction, with kind (always present here) saying which. It is exactly what was sent or received, except metadata, which is kept once, at the message's own metadata, and not repeated here.

livemode
boolean
required

Whether the message belongs to live mode.

created_at
string<date-time>
required

When Flow received (inbound) or accepted (outbound) the message.

from
string
read-only

Inbound messages only, on every channel. The contact who wrote it; in a group conversation, which participant. Absent on your own messages.

Pattern: ^ct_[0-9A-HJKMNP-TV-Z]{26}$
Example:

"ct_01JB8ZB2J4K6N8Q0S2V4W6Y8A0"

network
enum<string>
read-only

iMessage channel only: the network that carried the message. imessage, or sms or rcs when the line has the SMS/RCS add-on (Sender.imessage.fallback) and the contact could not get iMessage. The network is chosen for each message when it is sent, never by your app. Set on inbound messages, and on your messages once the channel reports it (in message.sent, message.delivered or message.failed, as data.message.network); absent before that and on other channels. A message that went by sms or rcs showed no imessage.styles, no imessage.subject and no effect, and edits and unsends of it answer 422 unsupported_content with channel_code not_on_sms.

Available options:
imessage,
sms,
rcs
error
object

The details of an error.

channel_message_id
string

The channel's own ID for the message, once the channel accepted it.

sms
object
read-only

SMS text messages only: how the text travels as SMS. Carriers bill and deliver SMS in segments: 160 GSM-7 characters fit one segment (153 each when split), but a single character outside GSM-7 (an emoji, curly quotes, most non-Latin letters) makes the whole text UCS-2, 70 characters in one segment (67 each when split). An SMS send may use at most 10 segments: 1530 GSM-7 characters (fewer when it uses GSM-7's two-unit characters such as { or โ‚ฌ), or 670 when it holds an emoji or other character outside GSM-7; a longer text is refused with 400 invalid_request. Absent on MMS and on other channels.

reply_to
string
read-only

The Flow ID of the message this one replies to. For a sent message, the message the send named in reply_to. For a received message, the message it replies to inline (a Telegram or WhatsApp reply; on iMessage, the thread's root message). Absent when the message is not a reply or the quoted message is not known to Flow.

Pattern: ^msg_[0-9A-HJKMNP-TV-Z]{26}$
Example:

"msg_01JB8ZD4M6P8R0T2V4X6Z8B0C2"

metadata
object

Up to 20 string pairs of your own, kept with the object and returned unchanged. Keys up to 40 characters, values up to 500.

updated_at
string<date-time>

When the status last changed.