Delete a contact and their data
DELETE /v0/contacts/{contact_id}Erases the contact and what Flow keeps about them in this app and mode. It cannot be undone. Use it when the person asks you to delete their data, or when you delete them in your own product.
Erased at once:
- the contact's name and address (phone, username, Telegram user ID, iMessage handle) and, on SMS, their recorded consent and opt-out;
- the content of every message in their conversations, inbound and outbound, with reply quotes, metadata and what the channel reported back;
- the files sent or received in those conversations, including uploads you
sent them (a
file_idsent to a deleted contact is not found afterwards); - the events of those conversations: they are no longer returned by
GET /v0/events, the stream or webhooks (an event ID you hold still works as anafterorbeforecursor); - webhook deliveries of those events still pending (they are not sent), and messages still queued to the contact (they are not sent; a message already handed to the channel may still arrive);
- saved
Idempotency-Keyanswers that held their data: repeating such a request answers404 not_found.
Kept: IDs, timestamps, and the counts that bill and pace your senders
(allowances, new-contact budgets, warm-up). The contact and their
conversations answer 404 not_found from then on and are not listed. Flow
cannot delete what the channel itself keeps, such as the chat on the
person's own device.
On a shared sandbox sender the person leaves your app and must send the join
message again to talk to it. On SMS the opt-out is erased with the contact:
carriers keep blocking a number that texted STOP, so do not text it again
unless the person opts in again. If the person writes again, or you send to their address, they are a
new contact with a new ID and a new conversation (conversation.started),
and the channel's usual rules apply, such as the WhatsApp 24-hour window.
The first delete emits contact.deleted, which carries only the contact's ID.
Deleting a contact that is already deleted also answers 204, so the call is
safe to retry. An ID this app and mode never had (including a contact of your
other mode) answers 404 not_found with param contact_id, as GET does.
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
contact_idstringrequiredThe contact's ID.
Response
204
The contact is deleted (or was already).
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.