Chatfuel

Flows API Reference

Read and build Chatfuel flows through the Public API: flows and groups, blocks and connections, message and action components, keyword rules and test chats.

Last updated on

A flow is a scripted conversation made of blocks connected to each other; each block holds components such as a WhatsApp message, a list, a condition or a JSON API call. Through the Public API you can read flows, create and organize them, add and connect blocks, configure every component, manage keyword rules and triggers, and run test chats. Reading flows and running test chats works for Agent virtual users; every change needs Editor.

How to read flows

type Bot {
  # Agent.
  flowGroups: [FlowGroup!]!            # { id name flows { id name } }
  flowsWithoutGroup: [RegularFlow!]!
  defaultReplyFlows: [DefaultReplyFlow!]!
  flow(flowID: FlowID!): Flow!
}
query FlowStructure($botID: BotID!, $flowID: FlowID!) {
  bot(id: $botID) {
    flow(flowID: $flowID) {
      id
      name
      platform
      startingPointBlock { id }
      blocks {
        id
        name
        positionX
        positionY
        blockElements { id errors { __typename } }
      }
      connections { __typename }
    }
  }
}

Block and BlockElement are interfaces with one type per kind of block and component. Use inline fragments for the types you work with.

How to create and organize flows

All mutations on this page change flows and need Editor.

type Mutation {
  createFlow(botID: BotID!, platform: Platform!): Bot!
  updateFlowName(flowID: FlowID!, name: String!): Flow!
  deleteFlow(flowID: FlowID!): Bot!
  createFlowGroup(botID: BotID!): Bot!
  updateFlowGroupName(id: FlowGroupID!, name: String!): FlowGroup!
  deleteFlowGroup(flowGroupId: FlowGroupID!): Bot!
  moveFlowToGroup(flowID: FlowID!, groupID: FlowGroupID!): Bot!
  removeFlowFromGroup(flowID: FlowID!): Bot!
  sortFlowGroups(botID: BotID!, flowGroupIds: [FlowGroupID!]!): Bot!
  sortFlowsInGroup(groupID: FlowGroupID!, flowIds: [FlowID!]!): FlowGroup!
  sortUngroupedFlows(botID: BotID!, flowIds: [FlowID!]!): Bot!
}

How to work with blocks and connections

type Mutation {
  updateBlockName(flowID: FlowID!, blockID: BlockID!, name: String!): Block!
  updateBlockPosition(flowID: FlowID!, blockID: BlockID!, positionX: Int!, positionY: Int!): Block!
  updateBlockPositionBulk(flowID: FlowID!, update: [BlockPositionBulkUpdate!]!): Flow!
  deleteBlock(flowID: FlowID!, blockID: BlockID!): Flow!
  blockSetStartingPoint(flowID: FlowID!, blockID: BlockID!): Flow!
  blockEnableEntryPoint(flowID: FlowID!, blockID: BlockID!): Flow!
  blockDisableEntryPoint(flowID: FlowID!, blockID: BlockID!): Flow!
  sortBlockElements(blockID: BlockID!, elementIDs: [BlockElementID!]!): Block!
  blockElementDelete(botID: BotID!, elementID: BlockElementID!): Flow!

  # Block → block, or a component's output handle (a button, a condition branch) → block.
  blockToBlockConnectionCreateOrUpdate(flowID: FlowID!, request: BlockToBlockConnectionCreateRequest!): Flow!
  blockToBlockConnectionDelete(flowID: FlowID!, sourceBlockID: BlockID!): Flow!
  componentToBlockConnectionCreateOrUpdate(flowID: FlowID!, request: ComponentToBlockConnectionCreateRequest!): Flow!
  componentToBlockConnectionDelete(flowID: FlowID!, sourceBlockElementID: BlockElementID!, sourceHandleID: ComponentHandleID!): Flow!
}

Positions are canvas coordinates in pixels, the same as in the dashboard flow editor.

How to add components

Each component kind has a family of mutations named after it. Most families have three ways to create a component:

  • <family>CreateWithBlock(flowID, positionX, positionY) creates a new block with the component at the given position.
  • <family>CreateWithBlockAndConnection(flowID, request, positionX, positionY) also connects it to an existing block or handle given in request: { sourceBlockID, sourceBlockElementID, sourceHandleID }.
  • <family>CreateInBlock(blockID) adds the component to an existing block.

Setters then take the component's blockElementID. A WhatsApp text message, for example:

type Mutation {
  whatsAppTextCreateWithBlock(flowID: FlowID!, positionX: Int!, positionY: Int!): Flow!
  whatsAppTextCreateWithBlockAndConnection(flowID: FlowID!, request: UndefinedTargetBlockConnectionCreateRequest!, positionX: Int!, positionY: Int!): Flow!
  whatsAppTextCreateInBlock(blockID: BlockID!): ContentBlock!
  whatsAppTextSetText(blockElementID: BlockElementID!, text: String!): ContentBlock!
  whatsAppTextSetWaitForReplies(blockElementID: BlockElementID!, waitForReplies: Boolean!): ContentBlock!
  whatsAppTextSetSaveContactReplyToAttribute(blockElementID: BlockElementID!, saveContactReply: Boolean!, attribute: AttributeName): ContentBlock!
}

The component families and their mutations, after the family prefix:

  • whatsAppText, whatsAppImage, whatsAppVideo, whatsAppAudio, whatsAppDocument: the three create mutations, SetText or SetImageFile / SetVideoFile / SetAudioFile / SetDocumentFile, SetCaption (image, video, document), SetWaitForReplies, SetSaveContactReplyToAttribute.
  • whatsAppTextAndButtons: CreateWithBlock, CreateWithBlockAndConnection, SetHeaderText, SetBodyText, SetFooterText, SetButtonTitle, AddNewContinueFlowButton, DeleteButton, MoveButton, WaitForReplies, SetSaveContactReplyToAttribute.
  • whatsAppTextAndURL: CreateWithBlock, CreateWithBlockAndConnection, SetHeaderText, SetBodyText, SetFooterText, SetButtonTitle, SetButtonURL, WaitForReplies, SetSaveContactReplyToAttribute.
  • whatsAppList: CreateWithBlock, CreateWithBlockAndConnection, SetBodyText, SetButtonTitle, AddRow, DeleteRow, ReorderRows, SetRowTitle, SetRowDescription, WaitForReplies, SetSaveContactReplyToAttribute.
  • whatsAppTemplate: CreateWithBlock, CreateWithBlockAndConnection, SetTemplate, DeleteTemplate, SetHeaderTextParamValue, SetBodyTextParamValue, SetFooterTextParamValue, SetHeaderImageFile, SetHeaderVideoFile, SetHeaderDocumentFile, SetURLButtonTextParamValue, SetCopyCodeButtonCodeValue, SetWaitForReplies, SetSaveContactReplyToAttribute.
  • whatsAppScheduledMessage: CreateWithBlock, CreateWithBlockAndWATemplate, UpdateSegment, SetFirstSendTime, SetRepeatType, SetRepeatEveryNDays, SetOnCertainDates, SetWeekdays.
  • whatsAppOneTimeNotification: CreateWithBlock, CreateWithBlockAndWATemplate, UpdateSegment, Send.
  • widgetTextAndButtons: the three create mutations, SetText, AddNewContinueFlowButton, AddNewOpenURLButton, AddNewPhoneButton, SetButtonTitle, SetButtonURL, SetButtonPhone, DeleteButton, MoveButton, SetWaitForReplies, SetSaveContactReplyToAttribute.
  • widgetImage: the three create mutations, SetImageFile, SetWaitForReplies, SetSaveContactReplyToAttribute.
  • whatsAppSwitchToChatWithHumanAgent, facebookSwitchToChatWithHumanAgent, instagramSwitchToChatWithHumanAgent, tiktokSwitchToChatWithHumanAgent, widgetSwitchToChatWithHumanAgent: the three create mutations.
  • aiAgent: CreateWithBlock and CreateWithBlockAndConnection with a templateID from the aiAgentTemplates(locale:) query, UpdateAdditionalInstructions, CreateRule, DeleteRule, UpdateRuleTitle, UpdateRulePrompt. A custom AI agent uses aiAgentCustomUpdatePrompt, aiAgentCustomCreateRule, aiAgentCustomDeleteRule, aiAgentCustomUpdateRuleTitle and aiAgentCustomUpdateRulePrompt.
  • sendJson (the JSON API action): the three create mutations, UpdateHTTPMethod, UpdateURL, AddHeader, UpdateHeaderTitle, UpdateHeaderValue, DeleteHeader, AddURLParam, UpdateURLParamTitle, UpdateURLParamValue, DeleteURLParam, UpdatePayloadType, UpdateCustomRequestPayload, EnableResponseParsingRules, DisableResponseParsingRules, ResponseAddParsingRule, UpdateResponseParsingRuleJSONPath, UpdateResponseParsingRuleAttributeName, DeleteResponseParsingRule, TestRequest.
  • albatoIntegration: the three create mutations with a templateID, UpdateSelectedEvent, UpdateEventFieldValue, AddEventCustomField, RemoveEventCustomField, UpdateEventCustomFieldName, UpdateEventCustomFieldValue.
  • setCondition: the three create mutations, UpdateSegment.
  • setContactProperty: the three create mutations, SetAttribute, SetValue. clearContactProperty: the three create mutations, SetAttribute.
  • summarizeChat: the three create mutations, AddEntry, UpdateEntry, DeleteEntry.
  • redirectToFlow: CreateWithBlock, CreateWithBlockAndConnection, SetTargetFlow, RemoveTargetFlow.
  • triggeredMessage: CreateWithBlock, CreateWithBlockAndWATemplate, SetSegment.

How to integrate with JSON API explains what each sendJson setting does.

Keyword rules and triggers

Keyword rules send a contact to a flow or reply with a message when their text matches. Reading them with bot.keywordRules(first, after) and changing them both need Editor.

type Mutation {
  keywordRuleCreate(botID: BotID!): KeywordRule!
  # matchType: similarTo, contains or matches
  keywordRuleUpdateMatchType(botID: BotID!, keywordRuleID: KeywordRuleID!, matchType: KeywordRuleMatchType!): KeywordRule!
  keywordRuleUpdateKeywords(botID: BotID!, keywordRuleID: KeywordRuleID!, keywords: [String!]!): KeywordRule!
  # actionType: switchToFlow, sendMessage or doNothing, set per platform
  keywordRuleUpdateActionType(botID: BotID!, keywordRuleID: KeywordRuleID!, platform: Platform!, actionType: KeywordRuleActionType!): KeywordRule!
  keywordRuleDelete(botID: BotID!, keywordRuleID: KeywordRuleID!): Bot!

  # Triggers of triggered messages. An enabled trigger can't be changed (EnabledTriggerIsImmutable).
  # conditionType: LastMessageFromContact or ContactAttributeChanged
  triggerSetConditionType(id: TriggerID!, conditionType: TriggerConditionType!): Trigger!
  triggerSetAttributeFilter(id: TriggerID!, attrCondition: AttrFilterInput!): Trigger!
  triggerDeleteAttributeFilter(id: TriggerID!): Trigger!
  triggerSetDelay(id: TriggerID!, delay: TriggerDelayInput!): Trigger!
}

How to test a flow in a test chat

A test chat runs a flow, the whole bot or an automation in a sandbox conversation without messaging real contacts. Starting a session works for Agent:

type Mutation {
  previewResponsesStartInFlow(flowID: FlowID!): PreviewResponsesFlowSession!
  previewResponsesStartForBot(botID: BotID!, platform: Platform!): PreviewResponsesBotSession!
  previewResponsesStartForFuelyAutomation(botID: BotID!, fuelyAutomationID: FuelyAutomationID!): PreviewResponsesFuelyAutomationSession!
}

The session returns a conversationID. Play the contact's side with previewResponsesWhatsappTextSend, previewResponsesInstagramTextSend, previewResponsesFacebookTextSend, previewResponsesTikTokTextSend or previewResponsesWidgetTextSend, simulate comments with previewResponsesInstagramPostCommentSend and previewResponsesFacebookPostCommentSend, and simulate clicks with previewResponsesWhatsappContinueFlowBtnClickSend, previewResponsesWhatsappListRowClickSend, previewResponsesWhatsappTemplateQuickReplyBtnClickSend and the previewResponsesWidget*BtnClickSend mutations. All take botID and conversationID. Read the bot's answers with the messageAdded subscription described in messaging.

Common issues

"NotEnoughPermissions" when changing a flow

Agent virtual users can read flows and run test chats but not change them. Change the role to Editor.

"EnabledTriggerIsImmutable"

A triggered message can't be edited while it is on. Turn it off in the dashboard, change the trigger, and turn it on again.

A component shows errors in the flow

blockElements { errors } lists what is missing, such as an empty text or an unset template. The dashboard shows the same errors on the block; fill in the missing settings with the component's setters.

On this page