NAV Navbar
http Node.js

Introduction

The Flow.ai API is organized around REST. Our API has predictable, resource-oriented URLs, and uses HTTP response codes to indicate API errors. We use built-in HTTP features, like HTTP authentication and HTTP verbs, which are understood by off-the-shelf HTTP clients.

Our messaging API supports cross-origin resource sharing, allowing you to interact securely with our API from a client-side web application (though you should never expose your secret API key in any public client-side code). JSON is returned by all API responses, including errors.

Socket API

A real time messaging API that allows you to send and receive messages from Flow.ai using web sockets.

Audience

The Socket API is specifically intended for developers looking to integrate Flow.ai in a client facing app. For example:

For server integrations we advice you to take a look at our Messaging API.

Getting started

An overview how the API works:

  1. Request (GET) a WebSocket endpoint
  2. Open a WebSocket connection (WSS)
  3. Send and receive messages
  4. Keep the connection alive

Request an endpoint

Example Request:

curl -X GET -H "Content-Type: application/json" "https://api.flow.ai/socket.info?clientId=YOUR_CLIENT_ID&sessionId=123432"
var request = require("request");

var options = { method: 'GET', url: 'https://api.flow.ai/socket.info/?clientId=YOUR_CLIENT_ID&sessionId=1234' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
var client = new RestClient("https://api.flow.ai/socket.info?clientId=YOUR_CLIENT_ID&sessionId=1234");
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
var request = NSMutableURLRequest(URL: NSURL(string: "https://api.flow.ai/socket.info/?clientId=YOUR_CLIENT_ID&sessionId=1234")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)

Example response:

200 OK
{
  "status": "ok",
  "payload": {
    "endpoint": "wss://api.flow.ai/ws/8c3b7d7ea9400..."
  }
}

To start a connection you'll need to make a GET call to the socket.info API method to the API endpoint at https://api.flow.ai. This provides a temporary WebSocket URL.

The socket.info method requires a sessionId and a clientId.

Query param Description
sessionId The sessionId is something unique you need to create for every call. This can be something like a UIUID. Each connection is partly identified on our end using this key
clientId Check the Channels app of the dashboard to find your unique clientId.

Open a connection

The socket URL provided by socket.info are single-use and are only valid for 60 seconds, so make sure to connect directly.

Common format

{
  "type": "...",
  "payload": {
    ...
  }
}

Any message or other kind of event you send or receive has the same JSON format.

Attributes

Property Description
type required The message type for example: message.send
payload required The body of the message

Keep alive

Example Message:

{
  "type": "ping"
}

Example Reply:

{
  "type": "pong"
}

When a connection is made we will automatically disconnect if we do not receive any messages within 50 seconds.

In order to keep the connection live we support a ping message.

Sending Messages

Example Message:

{
  "type": "message.send",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "traceId": 1519091841664,
    "speech": "Hi there!"
  }
}

The easiest way to send a simple text message in real time

Attributes

Property Description
threadId required Unique key identifying a user or channel
traceId optional Optional number used to track message delivery
speech required Text of message

Originator object

Example Message:

{
  "type": "message.send",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "traceId": 1519091841666,
    "speech": "Turn off the lights in the Living room",
    "originator": {
      "name": "John Doe",
      "role": "external"
    },
  }
}

Example Message:

{
  "type": "message.send",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "traceId": 1519091841667,
    "speech": "has my milk expired?",
    "originator": {
      "name": "John Doe",
      "role": "external",
      "profile": {
        "fullName": "John Doe",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "M",
        "locale": "en-US",
        "timezone": -5,
        "country": "us",
        "email": "[email protected]",
        "picture": "https://..."
      }
    }
  }
}

Example Message:

{
  "type": "message.send",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "speech": "I want to book a flight between Amsterdam and Toronto",
    "originator": {
      "name": "John Doe",
      "role": "external",
      "metadata": {
        "clientNumber": "asddaasq333ee332",
        "preference": "A,B,G"
      }
    }
  }
}

With each message you can customize information regarding the sender, user or as Flow.ai calls it, the originator of the message.

Attributes

Property Description
name string Name representing the originator
role string Either external, or moderator
profile Profile object Optional Profile object
metadata object Key value pairs with additional info

Profile object

An originator can contain additional profile information using the profile object

Property Description
fullName string Complete name
firstName string First name
lastName string Family name
gender string Gender, M, F or U
locale string Locale code (ISO)
timezone number Number of hours of UTC
country string Two letter country code
email string Email address
picture string URL to profile picture

Metadata

Example Message:

{
  "type": "message.send",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "speech": "I want to book a flight between Amsterdam and Toronto",
    "originator": {
      "name": "John Doe",
      "role": "external"
    },
    "metadata": {
      "language": "en-US",
      "timezone": -6,
      "params": {
        "seats": [{
          "value": "Business class"
        }]
      }
    }
  }
}

Along with every message you can send additional metadata. Some of this metadata is also used by the AI engine to determine the response.

Attributes
Property Description
language string Language code (ISO) of the message, not the user
timezone number Timezone of the message (where it was sent). Number of hours from UTC
params Params object Bag of parameters to use within the AI

Params object

Example Params

{
  "passengerCount": [{
    "value": "2"
  }]
}
{
  "food": [{
    "value": "food-item-22332",
    "match": "Pizza Hawaii"
  }, {
    "value": "food-item-44525",
    "match": "Pizza Calzone"
  }]
}

The params object resembles the matched result created by the AI engine using entity classification. Each param itself is a list of [{ value }] objects.

Property Description
value required The value of the param
match optional Represents a human value

Attachment

Example Message:

{
  "type": "message.send",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "traceId": 1519091841665,
    "speech": "event attachment",
    "attachment": {
      "type": "event",
      "payload": {
        "name": "INTRO"
      }
    }
  }
}

Instead of simple text messages, Flow.ai also supports sending attachments like files or events.

Attachment attributes
Property Description
type required Attachment type. Currently this has to be event
payload required Attachment object
Attachment object
Property Description Type
name required Name of the event to trigger

Responses

Example Reply:

{
  "type": "message.delivered",
  "payload": {
    "traceId": 1,
    "threadId": "31ea9df73ca74dfe9329bf68c09b61ce",
    "traceId": 1489399519321,
    "speech": "hi"
  }
}

If there is an error processing a message the server will reply with an error. For example:

{
  "type": "error",
  "message": "Invalid message format ..."
}

A reply is sent (almost) instantly. The following is replied if the message is successfully delivered.

Receiving Messages

Messages that are replied are in almost the same format as the ones that are sent.

Example or reply

{
  "type": "message.received",
  "payload": {
    "threadId": "57a8a2a8917250d54bcbb596",
    "messages": [
      {
        "fallback": "hallo",
        "responses": [
          {
            "type": "text",
            "payload": {
              "text": "hallo"
            }
          }
        ]
      }
    ],
    "originator": {
      "userId": "7250d54bcbb59657a8a2a891",
      "name": "Gijs van de Nieuwegiessen",
      "role": "user",
      "profile": {
        "fullName": "Gijs van de Nieuwegiessen",
        "firstName": "Gijs",
        "lastName": "van de Nieuwegiessen",
        "locale": "nl",
        "gender": "M",
        "picture": "https://flowai.s3.eu-central-1.amazonaws.com/identities/profile/5959ca45-318a-4d58-b5e1-b430934b8e23"
      }
    }
  }
}

Example of advanced reply

{
  "type": "message.received",
  "payload": {
    "threadId": "58ca9e327348ed3bd1439e7b",
    "messages": [
      {
        "fallback": "Hi, how can we help?",
        "silent": false,
        "replyTo": "event attachment",
        "originator": {
          "userId": "flowai|system",
          "name": "system",
          "role": "bot",
          "profile": {
            "picture": "https://flow.ai/img/brains/flowai.svg"
          }
        },
        "actions": [],
        "responses": [
          {
            "type": "text",
            "payload": {
              "text": "Hi, how can we help?",
              "quickReplies": [
                {
                  "label": "Chat with flow.ai",
                  "value": "Chat with someone from flow.ai",
                  "type": "text"
                },
                {
                  "label": "Call flow.ai",
                  "value": "What is your phone number?",
                  "type": "text"
                },
                {
                  "label": "Ask a question",
                  "value": "I want to ask a question",
                  "type": "text"
                }
              ]
            },
            "delay": 0
          }
        ],
        "flow": {
          "flowId": "2afcb930-9335-4e74-abb3-5745d26707f7",
          "title": "Intro"
        },
        "step": {
          "stepId": "d3d46698-e526-4252-b70c-e6e5af3338e0",
          "title": "INTRO",
          "type": "EVENT"
        },
        "params": {
          "event": [
            {
              "type": "custom",
              "value": {
                "name": "INTRO"
              }
            }
          ]
        }
      }
    ],
    "originator": {
      "userId": "flowai|system",
      "name": "system",
      "role": "bot",
      "profile": {
        "picture": "https://flow.ai/img/brains/flowai.svg"
      }
    }
  }
}
Payload fields
Property Description Type
threadId Required. Unique key identifying a user or channel string
messages List of Message templates array
originator Similar to the originator when sending messages object
Message fields
Property Description Type
fallback Speech representation of the message string
silent True if message does not have any output for a user bool
replyTo Optionally contains the text the message is a direct reply to string
originator Originator specific to this message object
actions Optional action names being called array
responses Collection of Response templates array
flow Information about the flow being matched object
step Information about the step being matched object
params Hash table with Parameters object
Response fields

We have a complete reference of the JSON responses available

Example

We provide a JavaScript SDK, but the following example demonstrates opening a connection and sending a test message using vanilla JavaScript in the browser.

<html>
  <body>
    <script>

    (function () {
      // Vanilla JS example
      // When executing this script. Check your development console for any messages

      // This identifies the channel we want to connect with
      var clientId = 'YOUR CLIENTID'

      // Global references to our WebSocket and interval
      var ws
      var keepalive

      // This methos is where we send test messages
      function runTestMessages() {

        console.info('runTestMessages')
        var message = {
          "type": "message.send",
          "payload": {
            "threadId": "jane.doe",
            "speech": "event attachment",
            "attachment": {
              "type": "event",
              "payload": {
                "name": "MY EVENT"
              }
            },
            "originator": {
              "name": "Jane Doe",
              "role": "external",
              "profile": {
                "fullName": "Jane Doe",
                "firstName": "Jane",
                "lastName": "Doe",
                "gender": "F",
                "locale": "en-US",
                "timezone": -5,
                "country": "us",
                "email": "[email protected]",
                "picture": "https://en.wikipedia.org/wiki/File:YellowLabradorLooking_new.jpg"
              },
              "metadata": {
                "clientNumber": "12345",
                "preference": "A,B,G"
              }
            }
          }
        }

        wsSendMessage(message)
      }

      // Get a new wss endpoint
      function getWsEndpoint() {
        console.info('Request endpoint')
        // socket.info endpoint
        var socketInfoUrl = 'https://api.flow.ai/socket.info?clientId=' + clientId + '&sessionId=' + Date.now();

        // Create a GET request
        var req = new XMLHttpRequest();
        req.onload = wsEndpointResponse
        req.responseType = 'json';
        req.open('GET', socketInfoUrl, true);
        req.send();
      }

      // Called when we get a response from socket.info
      // validate the response and open a websocket connection
      function wsEndpointResponse(e) {
        console.info('Received endpoint')

        var xhr = e.target;

        if(xhr.response.status !== 'ok') {
          // This is not OK..
          console.error('Error while fetching wss url', xhr.response)
          return
        }

        // Get the endpoint from the response
        var endpoint = xhr.response.payload.endpoint

        startWebsocket(endpoint)
      }

      // Open a new websocket connection
      function startWebsocket(endpoint) {
        console.info('Websocket start connection with endpoint', endpoint)
        // Create a new socket
        ws = new WebSocket(endpoint);
        ws.onopen = wsOnOpen;
        ws.onmessage = wsOnMessage;
      }

      // Handler called when the socket makes a connection
      function wsOnOpen(e) {
        console.info('Websocket connection open')

        // Start the keepalive
        wsStartKeepalive()

        // Run our test messages
        runTestMessages()
      }

      // Handler called when the socket receives a message
      function wsOnMessage(e) {
        var json = JSON.parse(e.data)
        console.info('Websocket received json', json)
      }

      // Simple keep alive method (sending pings)
      function wsStartKeepalive() {
        clearInterval(keepalive)

        // Send a ping 30 seconds
        keepalive = setInterval(function() {
          wsSendMessage({
            "type": "ping"
          })
        }, 30 * 1000)
      }

      // Helper method for sending messages
      function wsSendMessage(message) {
        ws.send(JSON.stringify(message))
      }

      // Start with sending a GET request for a WSS endpoint
      getWsEndpoint()
    }());
    </script>
  </body>
</html>

REST API

An API to built conversational interfaces (e.g., chatbots, voice-powered apps and devices). Warning. It's a Beta version of our API

Audience

The API is specifically made for developers that want to use the Flow.ai engine within their own technology stack or solution.

Some example use cases:

You call us, we'll call you

The REST API works asynchronous. Unlike other NLP APIs, Flow.ai will not return any direct reply to a Send call.

Send messages using REST API

Instead, the API will send a POST request to your configured webhook whenever a reply is being sent.

For some queries we added an optional sync support. To enable sync mode add sync=true flag to supported query.

Receive replies using Webhooks

Sending messages

Many types of unstructured content can be sent to the Flow.ai platform, including text, audio, images, video, and files. Our powerful AI engine will process any query and send back replies using the provided webhook.

Any message that is sent requires a threadId that relates the message to a specific user, chat or thread. Optionally you can provide a traceId that will help keep track of the message when you receive delivery events.

Endpoint

All the URLs referenced in the REST API have the following base:

https://api.flow.ai/rest/v1/

Authentication

Authenticate your API requests by providing an API key as a value of Authorization header. All API requests expect this header to be present.

You can get a new API key within the Organisation settings section by selecting API Keys tab and pressing Create a new API Token button. After that you need to select this API key in Outbound section of your REST API integration in integrations section and press Save button.

Originator

Example Message:

{
    "payload": {
        "type": "text",
        "speech": "hello",
        "originator": {
            "name": "John Doe",
            "role": "external"
        }
    }
}

Example Message:

{
    "payload": {
        "type": "text",
        "speech": "hello",
        "originator": {
            "name": "John Doe",
            "role": "external",
            "profile": {
                "fullName": "John Doe",
                "firstName": "John",
                "lastName": "Doe",
                "gender": "M",
                "locale": "en-US",
                "timezone": -5,
                "country": "us",
                "email": "[email protected]",
                "picture": "https://..."
            }   
        }
    }
}

Example Message:

{
    ...
    "originator": {
        "name": "John Doe",
        "role": "external",
        "metadata": {
            "clientNumber": "asddaasq333ee332",
            "preference": "A,B,G"
        }
    }
    ...
}

With each message you need to provide some information regarding the sender, user or as Flow.ai calls it, the originator of the message.

Attributes

Property Description
name string Name representing the originator
role string Either external, or moderator
profile Profile object Optional Profile object
metadata object Key value pairs with additional info

Profile object

An originator can contain additional profile information using the profile object

Property Description
fullName string Complete name
firstName string First name
lastName string Family name
gender string Gender, M, F or U
locale string Locale code (ISO)
timezone number Number of hours of UTC
country string Two letter country code
email string Email address
picture string URL to profile picture

Text message

Sending a text message

POST rest/v1/messages/:threadId

Example Request:

POST rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
{
    "payload": {
        "type": "text",
        "speech": "Hello",
        "originator": {
            "name": "John Doe",
            "role": "external"
        }
    }
}
import request from "async-request";

const result = await request({
  method: 'POST',
  url: 'https://api.flow.ai/rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {
        payload: {
            type: 'text',
            speech: 'Hello',
            originator: {
                name: "John Doe",
                role: "external"
        }
        }
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Parameters

threadId string Unique identifier of the thread

Arguments

traceId number Optional unique number that is passed along to identify the message. Use this to verify message delivery.
type string Indicates the type of message. Should be text
text string The text or speech message to process. The maximum length of a message is 255 characters.
lang string Optional language code in ISO format (2 letters)
timezone integer Optional UTF timezone offset in hours
params object Optional parameters

Event message

POST rest/v1/messages/:threadId

Example Request:

POST rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
{
    "payload": {
        "type": "event",
        "eventName": "MY_EVENT",
        "originator": {
            "name": "John Doe",
            "role": "external"
        }
    }
}
import request from "async-request";

const result = await request({
  method: 'POST',
  url: 'https://api.flow.ai/rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {
        payload: {
            type: 'event',
            eventName: "MY_EVENT",
            originator: {
                name: "John Doe",
                role: "external"
        }
        }
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Trigger events within Flow.ai by sending an event message.

Parameters

threadId string Unique identifier of the thread

Arguments

traceId number Optional unique number that is passed along to identify the message. Use this to verify message delivery.
type string Indicates the type of message. Should be event
eventName string The name of the event to trigger
lang string Optional language code in ISO format (2 letters)
timezone integer Optional UTF timezone offset in hours
params object Optional parameters

Location message

POST rest/v1/messages/:threadId

Example Request:

POST rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
{
    "payload": {
        "type": "location",
        "lat": "1232122422",
        "long": "2433343343",
        "originator": {
            "name": "John Doe",
            "role": "external"
        }
    }
}
import request from "async-request";

const result = await request({
  method: 'POST',
  url: 'https://api.flow.ai/rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {
        payload: {
            type: 'location',
            lat: "1232122422",
            long: "2433343343",
            originator: {
                name: "John Doe",
                role: "external"
        }
        }
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Send coordinates

Parameters

threadId string Unique identifier of the thread

Arguments

traceId number Optional unique number that is passed along to identify the message. Use this to verify message delivery.
type string Indicates the type of message. Should be location
lat string Latitude
long string Longitude
lang string Optional language code in ISO format (2 letters)
timezone integer Optional UTF timezone offset in hours
params object Optional parameters

Media message

POST rest/v1/messages/:threadId

Example Request:

POST rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
{
    "payload": {
        "type": "media",
        "mediaType": "image",
        "mimetype": "image/png",
        "url": "https://source.unsplash.com/random/880x400",
        "originator": {
            "name": "John Doe",
            "role": "external"
        }
    }
}
import request from "async-request";
import { createReadStream } from 'fs';
import FormData from 'form-data';

// Stream the binary file
const stream = createReadStream('./test.png')

// Create a formData and append the file and query (JSON)
const formData = new FormData()
formData.append('file', stream)
formData.append('query', JSON.stringify(query: {
    payload: {
        type: 'media',
        mediaType: 'image',
        mimeType: 'image/png;,
        url: 'https://source.unsplash.com/random/880x400'
        originator: {
            name: 'John Doe,
            role: external
        }
    }
}))

const result = await request({
  method: 'POST',
  url: 'https://api.flow.ai/rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY'
  },
  body: formData
})

Example Response:

200 OK
{
    "status": "ok"
}

The API allows you to send images, files and other media files.

For media you'll need to make a POST call that is multipart/form-data. The maximum file size you can upload is 250MB.

Parameters

threadId string Unique identifier of the thread

Arguments

traceId number Optional unique number that is passed along to identify the message. Use this to verify message delivery.
type string Indicates the type of message. Should be media
mediaType string Type of media, image, file, audio, or video
url string URL of media attachment
mimeType string Optionally specify the mime-type of the uploaded file, supported media formats are channel specific
lang string Optional language code in ISO format (2 letters)
timezone integer Optional UTF timezone offset in hours
params object Optional parameters

Thread messages

Flow.ai allows you to request messaging history for specific threadId. One history request is limited with 20 entries, if you need to retrieve more entries you should use optional parameter page.

GET rest/v1/messages/:threadId

Example Request

GET rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
import request from "async-request";

const result = await request({
  method: 'GET',
  url: 'https://api.flow.ai/rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Parameters

threadId string Unique identifier of the thread

Query parameters

sync string Optional parameter for enabling sync mode
page number Optional parameter for pagination

GET rest/v1/messages/:threadId?sync=true

Example Request

GET rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87?sync=true HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
import request from "async-request";

const result = await request({
  method: 'GET',
  url: 'https://api.flow.ai/rest/v1/messages/6ecfd199-853a-448f-9f91-ef397588ff87?sync=true&page=3',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok",
    "result": {
        "history": [
            {
                "originator": {
                    "name": "visitor_abc",
                    "role": "user",
                    "profile": {}
                },
                "messages": [
                    {
                        "fallback": "test",
                        "replyTo": null,
                        "contexts": [],
                        "params": {},
                        "intents": [],
                        "createdAt": "2019-06-25T12:45:11.857Z",
                        "responses": [
                                {
                                        "type": "text",
                                        "payload": {
                                                "text": "test"
                                        }
                                }
                        ]
                    },
                    ...
                ]
            },
            ...
        ],
    "threadId": "6ecfd199-853a-448f-9f91-ef397588ff87",
    "page": 3,
    "pages": 10
    }
}

Business hours

Retrieve a list of configured business hours for your project.

GET rest/v1/businesshours

Example Request

GET rest/v1/businesshours HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
import request from "async-request";

const result = await request({
  method: 'GET',
  url: 'https://api.flow.ai/rest/v1/businesshours',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok",
}

Query parameters

sync string Optional parameter for enabling sync mode

GET rest/v1/businesshours?sync=true

Example Request

GET rest/v1/businesshours?sync=true HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
import request from "async-request";

const result = await request({
  method: 'GET',
  url: 'https://api.flow.ai/rest/v1/businesshours?sync=true',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  json: true
})

Example Response:

200 OK
{
    "status": "ok",
    "businessHours": [
        {
            "weekdays": [
                {
                    "weekday": "Monday",
                    "content": [
                        {
                            "from": "0:20",
                            "to": "4:19"
                        },
                        {
                            "from": "10:00",
                            "to": "22:22"
                        },
                        ...
                    ]
                },
                ...
            ],
            "holidays": [
                {
                    "holiday": "New Year",
                    "date": "2019-12-31T00:00:00.000Z"
                },
                ...
            ],
            "label": "test BH",
            "timezone": "(UTC+03:00) Minsk"
        },
        ...
    ]
}

Webhooks

Webhooks are the way Flow.ai will deliver replies and notify your app of other type of events.

Receiving calls

Creating a webhook endpoint on your server is no different from creating any page on your website.

Webhook data is sent as JSON in the POST request body. The full event details are included and can be used directly, after parsing the JSON into an Event object.

Your webhook must meet with the following requirements:

Responding to a call

To acknowledge receipt of a webhook call, your endpoint should return a 2xx HTTP status code. All response codes outside this range, including 3xx codes, will indicate to Flow.ai that you did not receive the webhook. This does mean that a URL redirection or a "Not Modified" response will be treated as a failure. Flow.ai will ignore any other information returned in the request headers or request body.

We will attempt to deliver your webhooks for up to two 4 hours with an exponential back off. Webhooks cannot be manually retried after this time.

Type of Events

This is a list of all the types of events we currently send. We may add more at any time, so in developing and maintaining your code, you should not assume that only these types exist.

message.reply Called whenever Flow.ai is sending a reply message
message.delivered Called when your message that you sent has been successfully received
control.handover Called when the AI engine is handing off a specific threadId to your solution
control.pause Called when the AI engine has paused operation for a specific threadId
control.resume Called when the AI engine has resumed operation for a specific threadId

Bot control

We provide the ability to pause and resume bots for specific threads.

Pause

Pause a bot for specific thread

POST rest/v1/pause/:threadId

Example Request

POST rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
{}
import request from "async-request";

const result = await request({
  method: 'POST',
  url: 'https://api.flow.ai/rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {},
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Parameters

threadId string Unique identifier of the thread

Resume

Resume a bot for a specific thread

DELETE rest/v1/pause/:threadId

Example Request

DELETE rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
{}
import request from "async-request";

const result = await request({
  method: 'DELETE',
  url: 'https://api.flow.ai/rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {},
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Parameters

threadId string Unique identifier of the thread

Bot status

Retrieve the status of a bot (if it's paused or active) for a specific threadId

GET rest/v1/pause/:threadId

Example Request

GET rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87 HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
import request from "async-request";

const result = await request({
  method: 'GET',
  url: 'https://api.flow.ai/rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {},
  json: true
})

Example Response:

200 OK
{
    "status": "ok"
}

Parameters

threadId string Unique identifier of the thread

Query parameters

sync string Optional parameter for enabling sync mode

GET rest/v1/pause/:threadId?sync=true

Example Request

GET rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87?sync=true HTTP/1.1
Host: api.flow.ai
Content-Type: application/json
Authorization: Bearer MY_MESSAGING_API_KEY
import request from "async-request";

const result = await request({
  method: 'GET',
  url: 'https://api.flow.ai/rest/v1/pause/6ecfd199-853a-448f-9f91-ef397588ff87?sync=true',
  headers: {
    'Authorization': 'Bearer MY_MESSAGING_API_KEY',
    'Content-Type': 'application/json'
  },
  body: {},
  json: true
})

Example Response:

200 OK
{
    "status": "ok",
    "isPaued": false,
    "threadId": "6ecfd199-853a-448f-9f91-ef397588ff87"
}

Example

The following example demonstrates opening a connection and sending a test message using vanilla JavaScript in the browser.

<html>
    <script>
        (function () {
      // Vanilla JS example
      // When executing this script. Check your development console for any messages

      // This identifies specific user's message
      var threadId = 'USER_THREAD_ID'

      // Can be found in 'Outbound' section of your REST integration in Flow.ai dashboard
      var token = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZ2VudElkIjoiODkxZjBiZjQtNmYwYi00NWEyLThiYjUtMDk5MTI3MDdhZjQ0IiwiY2hhbm5lbElkIjoiOWUxYzZhOWUtMjE4ZC00NGFkLTg3OWYtNzEwMjFmMTgyYWU3IiwiaWF0IjoxNTYxMzk1MjM2fQ.sBzBBCplIPMzoOxBkQgkZtm7jN2TIrz_PWcI-bUjiOI'

      var url = 'https://api.flow.ai/rest/v1/'

      function sendTextMessage() {
        console.info('sendTextMessage')

        var message = {
          "payload": {
            "type": "text",
            "speech": "test",
            "originator": {
              "name": "John Doe",
              "role": "external",
              "profile": {
                "fullName": "John Doe",
                "firstName": "John",
                "lastName": "Doe",
                "gender": "M",
                "locale": "en-US",
                "timezone": -5,
                "country": "us",
                "email": "[email protected]",
                "picture": "https://randompicture.org"
              }
            }
          }
        }

        // Messaging/history endpoint
        var messageUrl = url + 'messages/' + threadId

        // Create a POST request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('POST', messageUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send(JSON.stringify(message))
      }

      function sendEventMessage() {
        console.info('sendEventMessage')

        var event = {
          "payload": {
            "type": "event",
            "eventName": "test_event",
            "originator": {
              "name": "John Doe",
              "role": "external",
              "profile": {
                "fullName": "John Doe",
                "firstName": "John",
                "lastName": "Doe",
                "gender": "M",
                "locale": "en-US",
                "timezone": -5,
                "country": "us",
                "email": "[email protected]",
                "picture": "https://randompicture.org"
              }
            }
          }
        }

        // Messaging/history endpoint
        var messageUrl = url + 'messages/' + threadId

        // Create a POST request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('POST', messageUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send(JSON.stringify(event))
      }

      function sendLocationMessage() {
        console.info('sendLocationMessage')

        var location = {
          "payload": {
            "type": "location",
            "lat": "12.3",
            "long": "3.21",
            "originator": {
              "name": "John Doe",
              "role": "external",
              "profile": {
                "fullName": "John Doe",
                "firstName": "John",
                "lastName": "Doe",
                "gender": "M",
                "locale": "en-US",
                "timezone": -5,
                "country": "us",
                "email": "[email protected]",
                "picture": "https://randompicture.org"
              }
            }
          }
        }

        // Messaging/history endpoint
        var messageUrl = url + 'messages/' + threadId

        // Create a POST request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('POST', messageUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send(JSON.stringify(location))
      }

      function sendMediaMessage() {
        console.info('sendMediaMessage')

        var media = {
          "payload": {
            "type": "media",
            "mediaType": "image",
            "url": "https://source.unsplash.com/random/880x400",
            "originator": {
              "name": "John Doe",
              "role": "external",
              "profile": {
                "fullName": "John Doe",
                "firstName": "John",
                "lastName": "Doe",
                "gender": "M",
                "locale": "en-US",
                "timezone": -5,
                "country": "us",
                "email": "[email protected]",
                "picture": "https://randompicture.org"
              }
            }
          }
        }

        // Messaging/history endpoint
        var messageUrl = url + 'messages/' + threadId

        // Create a POST request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('POST', messageUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send(JSON.stringify(media))
      }

      function getMessagingHistory() {
        console.info('getMessagingHistory')

        // Messaging/history endpoint        
        var historyUrl = url + 'messages/' + threadId

        //Create a GET request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('GET', historyUrl, true)
        req.setRequestHeader('Authorization', token)
        req.send()
      }

      function getMessagingHistorySync() {
        console.info('getMessagingHistorySync')

        // Messaging/history endpoint        
        var historyUrl = url + 'messages/' + threadId + '?sync=true'

        //Create a GET request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponseSync
        req.responseType = 'json'
        req.open('GET', historyUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function getBusinessHours() {
        console.info('getBusinessHours')

        // Messaging/history endpoint        
        var businessHoursUrl = url + 'businesshours'

        //Create a GET request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('GET', businessHoursUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function getBusinessHoursSync() {
        console.info('getBusinessHoursSync')

        // Messaging/history endpoint        
        var businessHoursUrl = url + 'businesshours?sync=true'

        //Create a GET request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponseSync
        req.responseType = 'json'
        req.open('GET', businessHoursUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function pauseBotForUser() {
        console.info('pauseBotForUser')

        // Pause/resume endpoint
        var pauseUrl = url + 'pause/' + threadId

        // Create a POST request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('POST', pauseUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function resumeBotForUser() {
        console.info('pauseBotForUser')

        // Pause/resume endpoint
        var resumeUrl = url + 'pause/' + threadId

        // Create a DELETE request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('DELETE', resumeUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function getBotStatus() {
        console.info('getBotStatus')

        // Messaging/history endpoint        
        var businessHoursUrl = url + 'pause/' + threadId

        //Create a GET request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponse
        req.responseType = 'json'
        req.open('GET', businessHoursUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function getBotStatusSync() {
        console.info('getBotStatusSync')

        // Messaging/history endpoint        
        var businessHoursUrl = url + 'pause/' + threadId + '?sync=true'

        //Create a GET request
        var req = new XMLHttpRequest()
        req.onload = restEndpointResponseSync
        req.responseType = 'json'
        req.open('GET', businessHoursUrl, true)
        req.setRequestHeader('Authorization', token)
        req.setRequestHeader("Content-type", "application/json")
        req.send()
      }

      function restEndpointResponse(e) {
        console.info('Received response')

        var xhr = e.target

        if (xhr.status !== 200) {
          // This is not OK..
          console.error('Error while sending text message', xhr.response)
          return
        }
        // In other case check your webhook url to see the response from Flow.ai
      }

      function restEndpointResponseSync(e) {
        console.info('Received response')

        var xhr = e.target

        if (xhr.status !== 200) {
          // This is not OK..
          console.error('Error while sending text message', xhr.response)
          return
        } else {
          console.log(xhr.response)
        }
      }

      // Sending text message
      sendTextMessage()

      // Sending event message
      sendEventMessage()

      // Sending location message
      sendLocationMessage()

      // Sending media message
      sendMediaMessage()

      // Getting business hours for project
      getBusinessHours()
      getBusinessHoursSync()

      // Getting messaging history
      setTimeout(function () {
        getMessagingHistory()
        getMessagingHistorySync()
      }, 1000)

      // Pausing bot
      setTimeout(function () {
        pauseBotForUser()
        getBotStatus()
        getBotStatusSync()
      }, 2000)

      // Resuming bot
      setTimeout(function () {
        resumeBotForUser()
      }, 3000)
    }())
    </script>
</html>

Management API (Beta)

Authentication

To authorize, use this code:

# With shell, you can just pass the correct header with each request
curl "https://api.flow.ai/v1/projects/:projectId/flows"
  -H 'Authorization: Bearer MY_MANAGEMENT_API_KEY'

Make sure to replace MY_MANAGEMENT_API_KEY with your API key.

Authenticate your API requests by providing a Management API key as a bearer token. All API requests expect this bearer token to be present.

You can register a new Management API key within your organisation settings.

Flows

Example Flow object:

{
    "flowId": "c48b0a06-9727-4735-8886-49286fae78e3",
    "projectId": "db3e3895-fe06-4dcc-a7a0-35b0c0ec55c3",
    "brainId": "86bc0fa0-25f7-4d3d-9dcf-eaa2a6f810b1",
    "title": "Hello World",
    "group": "Demo",
    "createdAt": "2018-10-24T06:45:19.541Z",
    "disabled": false,
    "steps": [{
        "stepId": "31aef3cf-8c96-442b-9871-7fc9be322da1",
        "title": "Hello!",
        "type": "INTENT",
        "contexts": [],
        "intent": {
            "intentId": "67841005-31b1-45b3-b939-3879dfd377de",
            "title": "Hello_World_Greeting",
            "createdAt": "2018-10-24T06:45:19.484Z",
            "examples": [{
                "entities": [],
                "query": "Hello"
            }, {
                "entities": [],
                "query": "Good day"
            }, {
                "entities": [],
                "query": "Good afternoon"
            }, {
                "entities": [],
                "query": "good morning"
            }, {
                "entities": [],
                "query": "hi"
            }, {
                "entities": [],
                "query": "Hey"
            }]
        },
        "actions": [{
            "type": "TEXT",
            "payload": {
                "texts": [
                    "Hi there! This is a customer service demo bot! ",
                    "Hello! I am a customer service demo bot!"
                ],
                "quickReplies": [],
                "delay": 0
            }
        }]
    }]
}

A Flow represents a conversation topic. It's combines a series of Step objects that the AI engine uses to determine what actions to perform.

The Flow object

Property Description
flowId string Unique ID of the Flow
projectId string Project ID the Flow belongs to
brainId string ID of the AI brain the Flow belongs to
title string Name of the Flow
group string Group name
createdAt date string Date the flow was created
disabled boolean Indicates if it should be ignored
steps array Collection of Step objects

The Step object

Example INTENT Step:

{
    "stepId": "31aef3cf-8c96-442b-9871-7fc9be322da1",
    "title": "Hello!",
    "type": "INTENT",
    "contexts": [],
    "actions": [{
        "type": "TEXT",
        "payload": {
            "texts": [
                "Simple reply"
            ],
            "quickReplies": [],
            "tags": []
        }
    }],
    "intent": {
        "intentId": "67841005-31b1-45b3-b939-3879dfd377de",
        "title": "Hello_World_Greeting",
        "createdAt": "2018-10-24T06:45:19.484Z",
        "examples": [{
            "entities": [],
            "query": "Hello"
        }, {
            "entities": [],
            "query": "hi"
        }, {
            "entities": [],
            "query": "Hey"
        }]
    }
}

Example EVENT Step:

{
    "stepId": "c7512efe-9c2e-4cd4-9fdc-11fc1d31dfb8",
    "type": "EVENT",
    "title": "EVENT NAME",
    "contexts": ["31aef3cf-8c96-442b-9871-7fc9be322da1"],
    "actions": [{
        "type": "TEXT",
        "payload": {
            "texts": [
                "Simple reply"
            ],
            "quickReplies": [],
            "tags": []
        }
    }]
}

Each Step is part of a Flow. Steps are used by the AI engine to determine what reply action to send when for example an intent is matched.

Steps can be related to other steps and configure complex tree like dialog structures,

Property Description
stepId string Unique ID of the Step
title string Name of the Step
type string Type of step. Should be a value of INTENT, EVENT, UNKNOWN, IMAGE, FILE, AUDIO, VIDEO, LOCATION, NOTHING, ANYTHING
contexts array Collection of stepIds that precede the step
intent object Intent object, required if type is INTENT
actions array Collection of Reply actions

List all Flows

This endpoint retrieves all Flows.

GET /flows/list

var request = require("request");
var options = { method: 'GET',
  url: 'https://api.flow.ai/v1/projects/:projectId/flows',
  qs: { limit: '5', skip: '0' },
  headers: 
   { 
     Authorization: 'MY_MANAGEMENT_API_KEY',
   } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
curl "https://api.flow.ai/v1/projects/:projectId/flows"
  -H 'Authorization: Bearer MY_MANAGEMENT_API_KEY'
Property Description
projectId required Project ID the Flow belongs to
limit optional Pagination option. Number of items per response
skip optional Pagination option. Number of items to skip
[{
    "flowId": "53ced89e-08e4-40bc-89b8-f7ea02ba6cd5",
    "projectId": "db3e3895-fe06-4dcc-a7a0-35b0c0ec55c3",
    "brainId": "86bc0fa0-25f7-4d3d-9dcf-eaa2a6f810b1",
    "title": "Get started",
  "group": "Weather",
    "createdAt": "2018-10-24T06:45:03.828Z",
    "disabled": false,
    "steps": [{
        "stepId": "4237653c-ad8d-4bf8-8ff5-da9dd7cb5636",
        "type": "INTENT",
        "title": "Get started",
        "contexts": [],
        "actions": ["5bd014ef0838670032b1aa11"],
        "intent": "5bd014ef0838670032b1aa16"
    }]
}, {
    "flowId": "f1a4c7fd-fa2b-4f67-a391-15b9e98d47ea",
    "projectId": "db3e3895-fe06-4dcc-a7a0-35b0c0ec55c3",
    "brainId": "86bc0fa0-25f7-4d3d-9dcf-eaa2a6f810b1",
    "title": "Weather",
  "group": "Weather",
    "createdAt": "2018-10-24T06:45:03.820Z",
    "disabled": false,
    "steps": [{
        "stepId": "ea8b18e6-eb07-4ad6-8df2-518c43c180e3",
        "type": "INTENT",
        "title": "What is the weather like",
        "contexts": [],
        "actions": ["5bd014ef0838670032b1aa13"]
    }, {
        "stepId": "e010bb48-a51b-48f3-ab46-81ce10f05454",
        "type": "SLOT",
        "title": "SLOT",
        "contexts": ["ea8b18e6-eb07-4ad6-8df2-518c43c180e3"],
        "actions": ["5bd014ef0838670032b1aa12"],
        "slot": {
            "validation": "REQUIRED",
            "entityId": "system.query",
            "label": "city"
        }
    }]
}]