curl --request POST \
--url https://api.flow.engineer/v0/conversations/{conversation_id}/typing \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'{
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"action": "typing"
}{
"error": {
"type": "invalid_request",
"message": "limit must be between 1 and 100.",
"hint": "Pass limit between 1 and 100 (default 20), and page with after or before.",
"doc_url": "https://api.flow.engineer/docs/errors/invalid_request",
"param": "limit"
}
}{
"error": {
"type": "authentication",
"message": "No valid API key was given.",
"hint": "Send the header Authorization: Bearer fk_test_... (or fk_live_...); no key yet? Get a test key with curl -X POST https://api.flow.engineer/v0/sandbox/keys",
"doc_url": "https://api.flow.engineer/docs/errors/authentication"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"channel": "telegram",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"channel": "telegram",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}{
"error": {
"type": "outside_window",
"message": "Last message from the contact was 31h ago; WhatsApp allows only templates now.",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"channel": "whatsapp",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
}
}{
"error": {
"type": "invalid_request",
"message": "The request body is larger than 33554432 bytes.",
"hint": "Send a smaller body; upload media with POST /v0/files and send its file_id instead of inlining it.",
"doc_url": "https://api.flow.engineer/docs/errors/invalid_request"
}
}{
"error": {
"type": "unsupported_content",
"channel": "telegram",
"param": "kind",
"message": "Carousels work on WhatsApp only.",
"hint": "On Telegram, send a basic message, then one buttons message with an image header per card.",
"doc_url": "https://api.flow.engineer/docs/errors/unsupported_content",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
}
}{
"error": {
"type": "new_contact_limit",
"message": "This sender has started its 15 new conversations for today.",
"hint": "Retry after 3600 seconds; replies into existing conversations still go.",
"doc_url": "https://api.flow.engineer/docs/errors/new_contact_limit",
"retry_after": 3600,
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T"
}
}{
"error": {
"type": "channel_error",
"message": "The channel refused: the request timed out.",
"hint": "Typing and read receipts are safe to ignore; carry on and send your reply.",
"doc_url": "https://api.flow.engineer/docs/errors/channel_error",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"channel": "telegram",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}Show the typing indicator
| Channel | Works | Limits |
|---|---|---|
| Telegram | Yes | |
| Yes | within 24 hours of the contact’s last message, after they wrote at least once | |
| iMessage | Yes | within 5 minutes of the contact’s last message; not in group conversations; imessage.duration_seconds 1 to 60 |
| SMS (US, pilot) | No |
On SMS, send instead: nothing (SMS has no typing indicator); send your reply when it is ready.
Shows the typing indicator in a conversation. The body is optional: no
body or {} shows it. No channel lets it be cleared on request: it clears
itself when your next message goes, or after a few seconds, so call again
every few seconds while your agent works. Idempotency-Key works as on
every POST: a repeat with the same key within 24 hours answers the first
call’s result and does not show the indicator again, so give each call that
should show it its own key (or none). SMS answers 422 unsupported_content with param kind, and an iMessage
group conversation with param kind and channel_code
group_unsupported: nothing is sent, so leave typing out there.
The call goes to the channel at once, not behind the conversation’s queued
messages, so the channel’s answer is the call’s answer. It fails with
409 outside_window when the channel allows typing only inside a window
(iMessage: within 5 minutes of the contact’s last message; WhatsApp: within
24 hours of it, and only after the contact wrote at least once), and with
502 channel_error when the channel failed or timed out. Both are safe to
ignore: typing is a courtesy, so never hold back a reply because of it.
curl --request POST \
--url https://api.flow.engineer/v0/conversations/{conversation_id}/typing \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'{
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"action": "typing"
}{
"error": {
"type": "invalid_request",
"message": "limit must be between 1 and 100.",
"hint": "Pass limit between 1 and 100 (default 20), and page with after or before.",
"doc_url": "https://api.flow.engineer/docs/errors/invalid_request",
"param": "limit"
}
}{
"error": {
"type": "authentication",
"message": "No valid API key was given.",
"hint": "Send the header Authorization: Bearer fk_test_... (or fk_live_...); no key yet? Get a test key with curl -X POST https://api.flow.engineer/v0/sandbox/keys",
"doc_url": "https://api.flow.engineer/docs/errors/authentication"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"channel": "telegram",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"channel": "telegram",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}{
"error": {
"type": "outside_window",
"message": "Last message from the contact was 31h ago; WhatsApp allows only templates now.",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"channel": "whatsapp",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
}
}{
"error": {
"type": "invalid_request",
"message": "The request body is larger than 33554432 bytes.",
"hint": "Send a smaller body; upload media with POST /v0/files and send its file_id instead of inlining it.",
"doc_url": "https://api.flow.engineer/docs/errors/invalid_request"
}
}{
"error": {
"type": "unsupported_content",
"channel": "telegram",
"param": "kind",
"message": "Carousels work on WhatsApp only.",
"hint": "On Telegram, send a basic message, then one buttons message with an image header per card.",
"doc_url": "https://api.flow.engineer/docs/errors/unsupported_content",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
}
}{
"error": {
"type": "new_contact_limit",
"message": "This sender has started its 15 new conversations for today.",
"hint": "Retry after 3600 seconds; replies into existing conversations still go.",
"doc_url": "https://api.flow.engineer/docs/errors/new_contact_limit",
"retry_after": 3600,
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T"
}
}{
"error": {
"type": "channel_error",
"message": "The channel refused: the request timed out.",
"hint": "Typing and read receipts are safe to ignore; carry on and send your reply.",
"doc_url": "https://api.flow.engineer/docs/errors/channel_error",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v0/conversations/{conversation_id}/template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"channel": "telegram",
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}Authorizations
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
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.
1 - 255The API version to use, as a date. Without it, the version pinned to your app when it was created is used.
"2026-11-01"
Path Parameters
The conversation's ID.
A conversation ID, conv_ and a ULID.
^conv_[0-9A-HJKMNP-TV-Z]{26}$"conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
Body
The typing indicator, sent only (POST /v0/conversations/{conversation_id}/typing; a typing piece in a webhook
reply or on the stream does the same). It shows the indicator, which
clears itself when your next message goes or after a few seconds.
Response
The channel showed the indicator.
The result of a typing or read call.
A conversation ID, conv_ and a ULID.
^conv_[0-9A-HJKMNP-TV-Z]{26}$"conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1"
Which action the channel took. typing (the indicator was shown) or read (the read receipt was sent).
typing, read