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.