Get a conversation
GET /v0/conversations/{conversation_id}Returns one conversation with its window state.
Authorizations
AuthorizationstringheaderrequiredAn 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
Flow-Versionstring<date>The API version to use, as a date. Without it, the version pinned to your app when it was created is used.
Path Parameters
conversation_idstringrequiredThe conversation's ID.
Response
200 application/json
The conversation.
id string required A conversation ID, conv_ and a ULID.
app string required An app ID, app_ and a ULID.
type enum<string> Flow always sends it; read a missing one as direct (answers from
before groups existed). direct: one sender and one contact (every
channel). group: a group chat
one of your dedicated iMessage lines was added to; it has group and no
contact. Flow's shared iMessage line ignores group chats, so they never
reach your app from it.
channel enum<string> required A messaging channel. sms is US SMS and MMS (in pilot), from dedicated numbers only.
sender string required A sender ID, snd_ and a ULID.
contact string The contact the conversation is with. Always set when type is direct; absent on group conversations (each message's from says who wrote).
group Group read-only Group conversations only (iMessage): the group chat as Flow saw it last.
People who join or leave change participants without an event; Flow
updates the list when the group next writes. The channel's own group ID is
never exposed: use the conversation's ID.
Show child attributes
name string The group chat's name, when it has one.
participants GroupParticipant[] required The people in the group other than your line, each a contact on the channel (made the first time Flow sees them, like a one-to-one contact).
Show child attributes
contact string required A contact ID, ct_ and a ULID.
address ContactAddress required How the contact is reached on their channel. Which fields are set depends on the channel; do not assume phone.
Show child attributes
phone string E.164 phone number (WhatsApp and SMS; iMessage when the handle is a number).
username string A username without @ (Telegram, WhatsApp usernames).
telegram_user_id string Telegram's numeric user ID, as a string.
handle string iMessage handle (a phone number or an email address).
name string The person's display name, as the channel reports it. May be missing.
livemode boolean required Whether the conversation belongs to live mode.
last_inbound_at string<date-time> When the contact last wrote. Absent if they never have.
window_open_until string<date-time> WhatsApp only. Until when free-form messages may be sent; after it, only templates. Absent when the window is closed or the channel has none.
opted_in boolean required Whether the contact has agreed to receive messages (wrote first, joined the sandbox, or you recorded consent). Always true on group conversations, which begin with the group writing.
simulated boolean read-only true for a simulated conversation, whose contact exists only inside Flow (test mode only, from POST /v0/test/conversations); absent otherwise.
metadata Metadata Up to 20 string pairs of your own, kept with the object and returned unchanged. Keys up to 40 characters, values up to 500.
created_at string<date-time> required When the conversation began.
400 application/json
The request is malformed or a parameter is invalid (invalid_request).
error.param names the parameter. Every endpoint answers this for a
Flow-Version header that is not a date this API serves (param
Flow-Version), and every POST that takes an Idempotency-Key for a key
over 255 characters (param Idempotency-Key).
error ErrorBody required The details of an error.
Show child attributes
type enum<string> required What went wrong. A closed list: new types arrive only with a new API version.
Each type has a page at https://api.flow.engineer/docs/errors/<type>, given in
the error's doc_url; the error's hint says what to change for the case.
invalid_request(400, or 413 for a request body over the size limit): the request is malformed or a parameter is invalid. Fix the parameter named inparam; thehintsays what it must look like. Every endpoint answers it for aFlow-Versionheader that is not a version this API serves.authentication(401): the API key is missing, malformed, unknown, revoked or expired. AnAuthorization: Bearerheader with nothing after it usually means the environment variable holding the key was empty when the header was built (for an MCP client, when the server was added): thehintsays so. SendAuthorization: Bearer fk_test_...orfk_live_...with a current key; with no key at all, get a test key withPOST /v0/sandbox/keys. A sandbox key past itsexpires_athaschannel_codesandbox_key_expired: sign in to claim the app, or get a new key.permission(403): the key may not do this, for example a test key using a live sender, a sandbox contact who joined another app, a new conversation from an iMessage line that may only reply, or a send past the app's sandbox allowance (channel_codesandbox_allowance_used,sandbox_contact_limitorsandbox_channel_not_included). Use the key of the right mode, have the contact send your join message, wait for the contact to message the line first, or sign in through the device flow to lift the allowance. On SMS:contact_opted_out(the contact texted STOP; nothing more goes to them until they text START),consent_required(a start to someone who never texted your numbers: record their consent withconsenton the start). In a HIPAA account:hipaa_channel_not_covered(the channel has no business associate agreement; use SMS). Simulated conversations:simulated_contact(a real sender was pointed at a simulated contact; reply in the contact's simulated conversation),not_simulated(a simulated sender or test endpoint was pointed at a real contact),test_mode_only,simulated_conversation_limit. Inmessage.failed:sandbox_contact_left(the contact joined another app on the sandbox sender while the message was queued; have them send your join message again).not_found(404): no such object for this app and mode. Check the ID's prefix and that it was made with a key of the same mode (test and live data are separate).idempotency_conflict(409): the idempotency key was used for a different request (channel_codebody_mismatch: use a new key), or that request is still running (in_progress: waitretry_afterseconds and repeat it with the same key), or it already created a secret that is shown only once (secret_not_kept: creating a webhook endpoint, rotating its secret, connecting a WhatsApp number; a secret that was lost must be rotated again, and a WhatsApp number connected again to see its verify token).outside_window(409, or inmessage.failed): the channel will not deliver outside its conversation window. On WhatsApp the 24-hour window is closed: send a template (POST /v0/conversations/{conversation_id}/template, orPOST /v0/messageswithkindtemplateto start), or wait for the contact to write. On iMessage the contact has not messaged the line (or opted in) yet, or not recently, so the failure arrives as amessage.failedevent: wait for the contact to write, then reply in that conversation. Typing and read receipts answer409 outside_windowdirectly when the channel's window for them is closed (iMessage typing works only within 5 minutes of the contact's last message; WhatsApp read receipts go at any time); ignore it and send your reply. On SMS,channel_codequiet_hours: the contact has not texted in the last hour and it is inside the sender's quiet hours in their time zone; retry afterretry_afterseconds, or wait for them to text. Inmessage.failed:window_closed(WhatsApp's 24-hour window closed while the message was queued; send a template) andqueued_too_long(the message waited in the queue longer than its sender allows, for example while the sender was paused; send it again if it still applies).unsupported_content(422): the conversation's channel does not take this kind, field, block or value, and nothing was sent; Flow never converts a message.paramnames what was refused:kind(the endpoint's kind is not on this channel, such as a carousel on Telegram), a field or block (reply_toon SMS,telegramon WhatsApp,telegram.is_big), or the field whose value is not taken (emojioutside Telegram's reaction emoji,buttonsfor more than 3 WhatsApp buttons).channelis the conversation's channel andhintsays what to send instead over plain HTTP; each endpoint's page lists its channels. In an iMessage group conversation, a reaction, typing or a read receipt answers it withparamkindandchannel_codegroup_unsupported: leave it out. Media to an SMS number without MMS answers it withparammediaandchannel_codeno_mms. An edit or unsend of an iMessage message that went by SMS or RCS (itsnetwork) answers it withchannel_codenot_on_sms: send a new message instead. An edit or unsend past the channel's time limit answers it withchannel_codeedit_window_closedorunsend_window_closed(iMessage: edits within 15 minutes of sending, unsends within 2 minutes; Telegram: unsends within 48 hours), and an iMessage edit of the message that started the conversation withfirst_message_not_editable;messagestates the limit and how long ago the message was sent. Send a new message instead.POST /v0/filesanswers it for a type Flow does not take (programs, web pages, unknown types). A send byfile_idof a document a contact sent before Flow malware-scanned documents answers it too: Flow sends only documents it scanned.new_contact_limit(429): the sender has used its budget for starting conversations. Waitretry_afterseconds; replies into existing conversations still go.sender_throttled(429): abuse signals tripped (the same text to many new contacts, many starts with no reply, blocks), so the sender may not start conversations untilretry_after; replies into existing conversations still go. Personalise first messages and start only conversations people expect.file_blocked(422): the file failed the malware scan and was not stored. Send a different file. (When the scan cannot run at all, the upload answers a retryable500 api_errorwithRetry-Afterinstead.)rate_limited(429): either too many requests for this key (the per-key request limit, reported in theRateLimit-*headers) or sends faster than the sender's sending rate (pacing). WaitRetry-After(retry_after) seconds and retry with the sameIdempotency-Key.channel_error(502, or inmessage.failed): the channel refused or failed the message, or timed out;channel_codecarries its own code. Readmessage, change what the channel objected to, and send again. From typing and read receipts, which call the channel at once, it is safe to ignore. SMS codes are Flow's, the same whichever carrier network carries the message:carrier_filtered(a carrier's spam filter blocked it: make it read like a person's message, no shortened links),unreachable,invalid_number,landline,registration_required(the number's 10DLC or toll-free registration is not approved yet),carrier_error, andprovider_not_configured(the SMS sender is not fully set up on Flow's side, so nothing was sent; contact the Flow team). Flow's own codes on every channel:channel_timeout_unknown_outcome(inmessage.failed: the channel did not answer after the message was sent, and the resends its policy allows did not settle it, so the message may have arrived or not; check with the contact before sending it again) andunknown_outcome(from typing and read receipts: the call timed out after it was sent).not_implemented(501): this endpoint or channel is not live yet during the beta. Use a channel that is live (Telegram, iMessage), or check the changelog.api_error(500, 503): something went wrong on Flow's side. Retry with the same idempotency key afterretry_afterseconds, and quoterequest_idif it persists.
message string required A sentence for a developer saying what went wrong. Do not parse it; switch on type.
hint string required One sentence saying what to change to make the request succeed, specific
to this case, for example "Send a template instead: POST
/v0/conversations/{conversation_id}/template." For unsupported_content
it says what to send instead over plain HTTP. Written for developers and
coding agents alike. Do not parse it; it may be reworded at any time.
doc_url string<uri> required The documentation page for this error's type, https://api.flow.engineer/docs/errors/<type>. It says what the error means, why it happens and how to fix it, with code.
param string The request parameter the error is about, as a dotted path (kind, telegram.is_big, buttons, cards[1].header.type, limit).
retry_after integer Seconds to wait before retrying, for errors that clear by themselves.
channel enum<string> The conversation's channel, on errors about what it takes (unsupported_content) and its windows (outside_window).
conversation string A conversation ID, conv_ and a ULID.
sender string A sender ID, snd_ and a ULID.
channel_code string For channel_error, the channel's own error code, as given by the
channel. For some other errors, Flow's own code naming the case, for
example sandbox_allowance_used (permission: the sandbox allowance is
used up), sandbox_contact_limit (permission: the allowance has no
room for another contact), sandbox_channel_not_included (permission:
the allowance does not cover this sandbox channel), sign_in_required
(permission: an app made without an account cannot do this) or
sandbox_key_expired (authentication: a key from POST /v0/sandbox/keys passed its expires_at; permission, for a send
that carries no key, such as a reply in a webhook answer, from such an
app). For idempotency_conflict, always one of body_mismatch (the
key was used for a different request), in_progress (the first
request is still running; retry_after says when to repeat it) or
secret_not_kept (its answer carried a secret shown only once).
SMS: contact_opted_out and consent_required (permission),
quiet_hours (outside_window, with retry_after), and
carrier_filtered, unreachable, invalid_number, landline,
registration_required, carrier_error and provider_not_configured
(channel_error). HIPAA accounts: hipaa_channel_not_covered
(permission). Connecting your own WhatsApp number (POST /v0/senders): whatsapp_token_malformed, whatsapp_token_rejected,
whatsapp_app_secret_malformed and whatsapp_number_not_in_account
(invalid_request), and whatsapp_number_taken,
whatsapp_account_taken and whatsapp_number_managed (permission).
Simulated conversations (permission): test_mode_only,
not_simulated, simulated_contact and simulated_conversation_limit.
For a message that failed after it was queued (message.failed):
sandbox_contact_left (permission), window_closed and
queued_too_long (outside_window), and
channel_timeout_unknown_outcome (channel_error: the channel never
confirmed the send, so it may or may not have arrived). iMessage
(unsupported_content): group_unsupported (a reaction, typing or a
read receipt in a group conversation; param kind) and
not_on_sms (an edit or unsend of a message that went by SMS or RCS;
param kind). SMS (unsupported_content): no_mms (media to a
number without MMS; param media).
Edits and unsends (unsupported_content): edit_window_closed and
unsend_window_closed (the message is older than the channel allows
for the change) and first_message_not_editable (iMessage: the message
that started the conversation). From typing and
read receipts, unknown_outcome (channel_error: the call timed out after
it was sent).
request_id string Flow's ID for this request. Quote it when asking for help.
401 application/json
The API key is missing, malformed, unknown, revoked or expired (authentication).
error ErrorBody required The details of an error.
Show child attributes
type enum<string> required What went wrong. A closed list: new types arrive only with a new API version.
Each type has a page at https://api.flow.engineer/docs/errors/<type>, given in
the error's doc_url; the error's hint says what to change for the case.
invalid_request(400, or 413 for a request body over the size limit): the request is malformed or a parameter is invalid. Fix the parameter named inparam; thehintsays what it must look like. Every endpoint answers it for aFlow-Versionheader that is not a version this API serves.authentication(401): the API key is missing, malformed, unknown, revoked or expired. AnAuthorization: Bearerheader with nothing after it usually means the environment variable holding the key was empty when the header was built (for an MCP client, when the server was added): thehintsays so. SendAuthorization: Bearer fk_test_...orfk_live_...with a current key; with no key at all, get a test key withPOST /v0/sandbox/keys. A sandbox key past itsexpires_athaschannel_codesandbox_key_expired: sign in to claim the app, or get a new key.permission(403): the key may not do this, for example a test key using a live sender, a sandbox contact who joined another app, a new conversation from an iMessage line that may only reply, or a send past the app's sandbox allowance (channel_codesandbox_allowance_used,sandbox_contact_limitorsandbox_channel_not_included). Use the key of the right mode, have the contact send your join message, wait for the contact to message the line first, or sign in through the device flow to lift the allowance. On SMS:contact_opted_out(the contact texted STOP; nothing more goes to them until they text START),consent_required(a start to someone who never texted your numbers: record their consent withconsenton the start). In a HIPAA account:hipaa_channel_not_covered(the channel has no business associate agreement; use SMS). Simulated conversations:simulated_contact(a real sender was pointed at a simulated contact; reply in the contact's simulated conversation),not_simulated(a simulated sender or test endpoint was pointed at a real contact),test_mode_only,simulated_conversation_limit. Inmessage.failed:sandbox_contact_left(the contact joined another app on the sandbox sender while the message was queued; have them send your join message again).not_found(404): no such object for this app and mode. Check the ID's prefix and that it was made with a key of the same mode (test and live data are separate).idempotency_conflict(409): the idempotency key was used for a different request (channel_codebody_mismatch: use a new key), or that request is still running (in_progress: waitretry_afterseconds and repeat it with the same key), or it already created a secret that is shown only once (secret_not_kept: creating a webhook endpoint, rotating its secret, connecting a WhatsApp number; a secret that was lost must be rotated again, and a WhatsApp number connected again to see its verify token).outside_window(409, or inmessage.failed): the channel will not deliver outside its conversation window. On WhatsApp the 24-hour window is closed: send a template (POST /v0/conversations/{conversation_id}/template, orPOST /v0/messageswithkindtemplateto start), or wait for the contact to write. On iMessage the contact has not messaged the line (or opted in) yet, or not recently, so the failure arrives as amessage.failedevent: wait for the contact to write, then reply in that conversation. Typing and read receipts answer409 outside_windowdirectly when the channel's window for them is closed (iMessage typing works only within 5 minutes of the contact's last message; WhatsApp read receipts go at any time); ignore it and send your reply. On SMS,channel_codequiet_hours: the contact has not texted in the last hour and it is inside the sender's quiet hours in their time zone; retry afterretry_afterseconds, or wait for them to text. Inmessage.failed:window_closed(WhatsApp's 24-hour window closed while the message was queued; send a template) andqueued_too_long(the message waited in the queue longer than its sender allows, for example while the sender was paused; send it again if it still applies).unsupported_content(422): the conversation's channel does not take this kind, field, block or value, and nothing was sent; Flow never converts a message.paramnames what was refused:kind(the endpoint's kind is not on this channel, such as a carousel on Telegram), a field or block (reply_toon SMS,telegramon WhatsApp,telegram.is_big), or the field whose value is not taken (emojioutside Telegram's reaction emoji,buttonsfor more than 3 WhatsApp buttons).channelis the conversation's channel andhintsays what to send instead over plain HTTP; each endpoint's page lists its channels. In an iMessage group conversation, a reaction, typing or a read receipt answers it withparamkindandchannel_codegroup_unsupported: leave it out. Media to an SMS number without MMS answers it withparammediaandchannel_codeno_mms. An edit or unsend of an iMessage message that went by SMS or RCS (itsnetwork) answers it withchannel_codenot_on_sms: send a new message instead. An edit or unsend past the channel's time limit answers it withchannel_codeedit_window_closedorunsend_window_closed(iMessage: edits within 15 minutes of sending, unsends within 2 minutes; Telegram: unsends within 48 hours), and an iMessage edit of the message that started the conversation withfirst_message_not_editable;messagestates the limit and how long ago the message was sent. Send a new message instead.POST /v0/filesanswers it for a type Flow does not take (programs, web pages, unknown types). A send byfile_idof a document a contact sent before Flow malware-scanned documents answers it too: Flow sends only documents it scanned.new_contact_limit(429): the sender has used its budget for starting conversations. Waitretry_afterseconds; replies into existing conversations still go.sender_throttled(429): abuse signals tripped (the same text to many new contacts, many starts with no reply, blocks), so the sender may not start conversations untilretry_after; replies into existing conversations still go. Personalise first messages and start only conversations people expect.file_blocked(422): the file failed the malware scan and was not stored. Send a different file. (When the scan cannot run at all, the upload answers a retryable500 api_errorwithRetry-Afterinstead.)rate_limited(429): either too many requests for this key (the per-key request limit, reported in theRateLimit-*headers) or sends faster than the sender's sending rate (pacing). WaitRetry-After(retry_after) seconds and retry with the sameIdempotency-Key.channel_error(502, or inmessage.failed): the channel refused or failed the message, or timed out;channel_codecarries its own code. Readmessage, change what the channel objected to, and send again. From typing and read receipts, which call the channel at once, it is safe to ignore. SMS codes are Flow's, the same whichever carrier network carries the message:carrier_filtered(a carrier's spam filter blocked it: make it read like a person's message, no shortened links),unreachable,invalid_number,landline,registration_required(the number's 10DLC or toll-free registration is not approved yet),carrier_error, andprovider_not_configured(the SMS sender is not fully set up on Flow's side, so nothing was sent; contact the Flow team). Flow's own codes on every channel:channel_timeout_unknown_outcome(inmessage.failed: the channel did not answer after the message was sent, and the resends its policy allows did not settle it, so the message may have arrived or not; check with the contact before sending it again) andunknown_outcome(from typing and read receipts: the call timed out after it was sent).not_implemented(501): this endpoint or channel is not live yet during the beta. Use a channel that is live (Telegram, iMessage), or check the changelog.api_error(500, 503): something went wrong on Flow's side. Retry with the same idempotency key afterretry_afterseconds, and quoterequest_idif it persists.
message string required A sentence for a developer saying what went wrong. Do not parse it; switch on type.
hint string required One sentence saying what to change to make the request succeed, specific
to this case, for example "Send a template instead: POST
/v0/conversations/{conversation_id}/template." For unsupported_content
it says what to send instead over plain HTTP. Written for developers and
coding agents alike. Do not parse it; it may be reworded at any time.
doc_url string<uri> required The documentation page for this error's type, https://api.flow.engineer/docs/errors/<type>. It says what the error means, why it happens and how to fix it, with code.
param string The request parameter the error is about, as a dotted path (kind, telegram.is_big, buttons, cards[1].header.type, limit).
retry_after integer Seconds to wait before retrying, for errors that clear by themselves.
channel enum<string> The conversation's channel, on errors about what it takes (unsupported_content) and its windows (outside_window).
conversation string A conversation ID, conv_ and a ULID.
sender string A sender ID, snd_ and a ULID.
channel_code string For channel_error, the channel's own error code, as given by the
channel. For some other errors, Flow's own code naming the case, for
example sandbox_allowance_used (permission: the sandbox allowance is
used up), sandbox_contact_limit (permission: the allowance has no
room for another contact), sandbox_channel_not_included (permission:
the allowance does not cover this sandbox channel), sign_in_required
(permission: an app made without an account cannot do this) or
sandbox_key_expired (authentication: a key from POST /v0/sandbox/keys passed its expires_at; permission, for a send
that carries no key, such as a reply in a webhook answer, from such an
app). For idempotency_conflict, always one of body_mismatch (the
key was used for a different request), in_progress (the first
request is still running; retry_after says when to repeat it) or
secret_not_kept (its answer carried a secret shown only once).
SMS: contact_opted_out and consent_required (permission),
quiet_hours (outside_window, with retry_after), and
carrier_filtered, unreachable, invalid_number, landline,
registration_required, carrier_error and provider_not_configured
(channel_error). HIPAA accounts: hipaa_channel_not_covered
(permission). Connecting your own WhatsApp number (POST /v0/senders): whatsapp_token_malformed, whatsapp_token_rejected,
whatsapp_app_secret_malformed and whatsapp_number_not_in_account
(invalid_request), and whatsapp_number_taken,
whatsapp_account_taken and whatsapp_number_managed (permission).
Simulated conversations (permission): test_mode_only,
not_simulated, simulated_contact and simulated_conversation_limit.
For a message that failed after it was queued (message.failed):
sandbox_contact_left (permission), window_closed and
queued_too_long (outside_window), and
channel_timeout_unknown_outcome (channel_error: the channel never
confirmed the send, so it may or may not have arrived). iMessage
(unsupported_content): group_unsupported (a reaction, typing or a
read receipt in a group conversation; param kind) and
not_on_sms (an edit or unsend of a message that went by SMS or RCS;
param kind). SMS (unsupported_content): no_mms (media to a
number without MMS; param media).
Edits and unsends (unsupported_content): edit_window_closed and
unsend_window_closed (the message is older than the channel allows
for the change) and first_message_not_editable (iMessage: the message
that started the conversation). From typing and
read receipts, unknown_outcome (channel_error: the call timed out after
it was sent).
request_id string Flow's ID for this request. Quote it when asking for help.
404 application/json
No such object for this app and mode (not_found).
error ErrorBody required The details of an error.
Show child attributes
type enum<string> required What went wrong. A closed list: new types arrive only with a new API version.
Each type has a page at https://api.flow.engineer/docs/errors/<type>, given in
the error's doc_url; the error's hint says what to change for the case.
invalid_request(400, or 413 for a request body over the size limit): the request is malformed or a parameter is invalid. Fix the parameter named inparam; thehintsays what it must look like. Every endpoint answers it for aFlow-Versionheader that is not a version this API serves.authentication(401): the API key is missing, malformed, unknown, revoked or expired. AnAuthorization: Bearerheader with nothing after it usually means the environment variable holding the key was empty when the header was built (for an MCP client, when the server was added): thehintsays so. SendAuthorization: Bearer fk_test_...orfk_live_...with a current key; with no key at all, get a test key withPOST /v0/sandbox/keys. A sandbox key past itsexpires_athaschannel_codesandbox_key_expired: sign in to claim the app, or get a new key.permission(403): the key may not do this, for example a test key using a live sender, a sandbox contact who joined another app, a new conversation from an iMessage line that may only reply, or a send past the app's sandbox allowance (channel_codesandbox_allowance_used,sandbox_contact_limitorsandbox_channel_not_included). Use the key of the right mode, have the contact send your join message, wait for the contact to message the line first, or sign in through the device flow to lift the allowance. On SMS:contact_opted_out(the contact texted STOP; nothing more goes to them until they text START),consent_required(a start to someone who never texted your numbers: record their consent withconsenton the start). In a HIPAA account:hipaa_channel_not_covered(the channel has no business associate agreement; use SMS). Simulated conversations:simulated_contact(a real sender was pointed at a simulated contact; reply in the contact's simulated conversation),not_simulated(a simulated sender or test endpoint was pointed at a real contact),test_mode_only,simulated_conversation_limit. Inmessage.failed:sandbox_contact_left(the contact joined another app on the sandbox sender while the message was queued; have them send your join message again).not_found(404): no such object for this app and mode. Check the ID's prefix and that it was made with a key of the same mode (test and live data are separate).idempotency_conflict(409): the idempotency key was used for a different request (channel_codebody_mismatch: use a new key), or that request is still running (in_progress: waitretry_afterseconds and repeat it with the same key), or it already created a secret that is shown only once (secret_not_kept: creating a webhook endpoint, rotating its secret, connecting a WhatsApp number; a secret that was lost must be rotated again, and a WhatsApp number connected again to see its verify token).outside_window(409, or inmessage.failed): the channel will not deliver outside its conversation window. On WhatsApp the 24-hour window is closed: send a template (POST /v0/conversations/{conversation_id}/template, orPOST /v0/messageswithkindtemplateto start), or wait for the contact to write. On iMessage the contact has not messaged the line (or opted in) yet, or not recently, so the failure arrives as amessage.failedevent: wait for the contact to write, then reply in that conversation. Typing and read receipts answer409 outside_windowdirectly when the channel's window for them is closed (iMessage typing works only within 5 minutes of the contact's last message; WhatsApp read receipts go at any time); ignore it and send your reply. On SMS,channel_codequiet_hours: the contact has not texted in the last hour and it is inside the sender's quiet hours in their time zone; retry afterretry_afterseconds, or wait for them to text. Inmessage.failed:window_closed(WhatsApp's 24-hour window closed while the message was queued; send a template) andqueued_too_long(the message waited in the queue longer than its sender allows, for example while the sender was paused; send it again if it still applies).unsupported_content(422): the conversation's channel does not take this kind, field, block or value, and nothing was sent; Flow never converts a message.paramnames what was refused:kind(the endpoint's kind is not on this channel, such as a carousel on Telegram), a field or block (reply_toon SMS,telegramon WhatsApp,telegram.is_big), or the field whose value is not taken (emojioutside Telegram's reaction emoji,buttonsfor more than 3 WhatsApp buttons).channelis the conversation's channel andhintsays what to send instead over plain HTTP; each endpoint's page lists its channels. In an iMessage group conversation, a reaction, typing or a read receipt answers it withparamkindandchannel_codegroup_unsupported: leave it out. Media to an SMS number without MMS answers it withparammediaandchannel_codeno_mms. An edit or unsend of an iMessage message that went by SMS or RCS (itsnetwork) answers it withchannel_codenot_on_sms: send a new message instead. An edit or unsend past the channel's time limit answers it withchannel_codeedit_window_closedorunsend_window_closed(iMessage: edits within 15 minutes of sending, unsends within 2 minutes; Telegram: unsends within 48 hours), and an iMessage edit of the message that started the conversation withfirst_message_not_editable;messagestates the limit and how long ago the message was sent. Send a new message instead.POST /v0/filesanswers it for a type Flow does not take (programs, web pages, unknown types). A send byfile_idof a document a contact sent before Flow malware-scanned documents answers it too: Flow sends only documents it scanned.new_contact_limit(429): the sender has used its budget for starting conversations. Waitretry_afterseconds; replies into existing conversations still go.sender_throttled(429): abuse signals tripped (the same text to many new contacts, many starts with no reply, blocks), so the sender may not start conversations untilretry_after; replies into existing conversations still go. Personalise first messages and start only conversations people expect.file_blocked(422): the file failed the malware scan and was not stored. Send a different file. (When the scan cannot run at all, the upload answers a retryable500 api_errorwithRetry-Afterinstead.)rate_limited(429): either too many requests for this key (the per-key request limit, reported in theRateLimit-*headers) or sends faster than the sender's sending rate (pacing). WaitRetry-After(retry_after) seconds and retry with the sameIdempotency-Key.channel_error(502, or inmessage.failed): the channel refused or failed the message, or timed out;channel_codecarries its own code. Readmessage, change what the channel objected to, and send again. From typing and read receipts, which call the channel at once, it is safe to ignore. SMS codes are Flow's, the same whichever carrier network carries the message:carrier_filtered(a carrier's spam filter blocked it: make it read like a person's message, no shortened links),unreachable,invalid_number,landline,registration_required(the number's 10DLC or toll-free registration is not approved yet),carrier_error, andprovider_not_configured(the SMS sender is not fully set up on Flow's side, so nothing was sent; contact the Flow team). Flow's own codes on every channel:channel_timeout_unknown_outcome(inmessage.failed: the channel did not answer after the message was sent, and the resends its policy allows did not settle it, so the message may have arrived or not; check with the contact before sending it again) andunknown_outcome(from typing and read receipts: the call timed out after it was sent).not_implemented(501): this endpoint or channel is not live yet during the beta. Use a channel that is live (Telegram, iMessage), or check the changelog.api_error(500, 503): something went wrong on Flow's side. Retry with the same idempotency key afterretry_afterseconds, and quoterequest_idif it persists.
message string required A sentence for a developer saying what went wrong. Do not parse it; switch on type.
hint string required One sentence saying what to change to make the request succeed, specific
to this case, for example "Send a template instead: POST
/v0/conversations/{conversation_id}/template." For unsupported_content
it says what to send instead over plain HTTP. Written for developers and
coding agents alike. Do not parse it; it may be reworded at any time.
doc_url string<uri> required The documentation page for this error's type, https://api.flow.engineer/docs/errors/<type>. It says what the error means, why it happens and how to fix it, with code.
param string The request parameter the error is about, as a dotted path (kind, telegram.is_big, buttons, cards[1].header.type, limit).
retry_after integer Seconds to wait before retrying, for errors that clear by themselves.
channel enum<string> The conversation's channel, on errors about what it takes (unsupported_content) and its windows (outside_window).
conversation string A conversation ID, conv_ and a ULID.
sender string A sender ID, snd_ and a ULID.
channel_code string For channel_error, the channel's own error code, as given by the
channel. For some other errors, Flow's own code naming the case, for
example sandbox_allowance_used (permission: the sandbox allowance is
used up), sandbox_contact_limit (permission: the allowance has no
room for another contact), sandbox_channel_not_included (permission:
the allowance does not cover this sandbox channel), sign_in_required
(permission: an app made without an account cannot do this) or
sandbox_key_expired (authentication: a key from POST /v0/sandbox/keys passed its expires_at; permission, for a send
that carries no key, such as a reply in a webhook answer, from such an
app). For idempotency_conflict, always one of body_mismatch (the
key was used for a different request), in_progress (the first
request is still running; retry_after says when to repeat it) or
secret_not_kept (its answer carried a secret shown only once).
SMS: contact_opted_out and consent_required (permission),
quiet_hours (outside_window, with retry_after), and
carrier_filtered, unreachable, invalid_number, landline,
registration_required, carrier_error and provider_not_configured
(channel_error). HIPAA accounts: hipaa_channel_not_covered
(permission). Connecting your own WhatsApp number (POST /v0/senders): whatsapp_token_malformed, whatsapp_token_rejected,
whatsapp_app_secret_malformed and whatsapp_number_not_in_account
(invalid_request), and whatsapp_number_taken,
whatsapp_account_taken and whatsapp_number_managed (permission).
Simulated conversations (permission): test_mode_only,
not_simulated, simulated_contact and simulated_conversation_limit.
For a message that failed after it was queued (message.failed):
sandbox_contact_left (permission), window_closed and
queued_too_long (outside_window), and
channel_timeout_unknown_outcome (channel_error: the channel never
confirmed the send, so it may or may not have arrived). iMessage
(unsupported_content): group_unsupported (a reaction, typing or a
read receipt in a group conversation; param kind) and
not_on_sms (an edit or unsend of a message that went by SMS or RCS;
param kind). SMS (unsupported_content): no_mms (media to a
number without MMS; param media).
Edits and unsends (unsupported_content): edit_window_closed and
unsend_window_closed (the message is older than the channel allows
for the change) and first_message_not_editable (iMessage: the message
that started the conversation). From typing and
read receipts, unknown_outcome (channel_error: the call timed out after
it was sent).
request_id string Flow's ID for this request. Quote it when asking for help.
429 application/json
Too many requests (rate_limited): either this key's request limit (see the
RateLimit-* headers) or the sender's sending rate (pacing) was exceeded;
retry after Retry-After seconds (also error.retry_after) with the same
Idempotency-Key. Or the sender has used its budget for starting
conversations (new_contact_limit), or the sender is throttled after abuse
signals (sender_throttled); wait retry_after seconds.
error ErrorBody required The details of an error.
Show child attributes
type enum<string> required What went wrong. A closed list: new types arrive only with a new API version.
Each type has a page at https://api.flow.engineer/docs/errors/<type>, given in
the error's doc_url; the error's hint says what to change for the case.
invalid_request(400, or 413 for a request body over the size limit): the request is malformed or a parameter is invalid. Fix the parameter named inparam; thehintsays what it must look like. Every endpoint answers it for aFlow-Versionheader that is not a version this API serves.authentication(401): the API key is missing, malformed, unknown, revoked or expired. AnAuthorization: Bearerheader with nothing after it usually means the environment variable holding the key was empty when the header was built (for an MCP client, when the server was added): thehintsays so. SendAuthorization: Bearer fk_test_...orfk_live_...with a current key; with no key at all, get a test key withPOST /v0/sandbox/keys. A sandbox key past itsexpires_athaschannel_codesandbox_key_expired: sign in to claim the app, or get a new key.permission(403): the key may not do this, for example a test key using a live sender, a sandbox contact who joined another app, a new conversation from an iMessage line that may only reply, or a send past the app's sandbox allowance (channel_codesandbox_allowance_used,sandbox_contact_limitorsandbox_channel_not_included). Use the key of the right mode, have the contact send your join message, wait for the contact to message the line first, or sign in through the device flow to lift the allowance. On SMS:contact_opted_out(the contact texted STOP; nothing more goes to them until they text START),consent_required(a start to someone who never texted your numbers: record their consent withconsenton the start). In a HIPAA account:hipaa_channel_not_covered(the channel has no business associate agreement; use SMS). Simulated conversations:simulated_contact(a real sender was pointed at a simulated contact; reply in the contact's simulated conversation),not_simulated(a simulated sender or test endpoint was pointed at a real contact),test_mode_only,simulated_conversation_limit. Inmessage.failed:sandbox_contact_left(the contact joined another app on the sandbox sender while the message was queued; have them send your join message again).not_found(404): no such object for this app and mode. Check the ID's prefix and that it was made with a key of the same mode (test and live data are separate).idempotency_conflict(409): the idempotency key was used for a different request (channel_codebody_mismatch: use a new key), or that request is still running (in_progress: waitretry_afterseconds and repeat it with the same key), or it already created a secret that is shown only once (secret_not_kept: creating a webhook endpoint, rotating its secret, connecting a WhatsApp number; a secret that was lost must be rotated again, and a WhatsApp number connected again to see its verify token).outside_window(409, or inmessage.failed): the channel will not deliver outside its conversation window. On WhatsApp the 24-hour window is closed: send a template (POST /v0/conversations/{conversation_id}/template, orPOST /v0/messageswithkindtemplateto start), or wait for the contact to write. On iMessage the contact has not messaged the line (or opted in) yet, or not recently, so the failure arrives as amessage.failedevent: wait for the contact to write, then reply in that conversation. Typing and read receipts answer409 outside_windowdirectly when the channel's window for them is closed (iMessage typing works only within 5 minutes of the contact's last message; WhatsApp read receipts go at any time); ignore it and send your reply. On SMS,channel_codequiet_hours: the contact has not texted in the last hour and it is inside the sender's quiet hours in their time zone; retry afterretry_afterseconds, or wait for them to text. Inmessage.failed:window_closed(WhatsApp's 24-hour window closed while the message was queued; send a template) andqueued_too_long(the message waited in the queue longer than its sender allows, for example while the sender was paused; send it again if it still applies).unsupported_content(422): the conversation's channel does not take this kind, field, block or value, and nothing was sent; Flow never converts a message.paramnames what was refused:kind(the endpoint's kind is not on this channel, such as a carousel on Telegram), a field or block (reply_toon SMS,telegramon WhatsApp,telegram.is_big), or the field whose value is not taken (emojioutside Telegram's reaction emoji,buttonsfor more than 3 WhatsApp buttons).channelis the conversation's channel andhintsays what to send instead over plain HTTP; each endpoint's page lists its channels. In an iMessage group conversation, a reaction, typing or a read receipt answers it withparamkindandchannel_codegroup_unsupported: leave it out. Media to an SMS number without MMS answers it withparammediaandchannel_codeno_mms. An edit or unsend of an iMessage message that went by SMS or RCS (itsnetwork) answers it withchannel_codenot_on_sms: send a new message instead. An edit or unsend past the channel's time limit answers it withchannel_codeedit_window_closedorunsend_window_closed(iMessage: edits within 15 minutes of sending, unsends within 2 minutes; Telegram: unsends within 48 hours), and an iMessage edit of the message that started the conversation withfirst_message_not_editable;messagestates the limit and how long ago the message was sent. Send a new message instead.POST /v0/filesanswers it for a type Flow does not take (programs, web pages, unknown types). A send byfile_idof a document a contact sent before Flow malware-scanned documents answers it too: Flow sends only documents it scanned.new_contact_limit(429): the sender has used its budget for starting conversations. Waitretry_afterseconds; replies into existing conversations still go.sender_throttled(429): abuse signals tripped (the same text to many new contacts, many starts with no reply, blocks), so the sender may not start conversations untilretry_after; replies into existing conversations still go. Personalise first messages and start only conversations people expect.file_blocked(422): the file failed the malware scan and was not stored. Send a different file. (When the scan cannot run at all, the upload answers a retryable500 api_errorwithRetry-Afterinstead.)rate_limited(429): either too many requests for this key (the per-key request limit, reported in theRateLimit-*headers) or sends faster than the sender's sending rate (pacing). WaitRetry-After(retry_after) seconds and retry with the sameIdempotency-Key.channel_error(502, or inmessage.failed): the channel refused or failed the message, or timed out;channel_codecarries its own code. Readmessage, change what the channel objected to, and send again. From typing and read receipts, which call the channel at once, it is safe to ignore. SMS codes are Flow's, the same whichever carrier network carries the message:carrier_filtered(a carrier's spam filter blocked it: make it read like a person's message, no shortened links),unreachable,invalid_number,landline,registration_required(the number's 10DLC or toll-free registration is not approved yet),carrier_error, andprovider_not_configured(the SMS sender is not fully set up on Flow's side, so nothing was sent; contact the Flow team). Flow's own codes on every channel:channel_timeout_unknown_outcome(inmessage.failed: the channel did not answer after the message was sent, and the resends its policy allows did not settle it, so the message may have arrived or not; check with the contact before sending it again) andunknown_outcome(from typing and read receipts: the call timed out after it was sent).not_implemented(501): this endpoint or channel is not live yet during the beta. Use a channel that is live (Telegram, iMessage), or check the changelog.api_error(500, 503): something went wrong on Flow's side. Retry with the same idempotency key afterretry_afterseconds, and quoterequest_idif it persists.
message string required A sentence for a developer saying what went wrong. Do not parse it; switch on type.
hint string required One sentence saying what to change to make the request succeed, specific
to this case, for example "Send a template instead: POST
/v0/conversations/{conversation_id}/template." For unsupported_content
it says what to send instead over plain HTTP. Written for developers and
coding agents alike. Do not parse it; it may be reworded at any time.
doc_url string<uri> required The documentation page for this error's type, https://api.flow.engineer/docs/errors/<type>. It says what the error means, why it happens and how to fix it, with code.
param string The request parameter the error is about, as a dotted path (kind, telegram.is_big, buttons, cards[1].header.type, limit).
retry_after integer Seconds to wait before retrying, for errors that clear by themselves.
channel enum<string> The conversation's channel, on errors about what it takes (unsupported_content) and its windows (outside_window).
conversation string A conversation ID, conv_ and a ULID.
sender string A sender ID, snd_ and a ULID.
channel_code string For channel_error, the channel's own error code, as given by the
channel. For some other errors, Flow's own code naming the case, for
example sandbox_allowance_used (permission: the sandbox allowance is
used up), sandbox_contact_limit (permission: the allowance has no
room for another contact), sandbox_channel_not_included (permission:
the allowance does not cover this sandbox channel), sign_in_required
(permission: an app made without an account cannot do this) or
sandbox_key_expired (authentication: a key from POST /v0/sandbox/keys passed its expires_at; permission, for a send
that carries no key, such as a reply in a webhook answer, from such an
app). For idempotency_conflict, always one of body_mismatch (the
key was used for a different request), in_progress (the first
request is still running; retry_after says when to repeat it) or
secret_not_kept (its answer carried a secret shown only once).
SMS: contact_opted_out and consent_required (permission),
quiet_hours (outside_window, with retry_after), and
carrier_filtered, unreachable, invalid_number, landline,
registration_required, carrier_error and provider_not_configured
(channel_error). HIPAA accounts: hipaa_channel_not_covered
(permission). Connecting your own WhatsApp number (POST /v0/senders): whatsapp_token_malformed, whatsapp_token_rejected,
whatsapp_app_secret_malformed and whatsapp_number_not_in_account
(invalid_request), and whatsapp_number_taken,
whatsapp_account_taken and whatsapp_number_managed (permission).
Simulated conversations (permission): test_mode_only,
not_simulated, simulated_contact and simulated_conversation_limit.
For a message that failed after it was queued (message.failed):
sandbox_contact_left (permission), window_closed and
queued_too_long (outside_window), and
channel_timeout_unknown_outcome (channel_error: the channel never
confirmed the send, so it may or may not have arrived). iMessage
(unsupported_content): group_unsupported (a reaction, typing or a
read receipt in a group conversation; param kind) and
not_on_sms (an edit or unsend of a message that went by SMS or RCS;
param kind). SMS (unsupported_content): no_mms (media to a
number without MMS; param media).
Edits and unsends (unsupported_content): edit_window_closed and
unsend_window_closed (the message is older than the channel allows
for the change) and first_message_not_editable (iMessage: the message
that started the conversation). From typing and
read receipts, unknown_outcome (channel_error: the call timed out after
it was sent).
request_id string Flow's ID for this request. Quote it when asking for help.
default application/json
An error. error.type says which (see ErrorType).
error ErrorBody required The details of an error.
Show child attributes
type enum<string> required What went wrong. A closed list: new types arrive only with a new API version.
Each type has a page at https://api.flow.engineer/docs/errors/<type>, given in
the error's doc_url; the error's hint says what to change for the case.
invalid_request(400, or 413 for a request body over the size limit): the request is malformed or a parameter is invalid. Fix the parameter named inparam; thehintsays what it must look like. Every endpoint answers it for aFlow-Versionheader that is not a version this API serves.authentication(401): the API key is missing, malformed, unknown, revoked or expired. AnAuthorization: Bearerheader with nothing after it usually means the environment variable holding the key was empty when the header was built (for an MCP client, when the server was added): thehintsays so. SendAuthorization: Bearer fk_test_...orfk_live_...with a current key; with no key at all, get a test key withPOST /v0/sandbox/keys. A sandbox key past itsexpires_athaschannel_codesandbox_key_expired: sign in to claim the app, or get a new key.permission(403): the key may not do this, for example a test key using a live sender, a sandbox contact who joined another app, a new conversation from an iMessage line that may only reply, or a send past the app's sandbox allowance (channel_codesandbox_allowance_used,sandbox_contact_limitorsandbox_channel_not_included). Use the key of the right mode, have the contact send your join message, wait for the contact to message the line first, or sign in through the device flow to lift the allowance. On SMS:contact_opted_out(the contact texted STOP; nothing more goes to them until they text START),consent_required(a start to someone who never texted your numbers: record their consent withconsenton the start). In a HIPAA account:hipaa_channel_not_covered(the channel has no business associate agreement; use SMS). Simulated conversations:simulated_contact(a real sender was pointed at a simulated contact; reply in the contact's simulated conversation),not_simulated(a simulated sender or test endpoint was pointed at a real contact),test_mode_only,simulated_conversation_limit. Inmessage.failed:sandbox_contact_left(the contact joined another app on the sandbox sender while the message was queued; have them send your join message again).not_found(404): no such object for this app and mode. Check the ID's prefix and that it was made with a key of the same mode (test and live data are separate).idempotency_conflict(409): the idempotency key was used for a different request (channel_codebody_mismatch: use a new key), or that request is still running (in_progress: waitretry_afterseconds and repeat it with the same key), or it already created a secret that is shown only once (secret_not_kept: creating a webhook endpoint, rotating its secret, connecting a WhatsApp number; a secret that was lost must be rotated again, and a WhatsApp number connected again to see its verify token).outside_window(409, or inmessage.failed): the channel will not deliver outside its conversation window. On WhatsApp the 24-hour window is closed: send a template (POST /v0/conversations/{conversation_id}/template, orPOST /v0/messageswithkindtemplateto start), or wait for the contact to write. On iMessage the contact has not messaged the line (or opted in) yet, or not recently, so the failure arrives as amessage.failedevent: wait for the contact to write, then reply in that conversation. Typing and read receipts answer409 outside_windowdirectly when the channel's window for them is closed (iMessage typing works only within 5 minutes of the contact's last message; WhatsApp read receipts go at any time); ignore it and send your reply. On SMS,channel_codequiet_hours: the contact has not texted in the last hour and it is inside the sender's quiet hours in their time zone; retry afterretry_afterseconds, or wait for them to text. Inmessage.failed:window_closed(WhatsApp's 24-hour window closed while the message was queued; send a template) andqueued_too_long(the message waited in the queue longer than its sender allows, for example while the sender was paused; send it again if it still applies).unsupported_content(422): the conversation's channel does not take this kind, field, block or value, and nothing was sent; Flow never converts a message.paramnames what was refused:kind(the endpoint's kind is not on this channel, such as a carousel on Telegram), a field or block (reply_toon SMS,telegramon WhatsApp,telegram.is_big), or the field whose value is not taken (emojioutside Telegram's reaction emoji,buttonsfor more than 3 WhatsApp buttons).channelis the conversation's channel andhintsays what to send instead over plain HTTP; each endpoint's page lists its channels. In an iMessage group conversation, a reaction, typing or a read receipt answers it withparamkindandchannel_codegroup_unsupported: leave it out. Media to an SMS number without MMS answers it withparammediaandchannel_codeno_mms. An edit or unsend of an iMessage message that went by SMS or RCS (itsnetwork) answers it withchannel_codenot_on_sms: send a new message instead. An edit or unsend past the channel's time limit answers it withchannel_codeedit_window_closedorunsend_window_closed(iMessage: edits within 15 minutes of sending, unsends within 2 minutes; Telegram: unsends within 48 hours), and an iMessage edit of the message that started the conversation withfirst_message_not_editable;messagestates the limit and how long ago the message was sent. Send a new message instead.POST /v0/filesanswers it for a type Flow does not take (programs, web pages, unknown types). A send byfile_idof a document a contact sent before Flow malware-scanned documents answers it too: Flow sends only documents it scanned.new_contact_limit(429): the sender has used its budget for starting conversations. Waitretry_afterseconds; replies into existing conversations still go.sender_throttled(429): abuse signals tripped (the same text to many new contacts, many starts with no reply, blocks), so the sender may not start conversations untilretry_after; replies into existing conversations still go. Personalise first messages and start only conversations people expect.file_blocked(422): the file failed the malware scan and was not stored. Send a different file. (When the scan cannot run at all, the upload answers a retryable500 api_errorwithRetry-Afterinstead.)rate_limited(429): either too many requests for this key (the per-key request limit, reported in theRateLimit-*headers) or sends faster than the sender's sending rate (pacing). WaitRetry-After(retry_after) seconds and retry with the sameIdempotency-Key.channel_error(502, or inmessage.failed): the channel refused or failed the message, or timed out;channel_codecarries its own code. Readmessage, change what the channel objected to, and send again. From typing and read receipts, which call the channel at once, it is safe to ignore. SMS codes are Flow's, the same whichever carrier network carries the message:carrier_filtered(a carrier's spam filter blocked it: make it read like a person's message, no shortened links),unreachable,invalid_number,landline,registration_required(the number's 10DLC or toll-free registration is not approved yet),carrier_error, andprovider_not_configured(the SMS sender is not fully set up on Flow's side, so nothing was sent; contact the Flow team). Flow's own codes on every channel:channel_timeout_unknown_outcome(inmessage.failed: the channel did not answer after the message was sent, and the resends its policy allows did not settle it, so the message may have arrived or not; check with the contact before sending it again) andunknown_outcome(from typing and read receipts: the call timed out after it was sent).not_implemented(501): this endpoint or channel is not live yet during the beta. Use a channel that is live (Telegram, iMessage), or check the changelog.api_error(500, 503): something went wrong on Flow's side. Retry with the same idempotency key afterretry_afterseconds, and quoterequest_idif it persists.
message string required A sentence for a developer saying what went wrong. Do not parse it; switch on type.
hint string required One sentence saying what to change to make the request succeed, specific
to this case, for example "Send a template instead: POST
/v0/conversations/{conversation_id}/template." For unsupported_content
it says what to send instead over plain HTTP. Written for developers and
coding agents alike. Do not parse it; it may be reworded at any time.
doc_url string<uri> required The documentation page for this error's type, https://api.flow.engineer/docs/errors/<type>. It says what the error means, why it happens and how to fix it, with code.
param string The request parameter the error is about, as a dotted path (kind, telegram.is_big, buttons, cards[1].header.type, limit).
retry_after integer Seconds to wait before retrying, for errors that clear by themselves.
channel enum<string> The conversation's channel, on errors about what it takes (unsupported_content) and its windows (outside_window).
conversation string A conversation ID, conv_ and a ULID.
sender string A sender ID, snd_ and a ULID.
channel_code string For channel_error, the channel's own error code, as given by the
channel. For some other errors, Flow's own code naming the case, for
example sandbox_allowance_used (permission: the sandbox allowance is
used up), sandbox_contact_limit (permission: the allowance has no
room for another contact), sandbox_channel_not_included (permission:
the allowance does not cover this sandbox channel), sign_in_required
(permission: an app made without an account cannot do this) or
sandbox_key_expired (authentication: a key from POST /v0/sandbox/keys passed its expires_at; permission, for a send
that carries no key, such as a reply in a webhook answer, from such an
app). For idempotency_conflict, always one of body_mismatch (the
key was used for a different request), in_progress (the first
request is still running; retry_after says when to repeat it) or
secret_not_kept (its answer carried a secret shown only once).
SMS: contact_opted_out and consent_required (permission),
quiet_hours (outside_window, with retry_after), and
carrier_filtered, unreachable, invalid_number, landline,
registration_required, carrier_error and provider_not_configured
(channel_error). HIPAA accounts: hipaa_channel_not_covered
(permission). Connecting your own WhatsApp number (POST /v0/senders): whatsapp_token_malformed, whatsapp_token_rejected,
whatsapp_app_secret_malformed and whatsapp_number_not_in_account
(invalid_request), and whatsapp_number_taken,
whatsapp_account_taken and whatsapp_number_managed (permission).
Simulated conversations (permission): test_mode_only,
not_simulated, simulated_contact and simulated_conversation_limit.
For a message that failed after it was queued (message.failed):
sandbox_contact_left (permission), window_closed and
queued_too_long (outside_window), and
channel_timeout_unknown_outcome (channel_error: the channel never
confirmed the send, so it may or may not have arrived). iMessage
(unsupported_content): group_unsupported (a reaction, typing or a
read receipt in a group conversation; param kind) and
not_on_sms (an edit or unsend of a message that went by SMS or RCS;
param kind). SMS (unsupported_content): no_mms (media to a
number without MMS; param media).
Edits and unsends (unsupported_content): edit_window_closed and
unsend_window_closed (the message is older than the channel allows
for the change) and first_message_not_editable (iMessage: the message
that started the conversation). From typing and
read receipts, unknown_outcome (channel_error: the call timed out after
it was sent).
request_id string Flow's ID for this request. Quote it when asking for help.
Thanks, we read every comment.