Skip to main content

TellFlow Interactive Messages

To use interactive UI components like selection boxes, forms, cards, article lists, video selection, and Q&A within the chat, a Chatwoot-like format is used in the webhook response.

Format reference: Chatwoot – Interactive messages.

Webhook request and session_id: The mobile app sends a session_id with every message. On the n8n side, you should use this as the conversation memory key. Details: Webhook Session Memory.

Webhook / API Response Format​

The TellFlow mobile app uses the following structure. In the response body, you can directly send content, content_type, and content_attributes, or use the interactive_message object or interactive_message_json string (the mobile app prioritizes these).

Common Fields​

FieldTypeRequiredDescription
contentstringNoThe header text of the message (description).
content_typestringYestext | input_select | form | cards | article | video_select | question_answer
content_attributesobjectYes*Contains items based on output type. Can be {} for text.
interactive_messageobjectNoObject containing the above fields; if present, the mobile app uses this.
interactive_message_jsonstringNoJSON string of the interactive_message; used after parsing.

* content_attributes and items are required for all types except text.

How the Mobile App Extracts the Payload​

The mobile app tries to find the interactive data in this order:

  1. response.interactive_message (if it's an object)
  2. response.interactive_message_json (if it's a string → parse)
  3. Root-level content + content_type + content_attributes

JSON Schema (for Mobile Rendering)​

The following structures are compatible with n8n node outputs and the format the backend should return. Mobile widgets render based on these field names.

General Structure​

{
"content": "Header text (optional)",
"content_type": "input_select | form | cards | article | video_select | question_answer | text",
"content_attributes": { ... }
}

1. content_type: "text"​

Plain text only; no interactive component.

{
"content": "Hello, how can I help you?",
"content_type": "text",
"content_attributes": {}
}

2. content_type: "input_select"​

Selection buttons. When clicked, the selected value is sent as a user message.

content_attributes:

FieldTypeDescription
itemsarrayEach item: title (display text), value (value to be sent)
{
"content": "Select an option",
"content_type": "input_select",
"content_attributes": {
"items": [
{ "title": "Option 1", "value": "opt1" },
{ "title": "Option 2", "value": "opt2" }
]
}
}

3. content_type: "form"​

Form fields (text, email, textarea, select). On submit, a map of field name → value is sent.

content_attributes.items for each item:

FieldTypeDescription
namestringField name (key)
typestringtext | email | text_area | select
labelstringLabel
placeholderstringPlaceholder
defaultstringDefault value
optionsarrayOnly for select: [{ "label": "...", "value": "..." }]
{
"content": "Enter your details",
"content_type": "form",
"content_attributes": {
"items": [
{ "name": "email", "type": "email", "label": "Email", "placeholder": "email@example.com", "default": "" },
{ "name": "choice", "type": "select", "label": "Choice", "options": [{ "label": "A", "value": "a" }, { "label": "B", "value": "b" }] }
]
}
}

4. content_type: "cards"​

Card list: image, title, description, and action buttons (link or postback).

content_attributes.items for each item:

FieldTypeDescription
media_urlstringURL for the card image
titlestringTitle
descriptionstringDescription
actionsarrayButtons: type, text, uri (link) or payload (postback)

actions item:

FieldTypeDescription
typestringlink | postback
textstringButton text
uristringURL (for type: "link")
payloadstringValue to be sent as a message (for type: "postback")
{
"content": "Product cards",
"content_type": "cards",
"content_attributes": {
"items": [
{
"media_url": "https://example.com/image.jpg",
"title": "Product Name",
"description": "Short description",
"actions": [
{ "type": "link", "text": "Details", "uri": "https://example.com/detail" },
{ "type": "postback", "text": "Select", "payload": "SELECT_1" }
]
}
]
}
}

5. content_type: "article"​

Title + description + link list items (opens link on click).

content_attributes.items for each item:

FieldTypeDescription
titlestringTitle
descriptionstringDescription
linkstringURL
{
"content": "Related articles",
"content_type": "article",
"content_attributes": {
"items": [
{ "title": "Article 1", "description": "Summary", "link": "https://example.com/1" },
{ "title": "Article 2", "description": "Summary", "link": "https://example.com/2" }
]
}
}

6. content_type: "video_select"​

Video list (thumbnail, duration, play URL). Selection is passed back to the app via callback.

content_attributes.items for each item:

FieldTypeDescription
idstringUnique ID
titlestringTitle
thumbnail_urlstringPreview image URL
durationstringDuration (e.g., "2:30")
urlstringVideo URL
{
"content": "Select a video",
"content_type": "video_select",
"content_attributes": {
"items": [
{ "id": "v1", "title": "Video 1", "thumbnail_url": "https://...", "duration": "2:30", "url": "https://..." }
]
}
}

7. content_type: "question_answer"​

Question-answer pairs (usually displayed as accordion or flat text).

content_attributes.items for each item:

FieldTypeDescription
questionstringQuestion
answerstringAnswer
{
"content": "Frequently Asked Questions",
"content_type": "question_answer",
"content_attributes": {
"items": [
{ "question": "How do I cancel?", "answer": "Settings > Subscription > Cancel." },
{ "question": "Payment methods?", "answer": "Credit card and bank transfer." }
]
}
}

n8n Integration​

  • TellFlow Interactive Message: Used as an AI agent tool; generates selection, form, cards, article, video, Q&A, or text.
  • TellFlow Interactive Message (From Input): Not an AI tool; generates the same interactive message format from JSON input (from webhook or previous node). Output structure is identical.

Both nodes produce content, content_type, content_attributes, interactive_message, and interactive_message_json in the output. You can add this output to the response body using "Respond to Webhook" or "Set"; the mobile app is compatible with both root fields and interactive_message / interactive_message_json.

Mobile Components​

content_typeFileDescription
input_selectinteractive_options_widget.dartSelection buttons (title / value)
forminteractive_form_widget.dartText, email, textarea, select
cardsinteractive_cards_widget.dartmedia_url, title, description, actions (type, text, uri, payload)
articleinteractive_article_widget.dartTitle, description, link
video_selectinteractive_video_select_widget.dartThumbnail, duration, url
question_answerinteractive_question_answer_widget.dartQuestion-answer pairs

All components are selected and rendered via interactive_message_widget.dart based on the payload.