cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Actions

Learn about building complex business logic contextually within Flows
Filter
Filter by Labels
Select any of the labels below to filter results.
Filters applied...
Sorted by:
Actions enable developers ways to add complex business logic and functionality that is executed contextually within Flows. They work like any other   reply   except they are linked to   Code actions,   Webhook actions,   or   Zapier actions. Simply drag and drop a   reply action   beneath a   trigger.     When and why to use Actions Actions make it easy to create complex apps with dynamic output. Example use cases: Call an API and send back replies Personalize or customize responses (using time of day) Send an email Handover conversations You create actions inside the   Actions view   either by creating   Code actions, configuring   Webhook actions,   or   Zapier actions. Read more on Actions: Code actions Webhook actions Zapier actions Payments actions Webviews actions  
View full article
by Khoros Staff Khoros Staff Jun 16, 2021
0
372
Execute custom code that is hosted on the Flow platform. Code actions are JavaScript that runs in a sandboxed environment and allows you to easily customize and extend Flow capabilities.   Limited execution time When using cloud code the code execution or a call to a service must be done within 10 seconds. Quick examples Send text async payload => { const text = new Text( `This is a reply text from your bot.` ) const message = new Message( `This is a reply text from your bot as a fallback text.` ) message.addResponse(text) return message } Send text with quick replies async payload => { const text = new Text( `This is a reply text from your bot.` ) text.addQuickReply( new QuickReply({ label : 'Again' , value : 'Get started' })) const message = new Message( `This is a reply text from your bot as a fallback text.` ) message.addResponse(text) return message } Sending an email async payload => { toolbelt.email({ to : 'name@domain.com' , subject : 'This is the subject of you email.' , message : 'Compose the body of your email here.' }) } Trigger a flow Within Code, you can choose to either reply directly with messages or trigger different flows. async payload => { trigger( 'EVENT' ) }    Read more on Code Actions: Payload Toolbelt API Calls Configuration Trigger events  Send Replies Params Manage state Debug  
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
430
A code action is a single function that is called along with a   payload . The payload contains metadata regarding the message and user that triggered the action. /** @param {object} payload - data and info @param {string} payload.threadId - Identifier for the conversation @param {string} payload.channelName - type of channel @param {string} payload.query - what the user sends @param {object} payload.params - data detected by AI @param {object} payload.user - user that triggered the action @param {string} payload.user.name - name of the user @param {string} [payload.user.profile.firstName] - first name of the user @param {string} [payload.user.profile.lastName] - Last name of the user @param {string} [payload.user.profile.fullName] - first and last name combined @param {string} [payload.user.profile.picture] - profile picture @param {string} [payload.user.profile.locale] - user language @param {string} [payload.user.profile.gender] - user gender @param {object} payload.match - matching flow and step @param {object} payload.match.flow - contains name and flowId of matching flow @param {object} payload.match.step - contains name and stepId of matching step */ async payload => { // Your custom logic } threadId The threadId is a unique identifier that represents the conversation. For some channels this identifier represents the user. For example, with Messenger this is the page specific ID (PSID). channelName With each call you als receive the type of channel. This is a simple string like   socket ,   whatsapp   or   rcs . API and webwidget Both the Socket API and Web widget are the socket channel query Usually, an action is triggered by a user saying something or sending a text message. If so, this property will contain the query. params Params contain any data extracted by the AI engine, or that is send by other integrations or channels user This object contains profile information regarding the user triggering the Code action. Except for name, most profile information is optional. Property Description name   profile.firstName Optional first name of the user profile.lastName Optional last name of the user profile.fullName Optional first and last name combined profile.picture Optional profile picture profile.locale Optional user language tags A list of (optional) tags applied match The match object will contain the matched   step   and   flow .
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
358
We provide a collection of builtin functions for doing stuff like sending notifications, emails or pausing a bot. Pausing a bot You can temporarily disable all automatic interaction for a number of minutes. The duration is configured within the brain settings   Minutes to auto pause. async payload => { // Disable the bot for a number of minutes // Check the brain settings toolbelt.pauseBot() } Handover Notify that the conversation needs to be taken over by a human. This will send a web push notification and place the interaction within the_take over required_list. Depending on the connected integration a conversation is moved into a different state. async payload => { // Move the thread into a hand over state toolbelt.handover() } Resolve Mark a conversation as resolved async payload => { // Move the thread into a hand over state toolbelt.resolve() } Send an email With this toolbelt function you can send an email notification. We support 2 types of email templates. Takeover This templates sends an email with the last 20 messages from the conversation to a specified recipient. async payload => { // Send an e-mail to notify a conversation needs to be taken over toolbelt.email({ to : 'name@company.com' , template : 'takeover' , hideButton : true //Optional }) } Custom This templates allows you to customise an email. async payload => { // Send an e-mail to notify a conversation needs to be taken over toolbelt.email({ to : 'name@company.com' , cc : 'name@company.com' , //Optional subject : 'Email subject' , message : 'Email message' }) } Delay Sometimes you need more control of timing in an Action. For that we provide a simple method that works similar to the native   setTimeout   JavaScript function. Max delay The maximum delay is   10 seconds   (10000) async payload => { // Delay the code by 2 secs toolbelt.delay( () => { // Executes after the delay ... }, 2000 ) } async payload => { // Or delay inside a async function by 2 secs await toolbelt.delay( 2000 ) // Executes after the delay ... } Unassigned interactions With cloud code you can build complex handover scenarios. By using   toolbelt.getUnassignedCount()   you can request the number of unassigned interactions within the chat app. async payload => { const count = await toolbelt.getUnassignedCount() if (count > 10 ) { return new Message( 'Sorry, its very busy at the moment..' ) } return new Message( 'Someone will be there shortly..' ) } Interaction URL Within the takeover email you'll get a link to any conversation. You can also request this link using   toolbelt.getInteractionUrl() . async payload => { const url = await toolbelt.getInteractionUrl() toolbelt.email({ to : 'name@domain.com' , subject : 'Check out the conversation' , message : `This is the link ${url} ` }) } Tags Tags are part of the   user   object within the   payload. They can be set and removed using the flow designer, but it's possible to dynamically add and remove tags using code Actions. async payload => { await toolbelt.addTags({ tags : [ { tagName : 'EXAMPLE_TAG_ONE' , tagValue : 'value 1' }, { tagName : 'EXAMPLE_TAG_TWO' , tagValue : 'value 2' } ], payload }) } Removing tags: async payload => { await toolbelt.removeTags({ tags : [ 'EXAMPLE_TAG_ONE' , 'EXAMPLE_TAG_TWO' ], payload }) }  
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
333
A common use case for code actions is to make API calls to external services. Requests From code actions you can call external APIs using a package called request. Request is based on the popular   axios   package. // GET Request async payload => { const result = await request.get( "https://some-external-api" ) console .info( 'Received data' , result.data) } // POST Request async payload => { const result = await request.post( "https://some-external-api" , { orderId : '1234' }) console .info( 'Received result' , result.data) } Catching errors Best practice is to catch and handle different errors when making API calls async payload => { try { // Make a request const result = await request.get( 'MY API ENDPOINT' ) // ... } catch (err) { if (err.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx console .error( 'Failed with response' , err.response.data) } else if (err.request) { // The request was made but no response was received console .error( 'Failed request' , err) } else { // Something happened in setting up the request that triggered an Error console .error( 'Failed in general' , err) } } } Read more Axios reference
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
346
Configuration can be used to share values globally across the project. A good example would be an API key, session key, and any other variable used across multiple cloud code actions. Data is stored on the project level and never expires. Values are stored encrypted. Configuration can be changed using the toolbelt configuration API or using the actions UI.   Code example async payload => { try { const secret = await toolbelt .config .get( 'secret_key' ) // Make a GET call Check https://github.com/mzabriskie/axios for specifics //we use secret_key config as api key to make a request const result = await request.get( `https://api.themoviedb.org/3/movie/popular?api_key= ${secret} ` ) //return results of api request to message return new Message(result.data.total_results) } catch (err) { console .log(err); } } Set a value Storing data can be done using the   toolbelt.config.set()   method. Provide a key and value to save. async payload => { const secret = await toolbelt .config .set( 'key' , 'value' ) } Get a value Fetch a value by key using the   get()   method. async payload => { const secret = await toolbelt .config .get( 'secret_key' ) } Note: If no data exists   get()   will return   null Removing values Remove a specific value by key async payload => { // Remove aa specific key await toolbelt .config .delete( 'key' ) } Reference toolbelt.config.set(key, value) Set config Returns:   Promise   - Promise that resolves with the value being set Properties Name  Type  Description Key string Key to value Value string  String to store toolbelt.config.update(key, value) Set config Returns:   Promise   - Promise that resolves with the value being updated Properties Name  Type  Description Key string Key to value Value string  String to store toolbelt.config.get(key) Retrieve data from config by key Returns:   Promise   - Promise that resolved with the value being stored or   null   if the key does not exist Properties Name  Type  Description Key string Key used to find the data toolbelt.config.delete(key) Remove data from config by key Returns:   Promise   - Resolves with the key of the deleted data Properties Name  Type  Description Key string Key of the data to delete
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
246
Within Code actions you can trigger events just like you would using the   UI . async payload => { trigger( 'EVENT_NAME' ) } This allows you to move static content away from your code and trigger flows based on more complex business rules or logic. async payload => { toolbelt.takeover() if ( await toolbelt.isBusinessHours({ label : "livechat" })) { trigger( 'TAKEOVER_OFFICE_HOURS' ) } else { trigger( 'TAKEOVER_OUT_OF_OFFICE' ) } } The example above is a piece of Cloud Code that will trigger 2 different flows depending on the current time.
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
260
Within Code actions all   response templates   are available. This allows you to build and send rich template responses within your custom code. There are two methods to send back messages to a user. The first is by simply returning within the cloud function, the other is by using the async   reply   method. async payload => { return new Message( 'Just saying hello' ) } It's also possible to reply with multiple messages. You might want to do that if you work with voice and speech based interfaces. async payload => { return [ new Message( 'Cats are amazing creatures!' ), new Message( 'Or are you a dog person?' ) ] } Async When you make a async call within your code it's not possible to reply with a message using the return method. Instead we provide a simple method called   reply . You can use reply to send back a single message back to a user. async payload => { // Send back a reply message to a user. // Use this when you have async logic like making a request to a REST API. const message = new Message( 'Just saying hello' ) reply(message) } Delays You can send text bubbles or any other template with delays. async payload => { const text1 = new Text( 'This is 1' ) text1.delay = 1000 // 1 sec const text2 = new Text( 'This is 2' ) text2.delay = 2000 const text3 = new Text( 'This is 3' ) text3.delay = 2000 const message = new Message( "This is 1, 2, 3" ) message.addResponse(text1) message.addResponse(text2) message.addResponse(text3) return message } Below are code examples of all the various message templates we support. Check our   reponse templates   for a complete reference. Text async payload => { const image = new Image({ title : "Image description" , url : "https://..." }) return new Message( 'Cats are amazing creatures!' ) .addResponse(image) } Quick Replies In addition to text only, you can also add quick replies. In the example below the first quick reply triggers an event. The second quick reply is a text type that sends text into the platform. async payload => { const text = new Text( 'Would you like to order the cat image?' ) text.addQuickReply( new QuickReply({ label : '👍' , value : 'confirm order' , type : 'event' })) text.addQuickReply( new QuickReply({ label : '👎' , value : 'no' , type : 'text' })) const message = new Message( 'Fallback text' ).addResponse(text) return message } Multiple bubbles This example would render 2 bubbles on a channel like Messenger, but just a single spoken message on for example Alexa. async payload => { const image1 = new Image({ title : "Image description" , url : "https://..." }) const image2 = new Image({ title : "Image description" , url : "https://..." }) return new Message( 'Cats are amazing creatures!' ) .addResponse(image1) .addResponse(image2) } Audio async payload => { const audio = new audio({ title : "Cool car" , url : "https://flow.ai/audio/vw.m4a" }) return new Message( 'listen to awesome audio' ) .addResponse(audio) } Buttons async payload => { // Send a message with a buttons template const buttons = new Buttons( "Vintage bikes and more" ) // Add a button .addButton( new Button({ label : "View website" , type : "url" , value : "https://flow.ai" })) // Add another button .addButton( new Button({ label : "Special offers" , type : "postback" , value : "Show me special offers" })) return new Message( 'Visit vintagebikes.. for all our offers' ) .addResponse(buttons) } Button types URL Opens a webpage async payload => { // Send a message with a buttons template const buttons = new Buttons( "Vintage bikes and more" ) // Add a button .addButton( new Button({ label : "View website" , type : "url" , value : "https://flow.ai" })) return new Message( 'Visit vintagebikes.. for all our offers' ) .addResponse(buttons) } Postback Pressing the button will send text: async payload => { // Send a message with a buttons template const buttons = new Buttons( "Vintage bikes and more" ) // Add a button .addButton( new Button({ label : "Special offers" , type : "postback" , value : "Show me the special offers" })) return new Message( 'Visit vintagebikes.. for all our offers' ) .addResponse(buttons) } Phone number Press the button to call a number: async payload => { // Send a message with a buttons template const buttons = new Buttons( "Vintage bikes and more" ) // Add a button .addButton( new Button({ label : "Call now" , type : "tel" , value : "+1 00 0000 0000" })) return new Message( 'Visit vintagebikes.. for all our offers' ) .addResponse(buttons) } Card A card can consist of an image, title, subtitle, and buttons: async payload => { // Create a button const button = new Button({ type : 'url' , label : 'Flow.ai website' , value : 'https://flow.ai' }) // Create a card const card = new Card({ title : "Corporate headquarters" , subtitle : "WeWork, Toronto, Canada" }) .addButton(button) // Create a message with fallback speech const message = new Message( 'Our corporate headquarters is at WeWork, Toronto, Canada' ) message.addResponse(card) return message } Carousel A carousel is a collection of cards: async payload => { // Create a card const card1 = new Card({ title : "Corporate headquarters" , subtitle : "1 Infinite Loop, Cupertino, California" , media : new Media({ url : 'http://...' , type : 'image' }) }) .addButton( new Button({ type : 'url' , label : 'Visit website' , value : 'http://awesomecorp.com' })) // Create another card const card2 = new Card({ title : "Local office" , subtitle : "1 Infinite Loop, Cupertino, California" }) .addButton( new Button({ type : 'url' , label : 'Visit website' , value : 'http://awesomecorp.com' })) const carousel = new Carousel() .addCard(card1) .addCard(card2) return new Message( 'Our corperate headquarters is at 1 Infinite Loop, Cupertino, California, our local...' ) .addResponse(carousel) } File async payload => { const file = new File({ title : "Cool car brochure" , url : "https://flow.ai/video/brochure.pdf" }) return new Message( 'Brochure of a cool car' ) .addResponse(file) } Image async payload => { const image = new Image({ title : "Image description" , url : "https://..." }) return new Message( 'Images are not supported on your device!' ) .addResponse(image) } Flow configures the message depending on the platform your customer is interacting on. The example above will show an image on the web, app, and Facebook Messenger but will speak the message on voice devices like Amazon Echo or Google Home. new Message( 'Images are not supported on your device!' ) Location async payload => { const loc = new Location({ title : '1 Infinite Loop in Cupertino' , lat : '37.332211' , long : '-122.030778' , action : new Action({ type : 'url' , value : 'https://www.awesome.corp' }) }) return new Message( '1 Infinite Loop in Cupertino' ) .addResponse(loc) } Video async payload => { const video = new Video({ title : "Cool car" , url : "https://flow.ai/video/vw.mp4" }) return new Message( 'Watch an awesome video of a cool car' ) .addResponse(video) }
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
386
Params are variables the bot has extracted that can be used in actions. These can be values detected by the NLP engine, metadata about users etcetera. Note: Params lifetime is 24h. Using params The NLP engine can for example   detect entities   within text and the values of those can be used within actions. If a user says:   I want to book a hotel in Amsterdam   and the NLP engine detects Amsterdam as a   destinationCity, you can use   destinationCity   in your action to call for example an API with this value. Note: Params are always lists (arrays). The NLP engine can detect multiple similar entities, for example:   I want to book a hotel in   Amsterdam   and   Copenhagen. if ( Array .isArray(payload.params.destinationCity)) { payload.params.destinationCity.forEach( city => { // Do something with the city // city.value (keyword of the entity) // city.match (matched word, could have misspellings etc) }) } Location When a user shares a location, the action will receive a collection of locations: if ( Array .isArray(payload.params.location)) { payload.params.location.forEach( location => { // Do something with the location const { lat, long } = location.value // .. }) } Multimedia Files When a user shares an image, video, audio or file the action will receive a collection of media elements: // User shares an image if ( Array .isArray(payload.params.image)) { payload.params.image.forEach( image => { // Do something with the image const url = image.value // .. }) } Sending params It’s also possible to explicitly define params, for example when a user presses a button that triggers an event specific to a product. In order to fetch the details, you might need to use a productId identifying it. For those use cases we provide a way to attach a   Param   to UI elements;   Button,   QuickReply   and   Action. Below you can view an example how to create and attach a param to a UI element. // Render a Button that triggers an event with a Param const param = new Param( 'itemId' , '332223323' ) // Attach the param to the button const button = new Button({ label : 'More info' , type : 'event' , value : 'MORE_INFO' , param }) It's also possible to attach multiple params: // Render a QuickReply that triggers an event with Params const shopId = new Param( 'shopId' , '33211233' ) const productId = new Param( 'productId' , '123443211' ) // Attach both params to the QuickReply const quickReply = new QuickReply({ label : 'Product details' , type : 'event' , value : 'PRODUCT_DETAILS' , param : [shopId, productId] }) Or even add the same param with multiple values: // Render a QuickReply that triggers an event with Params const categoryId1 = new Param( 'categoryId' , '123' ) const categoryId2 = new Param( 'categoryId' , '456' ) // Attach both params to the QuickReply const quickReply = new QuickReply({ label : 'Search more' , type : 'event' , value : 'PRODUCT_CATEGORY_SEARCH' , param : [categoryId1, categoryId2] }) The following is a complete working example of sending a buttons widget with params: async payload => { // Send a message with a buttons template const buttons = new Buttons( "Vintage bikes and more Ltd." ) // Add a button .addButton( new Button({ label : "View location" , type : "event" , value : "COMPANY_INFO" , param : new Param( 'companyId' , '122' ) })) // Add another button .addButton( new Button({ label : "Special offers" , type : "postback" , value : "Show me special offers" , param : new Param( 'companyId' , '122' ) })) return new Message( 'Vintage bikes and more Ltd' ) .addResponse(buttons) } Changing params With code actions you receive params but you can also manipulate them. This is simply done by returning a params object. Modifying a param You can modify an existing param by changing the value inside the returned object as the example below illustrates. async payload => { return { params : { // Using a spread operator, we add all provided params in the result ...payload.params, // Now we override the destination_city param destination_city : [{ value : `ams` , match : 'Amsterdam' }] } } } Warning Make sure to always return other params you'd like to return like in the above example. Clear a single param There are 3 ways of clearing params within context. Either by using a   reset   within the design tool, or by resetting params using a webhook or code action. The following example removes a single param: async payload => { return { params : { ...payload.params, // Only remove the arrival_city param arrival_city : null } } } Clear all params It's also possible to clear all params from context using a code action. Simply return a   null   as the value for   params . async payload => { return { params : null } }
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
451
Params are variables that are set within a conversation. But, whenever a session is reset or expires, these variables are lost.   Using a simple storage mechanism you can manage stateful data. Data is stored on a thread level and can be accessed even weeks after the first conversation took place. Code example async payload => { // Get the current count, or 0 let count = await state.get( 'count' ) || 0 // Save the current count await state.save( 'count' , count + 1 ) // Show or speak the current count return new Message( `Count is ${count} ` ) } Save a value Storing data can be done using the   state.save()   method. Provide a key and value to save: async payload => { await state.save( 'watched' , { season : 1 , episode : 2 , serie : 'game-of-thrones' }) } Get a value Fetch a value by key using the   get()   method: async payload => { // Could be null if not found const watched = await state.get( 'watched' ) if (watched) { // .... } } Note: If no data exists   get()   will return   null Removing values Remove a specific value by key: async payload => { // Remove aa specific key await state.remove( 'watched' ) } Clear all values stored for this thread: async payload => { // Remove all data for this conversation await state.clear() } Reference state.save(key, value) Save data in state Returns:   Promise   - Promise that resolves with the value being stored Properties Name  Type  Description key string Key used to save data value object  Either an object, array or string to store state.get(key) Retrieve data from state by key Returns:   Promise   - Promise that resolved with the value being stored or   null   if the key does not exist Properties Name  Type Description Key string  Key used to find the data state.remove(key) Remove data from state by key Returns:   Promise   - Resolves with the key of the deleted data Properties Name Type Description Key string  Key of the data to delete state.clear() Clear all data from state Returns:   undefined
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
229
With code actions you can use   console.log   and   console.error   to log messages just like you would with node.js. // User shares an image console .log( 'View params' , payload.params) // Something bad console .error( 'This is not good' , err) Any errors will show up in the notification bar as well as within the log view of the code editor.
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
219
Webhooks   are a way to receive information on your custom service through simple HTTP posts. Webhooks are based on a   We'll call you   principle. Each time a   webhook action   is triggered, Flow.ai makes a call to your service with a HTTP POST request. Getting started Start by creating a new Webhook action inside the   Code app. Callback url The URL that points to your Webhook. We've created an easy to start   example project   you can use as a boilerplate or example. Verify token This is a secret we send along with each call for verification of the Flow.ai service.   Read more on Webhook actions: Receive Calls  Send Replies  
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
347
Just like   Cloud code , Webhook actions are triggered using actions. Simply drag and drop them below any trigger and select the action. POST Request Whenever a webhook is triggered Flow.ai sends along data in JSON format to your callback url . { "type" : "action" , "verifyToken" : "b34768df-4768-4768-8cfe-0ac99db46ca9" , "threadId" : "99eb45ed85a0a00cef41f55aa03bea17" , "channelName" : "socket" , "query" : "hi" , "action" : "onboarding" , "params" : { }, "originator" : { "actorId" : "23249a99-a243-448b-asdf-daddd7bafb6c" , "userId" : "flowai|23249a99-1233-448b-ada1-daasafbafb6c" , "name" : "EN Bot" , "role" : "bot" , "profile" : { "description" : "Flow.ai" , "locale" : "en" , "picture" : "https://flow.ai/img/brains/flowai.svg" } }, "user" : { "name" : "Jane Doe" , "role" : "external" , "profile" : { "fullName" : "Jane Doe" , "firstName" : "Jane" , "lastName" : "Doe" , "email" : "jane@doe.ai" , "picture" : "https://..." , "locale" : "nl" , "timezone" : 2 , "gender" : "M" } }, "replyUrl" : "https://..." } Reference Property Description type By default this is:   action verifyToken The verify token you specified in the webhook configuration threadId The ID representing the thread that triggered the webhook call channelName Name of the channel on which the Webhook call was triggered query Optionally a user query that triggered this Webhook call action Each action triggering a Webhook call can customise this. See the Design app params Optional object with params retrieved by Flow.ai originator The sender of the action user The user that triggered the Webhook call replyUrl Unique url to be used to reply to this thread on the correct channel Action: You can control the value of   action , like in the example above (onboarding), from within the designer. This makes it easy to use a single endpoint with different actions. Params As with Cloud code you can expect a set of various params. For example a user shares a file or the   bot detects a named entity. { "type": "action", "verifyToken": "...", "threadId": "...", "channelName": "alexa", "query": "What is the weather like in Toronto?", "action": "get-weather-report", "params": { "city": [ { "match": "Toronto", "type": "system.query", "value": "Toronto" } ] }, ... } In the above example you can see that the engine extracted data and placed it into a params object. Each param is always a list (array) allowing multiple results. { "type": "action", "verifyToken": "...", "threadId": "...", "channelName": "amazon", "query": "What is the weather like in New York and Toronto?", "action": "get-weather-report", "params": { "city": [ { "match": "New York", "type": "system.query", "value": "New York" }, { "match": "Toronto", "type": "system.query", "value": "Toronto" } ] }, ... } Reference Property Description value The extracted value match Optionally, the piece of text that matched type Optionally, the type of data that was extracted Further reading Node.js webhook example project
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (2)
0
264
Whenever you receive a webhook call, Flow expects a   200   response code from your server. With each reply you can send back messages and information. Example { "verifyToken" : "59a755e5-2581-4307-393f-630ad4983adf" , "messages" : [{ "fallback" : "Hi there" , "responses" : [{ "type" : "text" , "payload" : { "text" : "Hi there" }, "delay" : 0 }] }] } When your webhook runs on Node.js it's best to use   flow-js-templates   to send back reply messages. Any other technology stack is possible as long as you   send back JSON formatted data. Send later Flow expects a Webhook call to return a reply within seconds. This can cause problems whenever you need to do a long running process. Certain business processes may however take considerably longer. For those cases Flow provides a mechanism that allows you to reply with messages at a later point in time. To do this there is a reply URL being provided with each webhook call. Use this URL to make a HTTP POST request. The JSON payload you send is the same as when replying directly. Do not forget to include the   verifyToken   with each request. // Node.js example using request const opts = { method : 'POST' , uri : replyUrl, body : { verifyToken, messages }, json : true } request(opts) Trigger events Like sending messages you can also   trigger events   using Webhooks. It works the same as with sending messages except you specify which event to trigger // Node.js example using request const opts = { method : 'POST' , uri : replyUrl, body : { verifyToken, events : [{ name : 'MY_EVENT_NAME' }] }, json : true } request(opts) Sending params With each reply (or immediate response) you can also manipulate data that is used by the NLP engine. This is done by sending along params with a reply message. The following example sends a reply that contains the params   destination_city   and   departure_city . const replyBody = { verifyToken, params : { destination_city : [{ value : 'AMS' }], departure_city : [{ value : 'NYC' }] }, events : [{ name : 'WELCOME' }] } const opts = { method : 'POST' , uri : replyUrl, body : replyBody, json : true } request(opts) Further reading Node.js response templates JSON response templates
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
302
We support a built-in   Zapier integration . Zapier is great for connecting different services without having to code. For example, you can save inputs your chatbot receives to Google Sheets. Using the Zapier action you can trigger a zap contextually. It's great for different   use cases   and will save you time writing custom integrations. Adding a Zapier action Note: Before you can connect a Zap you'll need to   create it first. Zapier actions work like webhook and code actions. You can simply drag and drop the   reply action   within your flows. It's possible to create multiple zaps and connect those to different Flows.   Whenever a Zap is triggered Flow sends essentially the same data as is sent when a webhook is triggered. Params To send specific params, make sure you specify those during the creation process of the Zap.     Read more More about the Zapier integration
View full article
by Khoros Staff Khoros Staff Aug 18, 2021
Labels (1)
0
258
Allow customers to make payments inside a conversation using our payments webview. How it works Payments are created using a code action and are initiated just like a common   toolbelt   function. Using the code action you can, for example, add a product created in   Stripe. Whenever a user triggers the code action a webview or link is shown. Opening the payments webview will redirect the user to a Stripe payment page. Prerequisites Stripe account You need to have an existing   Stripe   account. API Keys You need to retrieve   API Keys   from the Stripe   dashboard. Using with Messenger Make sure that is added to the list of whitelisted domains of your   Messenger   integration. Using with Web widget Make sure that is added to the list of whitelisted domains of your   Web widget   integration. Other payment platforms We have a closed beta of Braintree and SumUp providers, if you are interested   contact us. Read more on Payment actions: Stripe Single Purchase  Stripe prepared Product Purchase Examples of Stripe Purchases
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
234
This code action function allows you to create a new raw product that can be purchased inside your   flow   or you can use   price   of the existing   product . This function also allows you to use key-value based   metadata   object that will be sent to your webhook alongside with payment details. Usage example async payload => { const url = await payments.singlePurchase.stripe({ secret : 'your_stripe_secret' , key : 'your_stripe_publishable_key' , collectAddress : true , locale : 'nl' , submitType : 'auto' , currency : 'usd' , metadata : { MY_KEY : 'MY_VALUE' }, items : [ // raw products { price : 1200 , quantity : 1 , images : [ 'https://www.howtogeek.com/wp-content/uploads/2018/09/vac_lede.png' ], name : 'Audio' , description : 'Awesome mic' }, { price : 1000 , quantity : 2 , images : [ 'https://www.howtogeek.com/wp-content/uploads/2018/09/vac_lede.png' ], name : 'Video' , description : 'Awesome cameras' }, // existing product's price // PLEASE NOTE YOU CAN'T MIX RAW PRODUCTS WITH EXISTING PRICES { price : 'price_2XX7x0XXXyxxx6x9x7XxXXXx' , quantity : 3 } ], onSuccess : { eventName : 'bought' , params : [ new Param( 'name' , 'electronics' ), new Param( 'price' , '21$' ) ] }, onFailure : { eventName : 'not bought' , params : [ new Param( 'name' , 'electronics' ) ] } }) const buttons = new Buttons( 'Purchase my items' ) buttons.addButton( new Button({ label : 'Click to purchase' , type : 'payment' , value : url })) const message = new Message( `Purchase items here ${url} ` ) message.addResponse(buttons) return message } Properties Property Type Example Description Required secret string sk_test_XXXXXXXXXXX Your Stripe Secret Key Yes key string pk_test_XXXXXXXXXXX Your Stripe Publishable Key Yes collectAddress boolean true Whether Checkout should collect customer's   address   locale string nl By default, Checkout detects the locale of the customer’s browser and displays a translated version of the page in their language, if it is   supported. You can also provide a specific locale for Checkout to use instead   submitType string donate Submit type   of payment session   currency string eur Currency that should be used in checkout Yes metadata object { MY_KEY: 'MY_VALUE' } Object that will be sent with payment details to your webhook button.label string Click to purchase Label of the confirmation button   Success and Failure params You can include   onSuccess   and   onFailure   configuration which will be used in corresponding situations. Property Type Example Description Required eventName string bought Event name to trigger when items are successfully bought / purchase is rejected   params array new Param('productiId', 112234) Parameters that are set when the items are bought / purchase is rejected   Items The multiple select is based on a number of items. Each individual item should contain   price ,   quantity   and   name   properties and can contain   images   and   description   properties. Properties Property Type Example Description Required price number   or   string 1000   or   price_2XX7x0XXXyxxx6x9x7XxXXXx If you're creating new raw product you need to use numeric price (last two digits correspond to .00) Yes quantity number 1 Amount of items to be purchased Yes images Array of strings ["https://.../thumbnail.png"] URLs of images to display alongside corresponding product (if using with raw product)   name string Microphone Name of your product Yes (if using with raw product) description string Awesome mic Description of your product (if using with raw product)  
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
388
This function allows you to use an existing   Stripe product's   SKUs   that could be purchased inside your   flow . Notes This method does not support   metadata . Prerequisites Enabling Checkout You need to enable the   Checkout client-only integration   within the Stripe   Checkout settings.   One-time purchase products Flow.ai supports only   One-time purchase products . Double check you have chosen the proper option when creating a   new Stripe product.   Usage example async payload => { const url = await payments.preparedPurchase.stripe({ key : 'your_stripe_publishable_key' , locale : 'nl' , collectAddress : true , submitType : 'donate' , items : [ { sku : 'sku_of_your_product' , quantity : 1 }, { sku : 'sku_of_your_another_product' , quantity : 3 } ], onSuccess : { eventName : 'bought' , params : [ new Param( 'category' , 'clothes' ) ] }, onFailure : { eventName : 'not bought' , params : [ new Param( 'category' , 'clothes' ) ] } }) const buttons = new Buttons( 'Purchase my items' ) buttons.addButton( new Button({ label : 'Click to purchase' , type : 'payment' , value : url })) const message = new Message( `Purchase items here ${url} ` ) message.addResponse(buttons) return message } Properties Property Type Example Description Required key string pk_test_XXXXXXXXXXX Your Stripe Publishable Key Yes collectAddress boolean true Whether Checkout should collect customer's   address   locale string nl By default, Checkout detects the locale of the customer’s browser and displays a translated version of the page in their language, if it is   supported. You can also provide a specific locale for Checkout to use instead   submitType string donate Submit type   of payment session   button.label string Click to purchase Label of the confirmation button   Success and Failure params You can include   onSuccess   and   onFailure   configuration which will be used in corresponding situations. Property Type Example Description Required eventName string bought Event name to trigger when items are successfully bought / purchase is rejected   params array new Param('productiId', 112234) Parameters that are set when the items are bought / purchase is rejected   Items The multiple select is based on a number of items. Each individual item should contain   sku   and   quantity   properties. Properties Property Type Example Description Required sku string sku_XXXXXXXXXXX SKU   of your product Yes quantity number 1 Amount of items to be purchased Yes  
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (2)
0
187
Default checkout screen without non-required params   Checkout screen with custom submit type and address collection enabled   Checkout screen with Dutch locale enabled  
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
177
Webviews allow you to offer experiences and features that require a more complex user interface that might be difficult to create in-conversation, such as picking seats to book, or browsing available dates.   Built-in Templates Normally you are required to set up a separate service to host a Webview. To make it easier to take advantage of Webviews, Flow.ai provides pre-built webview templates straight from code actions. Using cloud actions you can configure, customize and add dynamic data to any webview. Getting started A webview is created using the   webviews   library inside a code action. async payload => { // Create a new Article webview const url = await webview.article.create({ ref : 'news-item' , title : 'Hello world' , content : `Lorem ipsum dolor sit amet, consectetur adipiscing elit.` }) // After generating a webview you receive a URL // that can be used with any button or within a simple text message const buttons = new Buttons( 'Hello world article' ) buttons.addButton( new Button({ label : 'Read article' , type : 'webview' , value : url })) const message = new Message( `Read my article at ${url} ` ) message.addResponse(buttons) return message } Customize Templates allow customization using a   tint   property.   const url = await webview.radioSelect.create({ ... tint: '#50E3C2' , ... }) Templates The following overview displays all the available templates.   Template Description   webview.article Display a long-read article. Read Reference   webview.datePicker Helps to select a date. Read Reference       webview.radioSelect Display a list with items a user can select from. If the list becomes long you can optionally provide a search bar. Read Reference   webview.multipleSelect Like the radio select, but allows multiple items to be selected. Read Reference   webview.terms Display an article or webpage with a confirmation button. Read Reference Supported Channels Webview are only fully supported with   Facebook Messenger   and   Web widget. Other messaging and voice channels, that do not allow the rendering of HTML, are not supported. The appearance of a webviews depends on the messaging app and device it is displayed on:   iOS ,   Android   or   Desktop . Languages Most of the text inside the webview templates can be customized. The default labels and text are available in the following languages: English Dutch German French Spanish Portuguese Russian Turkish Swedish Greek Polish Norwegian Japanese Italian Danish Ukrainian Context Webviews are always created within the context of a thread ID and are static by nature. In other words, they are unique for a user and created once. Whenever you would call   create()   again, it would create a new webview unless you provide a   ref   property during creation. Troubleshooting The window will not open or close in Messenger Please make sure the  allowed-listed  domains   within your Messenger configuration contains   https://app.flow.ai . You can find the  allowed-listed domains within the bottom of the   Customize   tab of the Messenger integration screen. It does not work in WhatsApp or Telegram At this time we only support Facebook Messenger and the web widget. Read more on Webview actions: Article Date Picker Radio Select Multiple Select Terms
View full article
by Khoros Staff Khoros Staff Jun 17, 2021
Labels (1)
0
337