Developing with Infobip
Step 3: Develop your app

Step 3: Develop your app

Each app has its own architecture and components required, but the overall process of developing your app is the same.

  1. Create the app shell
  2. Develop the core functionality of your app
  3. Create and connect the configuration page and settings DB, and connect to middleware/context card (optional)
  4. Connect your app to Infobip by updating the manifest
  5. Test your app.
  6. List to marketplace (optional)

Create the app shell

To get started creating an app, you’ll need to create the app shell which contains the information Infobip needs to use your app’s functionality. This also creates the app’s Client ID and Client Secret that can be used in the OAuth process.

When the app shell is first created, it is available to your account, but not available to anyone else. This is called private access. To make your app available to additional accounts, see the section on Listing your app on the Exchange marketplace.

To create your app shell:

  1. Log into your Infobip account and go to Exchange (opens in a new tab).

  2. Click Publish. If you can't see the Publish option, contact the Infobip Support (opens in a new tab) team to request access.

  3. Click Create App.

  4. Enter a name for your app in the App Name You can choose any name you prefer, but if you want to list your app on the public Exchange marketplace, you need to choose a unique name.

  5. From the Works withdrop-down list, select the products that your app uses. You can select all the relevant products.

    ProductNotes
    ConversationsIf your app is a context card, you do not need to select a channel as the app works natively with the channels supported by Conversations.
    AnswersIf your app is a chatbot block, you do not need to select a channel as the app works natively with the channels supported by Answers.
    Moments  FlowIf your app is a Moments Flow element, you do not need to select a channel as the app works natively with the channels supported by Moments.
    PeopleIf your app syncs data via the People API, then you do not need to select the channel as the app works with the channels supported by People. 
    ChannelsIf you have integrated a channel into your product using an API, then select the relevant channel.

    You'll then see an embedded text editor where you can build your manifest by editing the values. If you have chosen more than one product from the Works with drop-down list, you see separate tabs for each integration point manifest. Choose whether to use YAML or JSON to define your manifest.

  6. Edit the example manifest in the embedded text editor to define how your app connects to Infobip. At this stage, you can still create the app using default or dummy values, but be sure to update your manifest when you have the relevant information. See the section Define your manifest to correctly structure your manifest.

  7. Specify the URLs for: Settings URL for the location of the settings and configuration for the app. This is a web page where users can save settings and configure your app. This field is optional. Redirect URL for redirecting after authentication. If you use OAuth to connect your app to Infobip, this is the URL that redirects back to your app after authentication.

  8. Add a URL to an image for the logo in the Logo URL field. The logo file must be SVG format (.svg), with a size of 40 x 40 pixels.

  9. Click Create App to save your app settings and generate the app's credentials for connecting to Infobip.

You see the app created and listed in the Exchange Publish page.

The app details show the name and a Private label to show that it is available only to your account.

You'll also see the Infobip products that relate to this app.

The three-dot menu gives you a number of options.

OptionDescription
Edit Make changes to the settings that you entered in the publish stage. You can also view the Client ID, Client Secret and Signing secret.
ConfigureOpen the settings URL page for the app settings and configuration.
View IDView the client ID and client secret, the OAuth credentials used in authorization.
DeleteRemove the app from Exchange.

Once you've created your app, it is active for your account only. If the app includes a context card, the card is available to all agents in your account. If the app includes an Answers bot block, the block is available in the bot builder canvas.

If you intend to use the OAuth 2.0 flow with your app, you need to save the client ID and client secret. To validate the execution signature in Answers, you need to save the signing secret.

Develop core functionality of your app

In this step, you create the core functionality for the app. Depending on the needs of your app, you may create a UI experience through a website embedded via an iframe, an API, or middleware to interpret the call from Answers to your API endpoint.

Conversations

The following core functionality can be developed for Conversations:

  • Context Card UI: standard and XL sizes
  • Full page UI

Context Card UI

Conversations context cards allow you to show custom information to contact center agents in their workspace, as they assist end customers. Your context card UI should be a web page or web site that can be embedded into the agent experience using an iframe.

Context cards are available in two sizes: standard and XL.

Standard size context cards

Standard size context cards are loaded in the right-side panel of the agent’s workspace in My Work. By default, standard size context cards are not expanded. Agents can open the context card by clicking on the context card’s title to expand it.

To ensure the best display in the context card, design the content in your app with a maximum size of 425 x 500.

Standard sized context cards

XL size context cards

XL size context cards are loaded in a separate panel in the agent’s workspace in My Work. By default, XL context cards are expanded when the conversation is loaded. Agents only see one XL card, even if multiple are installed. Not all Infobip accounts are configured to support XL cards, so please reach out to us if you plan to use this setup.

The area available to the XL card changes based on the screen available, so responsive UI displays best. If the user has a screen less than 750px wide, the XL card is not visible.

XL sized context cards

Creating the context card UI and functionality

Your context card UI can be created however you like. There is some information available from Infobip that can help tailor the user’s experience.

On page load, Conversations loads your UI, and include the Conversations ID as a query parameter in the referrer header.

You can use this data to get more information about the Conversation using the Conversations API (opens in a new tab). To use Infobip APIs on behalf of the customer, you need to complete the OAuth 2.0 flow.

Example header content:

json
 
    {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
      "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
      "accept-encoding": "gzip, deflate, br",
      "accept-language": "en-US,en;q=0.9",
      "referer": "https://portal.infobip.com/conversations/my-work?conversationId=1f073950-5c7f-417e-990d-ae0efd8af797",
      "sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"",
      "sec-ch-ua-mobile": "?0",
      "sec-ch-ua-platform": "\"Windows\"",
      "sec-fetch-dest": "iframe",
      "sec-fetch-mode": "navigate",
      "sec-fetch-site": "cross-site",
      "sec-fetch-user": "?1",
      "upgrade-insecure-requests": "1",
      "x-forwarded-for": "89.164.98.239",
      "x-forwarded-host": "appendpoint.free.beeceptor.com",
      "x-forwarded-proto": "https"
    }
 

The following table shows the features commonly used on Context cards:

ActionSource
Get customer’s account keyOAuth 2.0
Get user’s emailOAuth 2.0
Get user’s preferred languageOAuth 2.0
Get Infobip token to use in API callsOAuth 2.0
Get customer’s channelConversations API: get Messages (opens in a new tab)
Get customer phone or email addressConversations API: get Messages (opens in a new tab)
Get conversation messagesConversations API: get Messages (opens in a new tab)
Send message in conversationConversations API: create Message (opens in a new tab)
Create noteConversations API: create Note (opens in a new tab)
Get customer informationPeople API: get Person (opens in a new tab)
Update customer informationPeople API: update Person (opens in a new tab)
Create a new customerPeople API: create Person (opens in a new tab)
Create an event to a customerPeople API: create Event (opens in a new tab)

Full page UI

Conversations full page apps allow you to show custom information to contact center agents and supervisors on a separate area within Conversations. Your full page UI should be a web page or web site that can be embedded using an iframe. There are no limitations on the size of the content for this app, but we recommend creating the UI in a responsive way so that it displays correctly on a variety of screen sizes, including mobile.

Your full page UI can be created however you like. There is some information available to your UI from Infobip that can help tailor the user’s experience.

On page load, Conversations loads your UI. As this experience isn’t tied to a specific conversation, the referrer does not include a Conversations ID. To get information about the customer’s account, use Infobip APIs on behalf of the customer, you need to complete the OAuth 2.0 flow.

The following table shows the features commonly used on full page apps:

ActionSource
Get customer’s account keyOAuth 2.0
Get user’s emailOAuth 2.0
Get user’s preferred languageOAuth 2.0
Get Infobip token to use in API callsOAuth 2.0
Get agentsConversations API: get Agents (opens in a new tab)
Get QueuesConversations API: get Queues (opens in a new tab)
Update working hoursConversations API: update Working Hours (opens in a new tab)
Get Conversation routing informationConversations API: get Routing (opens in a new tab)
Get customer informationPeople API: get Person (opens in a new tab)
Get list of tagsPeople API: get Tags (opens in a new tab)
Add a tag to a batch of peoplePeople API: add Tag (opens in a new tab)

Answers

The following core functionality can be developed for Answers:

  • API connection to Answers
  • Passing variables to your API
  • Designer experience
  • Account level variables
  • Arrays and complex data lists
  • Webhooks

Setting up the API to connect Answers

Answers connects to your app via an API call. It can call your API directly or through a middleware. Direct connections can be a quick way to create your app, however there are some limitations. Depending on the needs of your API and the experience you want to offer to users, you may need or want to develop middleware to translate the call from Answers into the call format needed for your API. Once your API is ready, update the Manifest to connect Answers to your API.

Passing variables to your API

Answers can send chatbot variables to your API in two ways: query and path parameters. Header parameters are not currently supported. If your API requires that variables be sent using a header, you must use a middleware API to translate the call from Answers into the correct format for your API.

Note: We do not recommend this option for information like platform credentials, tokens, etc as data set in bot attributes are not stored securely.

Answers Designer experience

When setting and receiving variables in the API call, Answers uses values set in bot Attributes by the Answers Designer. If the Answers Designer is unlikely to know how to populate a specific variable as an attribute, we recommend having the integration manager define the variable in the Configuration page, and use a middleware to combine the attributes set in the bot with the variables set in the configuration page.

Account level variables

If some variables are always the same for a specific account (such as account credentials), we recommend having the integration manager define the variable in the Configuration page, and use a middleware to combine the attributes set in the bot with the variables set in the configuration page.

Arrays and complex data types

Arrays are stored as a List in Answers. At this time, there isn’t a way to map a variable-length array response from your API directly to a List. We recommend returning the array to a JSON or Text attribute, then requiring the Answers Designer to parse the response to a List using a Code Block.

Handling webhooks

If the chatbot needs to wait for a change in state in your app, you need to manage this in your API or middleware. The Answers Designer can create a webhook for the bot instance as part of their bot setup. If the Answers Designer assigns the sessionId to an attribute using a Code Block, it can be sent to your API. Then your app can continue the bot by calling the webhook at https://api.infobip.com/bots/webhook/\{\{sessionId\}\}‎ (opens in a new tab).

Moments - Flow

The following core functionality can be developed for Moments - Flow:

  • API connection to Flow
  • Passing variables to your API

Setting up the API to connect Flow

Flow connects to your app via an API call. It can call your API directly or through middleware.

Direct connections are a quick way to create your app, however there are some limitations.

Depending on the needs of your API and the experience you want to offer to users, you may need or want to develop middleware to translate the call from Flow into the call format needed for your API. Once your API is ready, update the Manifest to connect Flow to your API.

Passing Flow variables and People attributes to your API

You can send variables to your API in the following ways:

  • path and query - also known as the URL parameters
  • body
  • headers - only supported in Flow

Handling authorization tokens

If your API requires authorization tokens, and especially if they expire, you need to manage the token lifecycle within your API or middleware.

Creating a configuration page and settings DB

In this optional step, you’ll set up the configuration page UI and any supporting database and API connections needed. We recommend using a configuration page for the best user experience when your API requires account level information or you have additional settings that is used by your middleware, or if you would like to have more information available to the person who sets up your app for use. The configuration page can also be used to help with the onboarding process, offering access to templates and additional documentation users need to best use your app. You can store any settings defined by the Integrations Manager in a settings database, and use your middleware to insert the appropriate calls into your API endpoint call.

Configuration page UI

Configuration pages allow integration managers to define settings that can apply to any usage of the app.  Integrations managers can access this page through the My Apps section of Exchange. Your configuration page UI should be a web page or web site that can be embedded using an iframe. There are no limitations on the size of the content for this page, but we recommend creating the UI in a responsive way so that it displays correctly on a variety of screen sizes, including mobile. This page is defined in the App shell by populating the Settings URL field.

Configuration page UI

Your configuration page UI can be created however you like. There is some information available to your UI from Infobip that can help tailor the user’s experience.

On page load, Exchange loads your UI. To get information about the customer’s account, use Infobip APIs on behalf of the customer, you need to complete the OAuth 2.0 flow. Some features commonly used on the configuration page:

ActionSource
Get customer’s account keyOAuth 2.0
Get user’s emailOAuth 2.0
Get user’s preferred languageOAuth 2.0
Get Infobip token to use in API callsOAuth 2.0

You can point to the location of page in the Settings URL when publishing your app, or select the Edit option on your app to change this location.

When you have entered a settings page URL for your app, your app three-dot menu also shows a Configure option.

To open the settings page so that you can see the app settings, select Configure.

Update the manifest

The manifest is the interface between your app and Infobip. The manifest contains all the information that Infobip needs to display and use your app.

Manifests can be in either JSON or YAML format. The full structure of the manifest depends on whether you are building an app for Conversations, Answers, or Moments.

Conversations

A Conversations manifest includes dictionaries for each entry point that the app supports. Currently each app can support one context card and full-page app.

The Conversations manifest contains the following key-value pairs for context card.

Card Key  Card Value description
cardThe integration point type for context card.
titleThe name of the app that is displayed to the user. This is a required field. The default example is My App Name.
srcThe URL of the page that is inserted into the iframe in Conversations. HTTPS links are strongly recommended. This is a required field. The default example is  https://awesome.app.com/context-card (opens in a new tab) .
sizeThe size of the context card in the Conversations right-side panel. The default is standard.·         standard: context card is shown along with other cards·         XL: the context card is shown on its own and spans the whole height of the screen

The Conversations manifest contains the following key-value pairs for a full page app.

Page Key  Page Value description
pageThe integration point type for full-page.
titleThe name of the app that is displayed to the user. This is a required field. The default example is My App Name.
srcThe URL of the page that is inserted into the iframe in Conversations. HTTPS links are strongly recommended. This is a required field. The default example is https://awesome.app.com/context-card (opens in a new tab).
pathThe path where the integration is presented. The path should start with "/". For example, /my-app

This is an example YAML manifest for Conversations:


    card: 
        title: My App Name 
        src: https://awesome.app.com/context-card 

This is an example JSON manifest for Conversations:

json
 
    {  
        "page": {
            "title": "My full-page app",
            "src": "https://awesome.app.com/fullpage-source",
    
             "path": "/documents/my-app"
        }
    }
 

This is an example YAML manifest for Conversations using both entry points:


    card:
      title: My Super Context Card
      src: https://awesome.app.com/context-card
    page:
      title: My Super Full-Page App
      src: https://awesome.app.com/fullpage

Answers

You can choose one of the following layout types when creating your manifest for Answers:

  • Verbose layout: defining the full structure of the functions used in your api call, including input and output fields
  • Simplified layout: specifying an endpoint in the manifest that returns the full function details

Each of the manifest layouts are outlined below.

The Answers manifest may contain some or all of the following key-value pairs.

KeyValue description
functionsDefine a list of all available functions in this dictionary. 
nameThe name of the function (default is My Order App). This value is shown to the chatbot editor. Each app can have multiple functions.
methodDefines how to call your function. The accepted methods are GET, POST, DELETE, POST, and PATCH.
descriptionUse this field to describe what the function does. For example, this function retrieves order details by Order ID. This description is shown to the chatbot editor. 
uriThis is the endpoint the chatbot calls to execute the function. For example,https://my-shopping-app.com/app/8/invoke/getOrderDetails (opens in a new tab) .
inSchemaDefines the variables that are inputs to your function request, including variable type, customer readable descriptions, variable names and whether the variable is required. type: The type, for example, object. required: Lists the properties that are required. These are the properties that you describe in the properties field. properties: A list of each property that could be passed to your endpoint call. You can define multiple properties. property_name: The name of any input property used in the endpoint request, for example, a property name like order_id.  type: The type of property. The possible values are: string, number. title: A UI-friendly name of the input property. This property title is displayed to the chatbot editor. example: Provides example values for the property. This is used to show the user how this information will look.
outSchemaDefines the variables that are outputs from your function response, including variable type, customer readable descriptions and variable names. type: The type, for example, object. required: Lists the properties that are required. These are the properties that you describe in the properties field. properties: A list of each property that could be returned in your endpoint response. You can define multiple properties. property_name: The name of any output property used in the endpoint request.  type: The type of property, for example, integer or string. title: A UI-friendly name of the input property. This property title is displayed to the chatbot editor. default: The default value of the property. For integer types, the default is 0. For string types, the default is ''. example: Provides example values for the property. This is used to show the user how this information will look. pattern: The expected schema pattern. The default is ^(.*)$

Making changes to the manifest

Take care when updating your manifest after users have implemented your integration. Adding optional variables to your inSchema and outSchema are likely to have minimal impact, but adding required variables to the inSchema may break users in production. If you need to make significant changes to your manifest, contact Infobip to help migrate customers to a new version of your manifest.

Query parameters and path parameters

The Answers manifest gives you the ability to add supporting query parameters and path parameters. This means that you can include chatbot attributes as parameters within your function. To use chatbot attributes within your functions, you surround the attribute with curly braces { }.

For example, a function that calls the endpoint:

https://my-shoping-app.com/app/8/invoke/getOrderDetails (opens in a new tab)

If you obtain the "orderId" from your chatbot, the uri value in your manifest becomes:

https://my-shoping-app.com/app/8/invoke/getOrderDetails/{orderId} (opens in a new tab)

Another example of using query parameters is:

https://my-shoping-app.com/app/orders?limit={limit} (opens in a new tab)

You do not need to include the parameters as inSchema properties.

When using the bot block within Answers, you can choose the value of each of the defined parameters.

Verbose manifest layout

Use this layout if the overall structure for your app does not change from user to user, and you don't anticipate the endpoints or function schemas changing frequently.

To define your manifest, you'll specify each function that your app uses, its endpoint, and all input and output fields that the function uses.

This is an example YAML verbose manifest for Answers:


    functions:
      - name: getOrderDetails
        method: GET
        description: Gets Order details by Order ID
        uri: https://my-shoping-app.com/app/8/invoke/getOrderDetails
        inSchema:
          type: object
          required:
            - order_id
          properties:
            order_id:
              type: number
              title: Order ID
        outSchema:
          type: object
          title: The Items Schema
          required:
            - id
            - email
          properties:
            id:
              type: integer
              title: The Id schema
              default: 0
              examples:
                - 450789469
            email:
              type: string
              title: The Email Schema
              default: ''
              examples:
                - [email protected]
              pattern: ^(.*)$

This is an example JSON verbose manifest for Answers:

json
 
    {
        "functions": [
            {
                "name": "getOrderDetails",
                "method": "GET",
                "description": "Gets Order details by Order ID",
                "uri": "https://my-shoping-app.com/app/8/invoke/getOrderDetails",
                "inSchema": {
                    "type": "object",
                    "required": [
                        "order_id"
                    ],
                    "properties": {
                        "order_id": {
                            "type": "number",
                            "title": "Order ID"
                        }
                    }
                },
                "outSchema": {
                    "type": "object",
                    "title": "The Items Schema",
                    "required": [
                        "id",
                        "email"
                    ],
                    "properties": {
                        "id": {
                            "type": "integer",
                            "title": "The Id schema",
                            "default": 0,
                            "examples": [
                                450789469
                            ]
                        },
                        "email": {
                            "type": "string",
                            "title": "The Email Schema",
                            "default": "",
                            "examples": [
                                "[email protected]"
                            ],
                            "pattern": "^(.*)$"
                        }
                    }
                }
            }
        ]
    }
 

This is an example YAML verbose manifest for Answers with two functions: getOrderDetails and getShippingDetails.


    functions:
      - name: getOrderDetails
        method: GET
        description: Gets Order details by Order ID
        uri: https://my-shoping-app.com/app/8/invoke/getOrderDetails
        inSchema:
          type: object
          required:
            - order_id
          properties:
            order_id:
              type: number
              title: Order ID
        outSchema:
          type: object
          title: The Items Schema
          required:
            - id
            - email
          properties:
            id:
              type: integer
              title: The Id schema
              default: 0
              examples:
                - 450789469
            email:
              type: string
              title: The Email Schema
              default: ''
              examples:
                - [email protected]
              pattern: ^(.*)$
      - name: getShippingDetails
        method: POST
        description: Get shipping details based on an input order id.
        uri: https://awesome.app.com/getShippingDetails
        inSchema:
          type: object
          required: 
          - orderId
          properties:
            orderId:
              type: number
              title: Order ID
        outSchema:
          type: object
          properties:
            shippingStatus:
              type: string
              title: Order status
            trackingNumber:
              type: number
              title: Number of items in order
            expectedDeliveryDate:
              type: string
              title: Expected delivery date

Simplified manifest layout

Use this layout if you plan to use different endpoints based on the logged-in user. Answers queries this endpoint to get the list of functions and their inputs and outputs.

This is an example of a YAML simplified manifest:


    uri:  https://awesome.app.com/getFunctions

This is an example of a JSON simplified manifest:

json
 
    {"url":  "https://awesome.app.com/getFunctions"
    }
 

Moments - Flow

A Moments - Flow manifest includes the functions that define Flow elements in the Flow editor. A Moments – Flow manifest consists of the parameters that build an element and define how it is rendered in the Flow.

The Moments - Flow manifest consists of the following main sections:

  • Functions - define any procedure that can be executed on a third-party service
  • Action - every action defines an element in Flow and it will execute some function when the flow is started
  • Render - defines the list of input fields used by an action and which specifics how the user sees the function in the Flow editor

Functions

The following table describes the function fields and examples from the default manifest in Exchange.

Both inSchema and outSchema support the https://json-schema.org/ (opens in a new tab) standard.

FieldField descriptionExample
nameDefines the name of the function as the function identifier. Each app can have multiple functions. This is the function that will be executed when the flow element is processed. When you define an action, make sure that the action name has a corresponding function with the same name. For every render option that has the field model set, there needs to be defined a function with the same name as the model. This is the function that will be executed when the predefined values for this field are fetched.{
    "functions": [
        {
            "name": "Create reservation",
            ...
        }
    ]
}
 
methodDefines how to call your function. The valid methods are GET, POST, DELETE, POST, and PATCH.{
  "functions": [
        {
          "name": "Create reservation",
"method": "POST",
...
        }
    ]
}
descriptionUse this field to describe what the function does.This description is shown to the user as the function definition in the Flow editor.{
  "functions": [
        {
          "name": "Create reservation",
"method": "POST",
"description": "Creates a reservation",
...
       }
   ]
}
uriThis is the endpoint call to execute the function. This endpoint is used by Exchange when executing the function.{
  "functions": [
        {
          "name": "Create reservation",
"method": "POST",
"description": "Creates a reservation",
"uri": "https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations (opens in a new tab)",
...
        }
    ]
}
 Optionally, you can add supporting query parameters and path parameters.  This allows you to include attributes as parameters within your function. To use attributes within your functions, you surround the attribute with curly braces { }. For example, a function that calls the endpoint:https://api.example.com/\{path1\}/v1?query1=\{query1 (opens in a new tab)} Map parameters to the properties in inSchema, for example, the query parameter query1={query1} maps to the property as: 

        "_query1": {
         "title": "Query 1",
         "type": "string"
     }

The property must be defined with the underscore prefix (_query1). 
..."uri": "https://api.example.com/\{path1\}/v1?query1=\{query1 (opens in a new tab)}",

"inSchema": {
                "properties": {
                   "_path1": {
                       "title": "Path 1",
                        "type": "string"
                    },
                   "_query1": {
                       "title": "Query 1",
                        "type": "string"
                   }
                }

inSchemaDefines the input parameters to a function, including variable type, customer readable descriptions, variable names and whether the variable is required. inSchema must include the following parameters: 
  • type: Set the type as object.
  • properties: A map of each property that could be passed to your endpoint call. You can define multiple properties.
  • required: list the input properties that are be included in the function.
 For each of the properties, you must define: 
  • property_name: The name of any input property used in the endpoint request. The property names must match field names from the render options this field depends on. For example, date or host_email.
  •  
  • type: The type of property. The possible values are: string, number.
  •  
  • title: A UI-friendly name of the input property. This property title is displayed in the Flow editor.
 You can also include: 
  • examples: Provides example values for the property. This is used to show the user how this information will look.
...           
"inSchema": {
                "type": "object",
                "properties": {
                    "host_name": {
                        "type": "string",
                        "title": "Host's Name"
                    },
                    "host_email": {
                        "type": "string",
                        "title": "Host's email"
                    },
                    "date": {
                        "type": "string",
                        "title": "Reservation date"
                  }
                },
                "required": [
                    "date",
                  "host_name"
                ]
            },
outSchemaDefines the output parameters from your function response, including variable type, customer readable descriptions and variable names. outSchema must include the following parameters: 
  • type: The top-level type is object.
  • properties: A map of each property that can be returned in your endpoint response. You may define multiple properties.
For each property, define: 
  • property_name: The name for the output property used in the endpoint request. The name of the property should match the name of the field in the render options.
  •  
  • For each property, define:  
  •  
    • path: Defines where the response is located. For example, header or body. The default is body. You can also define statusCode.
  •  
    • type: The property type. For example, integer, string, number, boolean, object.
      Type may also contain array for functions that fetch predefined values for drop down lists. Define the type array when using render option viewClass: SelectView field. 
    •  
    • title: A name for the property. 
...           
"outSchema": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "title": "Reservation ID"
                    },
                    "host_name": {
                        "type": "string",
                        "title": "Host's Name"
                    },  
                    "host_email": {
                        "type": "string",
                        "title": "Host's email"
                    },
                    "date": {
                        "type": "string",
                        "title": "Reservation date"
                  },
"status": {
                      "path": "statusCode"
"type": "string",
                      "title": "Reservation status"
                  },

                }
 Example using type array: A map of properties should include two properties to identify which values will be used for SelectView (dropdown) field as Option Name and Option ID. 
  • selectViewOptionIdPath
  • selectViewOptionNamePath
 Define value of these properties as JSON path to reach out ID and Name in the given array.

...
"outSchema": {

       "properties": {             "selectValue": {                "selectViewOptionIdPath": "$.array[].id",               "selectViewOptionNamePath": "$.array[].name",                "title": "selectValue",                "type": "array"             }           }

Actions

The following table describes the actions fields and examples from the default manifest in Exchange.

Note

Actions are only used in Moments - Flow manifests and are not supported in manifests for other products.

FieldField descriptionExample
name Defines the name for the action. This is a string. Every action must have a corresponding function with the same name. For example, if you define an action in the manifest, which will correspond with the function called getActionOne, then you must define the action name also as getActionOne.There can be many functions related to one action but there must be one function that has the same name as the action.
{
...
"actions": [
      {
"name": "Delete reservation",
...
}
]
}


 

render  Defines the list of input fields used by the action. These input fields are used to define how to user sees the the function in the Flow editor.Each input field must specify the following:
  • field: The name of the field. This name must match the property name in the corresponding function. For example, properties: _id:
  •  
  • viewClass: Defines how the user inputs data to this field:
  •  
    • TextFieldView  - renders an input field for plain text
    • SelectView  - renders a drop down menu to allow the selection from a list of items
 The following fields are optional: 
  • placeholder: Defines the placeholder text for the function. For example, "Provide the conferenceId..."
  •  
  • personalization: A boolean value. Defines whether the "Personalize with placeholders" {} option is available in the field. This option allows the user to put tokens, such as flow variables, personal information and contact information, which will be interpolated when the element will be processed. This option is only appropriate to TextFieldView fields. For SelectView, set to false.
  •  
  • model : If the field is SelectView this specifies the name of the function that will be invoked to fetch possible values for this field. The name must relate to the functions defined in the manifest. This value is a string. In the example, model corresponds to the Get all reservations function.
  •  
  • dependencies : A list of strings specifying on which other fields that this field depends. These strings must not create any circular dependencies and the the fields must be resolved in at least one order, otherwise all flows with this integration will be rejected upon flow launch. It the field is SelectView , the function that is being invoked to fetch the predefined values for this field might expect some parameters. 
{
...
"actions": [
      {
"name": "Create reservation",
       "render": [
                {
                  "field": "host_name",
                  "viewClass": "TextFieldView",
                  "personalization": true,
                    "dependencies": []
                }
...
          ]
...
},
{
"name": "Delete reservation",
        "render": [
                {
                    "field": "_id",
                    "viewClass": "SelectView",
                    "model": "Get all reservations",
                    "personalization": false,
                    "dependencies": []
                }
...
]
}
]
}


    

Example Manifest

The following is an example JSON manifest for Moments Flow. This manifest represents a working integration with a demo application to manage imaginary restaurant reservations.

Go to the demo application at the following link: https://restaurant-reservations-demo.azurewebsites.net/ (opens in a new tab)

The demo application is published on Github: https://github.com/infobip-community/restaurant-reservations-demo (opens in a new tab)

You may use this manifest and test how integration works with the app from your Infobip account.

Note

The app is used only as an example representation of an Exchange integration and to show the manifest capabilities. Do not use the demo application in any production scenarios and do not share personal data with the application.

json
 
    {
        "icon": "https://cdn-web.infobip.com/uploads/2023/01/Infobip-logo.svg",
        "functions": [
            {
                "name": "Get all reservations",
                "description": "Get all reservations",
                "method": "GET",
                "uri": "https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations",
                "inSchema": {},
                "outSchema": {
                    "type": "object",
                    "properties": {
                        "_id": {
                            "type": "array",
                            "items": [
                                {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "string",
                                            "title": "Reservation ID"
                                        },
                                        "host_name": {
                                            "type": "string",
                                            "title": "Host's Name"
                                        }, 
                                        "host_email": {
                                            "type": "string",
                                            "title": "Host's email"
                                        },
                                        "date": {
                                            "type": "string",
                                            "title": "Reservation date"
                                        },
                                        "hour": {
                                            "type": "string",
                                            "title": "Reservation time"
                                        },
                                        "party_size": {
                                            "type": "number",
                                            "title": "Number of participants"
                                        }
                                    }
                                }
                            ],
                            "selectViewOptionIdPath": "$.reservations[*].id",
                            "selectViewOptionNamePath": "$.reservations[*].host_email"
                        }
                    }
                }
            },
            {
                "name": "Create reservation",
                "description": "Creates a reservation",
                "method": "POST",
                "uri": "https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations",
                "inSchema": {
                    "type": "object",
                    "properties": {
                        "host_name": {
                            "type": "string",
                            "title": "Host's Name"
                        },
                        "host_email": {
                            "type": "string",
                            "title": "Host's email"
                        },
                        "date": {
                            "type": "string",
                            "title": "Reservation date"
                        },
                        "hour": {
                            "type": "string",
                            "title": "Reservation time"
                        },
                        "party_size": {
                            "type": "number",
                            "title": "Number of participants"
                        }
                    },
                    "required": [
                        "date",
                        "host_name",
                        "host_email",
                        "hour",
                        "party_size"
                    ]
                },
                "outSchema": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "string",
                            "title": "Reservation ID"
                        },
                        "host_name": {
                            "type": "string",
                            "title": "Host's Name"
                        }, 
                        "host_email": {
                            "type": "string",
                            "title": "Host's email"
                        },
                        "date": {
                            "type": "string",
                            "title": "Reservation date"
                        },
                        "hour": {
                            "type": "string",
                            "title": "Reservation time"
                        },
                        "party_size": {
                            "type": "number",
                            "title": "Number of participants"
                        }
                    }
                }
            },
            {
                "name": "Update reservation",
                "description": "Updates a reservation",
                "method": "PUT",
                "uri": "https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations/{id}",
                "inSchema": {
                    "type": "object",
                    "properties": {
                        "_id": {
                            "type": "string",
                            "title": "Reservation ID"
                        },
                        "host_name": {
                            "type": "string",
                            "title": "Host's Name"
                        },
                        "host_email": {
                            "type": "string",
                            "title": "Host's email"
                        },
                        "date": {
                            "type": "string",
                            "title": "Reservation date"
                        },
                        "hour": {
                            "type": "string",
                            "title": "Reservation time"
                        },
                        "party_size": {
                            "type": "number",
                            "title": "Number of participants"
                        }
                    },
                    "required": ["_id"]
                },
                "outSchema": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "string",
                            "title": "Reservation ID"
                        }, 
                        "host_email": {
                            "type": "string",
                            "title": "Host Email"
                        },
                        "host_name": {
                            "type": "string",
                            "title": "Host Name"
                        },
                        "hour": {
                            "type": "string",
                            "title": "Hour"
                        },
                        "date": {
                            "type": "string",
                            "title": "Date"
                        },
                        "party_size": {
                            "type": "number",
                            "title": "Party Size"
                        }                  
                    }
                }
            },
            {
                "name": "Delete reservation",
                "description": "Deletes a reservation",
                "method": "DELETE",
                "uri": "https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations/{id}",
                "inSchema": {
                    "type": "object",
                    "properties": {
                        "_id": {
                            "type": "string",
                            "title": "Reservation ID"
                        }
                    },
                    "required": ["_id"]
                },
                "outSchema": {}
            }
        ],
        "actions": [
            {
                "name": "Create reservation",
                "render": [
                    {
                        "field": "host_name",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "host_email",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "date",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "hour",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "party_size",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    }
                ],
                "async": false
            },
            {
                "name": "Update reservation",
                "render": [
                    {
                        "field": "_id",
                        "viewClass": "SelectView",
                        "model": "Get all reservations",
                        "personalization": false,
                        "dependencies": []
                    },
                    {
                        "field": "host_name",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "host_email",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "date",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "hour",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    },
                    {
                        "field": "party_size",
                        "viewClass": "TextFieldView",
                        "personalization": true,
                        "dependencies": []
                    }
                ],
                "async": false
            },
            {
                "name": "Delete reservation",
                "render": [
                    {
                        "field": "_id",
                        "viewClass": "SelectView",
                        "model": "Get all reservations",
                        "personalization": false,
                        "dependencies": []
                    }
                ],
                "async": false
            }
        ],
    
      "triggers": []
 

API request example

The following is an example of an API request. Exchange calls the defined uri with the data provided in this format.

The example show the raw body for function the "Creation reservation" https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations (opens in a new tab).

json
 
    {
        "host_email": "[email protected]",
        "host_name": "Test",
        "hour": "11:00",
        "date": "2/15/2024",
        "party_size": "2"
    }
 

API response example

The following is an examples of an API response. Exchange expects the function to return data in this format for the manifest configuration.

The example shows the response for the function "Get all reservations" https://restaurant-reservations-demo.azurewebsites.net/exchange/restaurant/reservations (opens in a new tab).

json
 
    {
        "reservations": [
            {
                "host_email": "[email protected]",
                "host_name": "Test",
                "hour": "15:30",
                "date": "2/14/2024",
                "party_size": "2",
                "additionalFields": [],
                "id": "fde30afb-f563-40b1-aa6c-d8106e3f278d"
            },
            {
                "host_email": "[email protected]",
                "host_name": "Bob",
                "hour": "11:00",
                "date": "2/15/2024",
                "party_size": "2",
                "additionalFields": [],
                "id": "c96734da-1f1c-4aba-8129-5c3e9848ba14"
            }
        ]
    }
 

Model

If a function corresponds to a model for an input field, then its inSchema properties can be any from the list except array, and its outSchema properties should be array. In the outSchema, the name of the property should match the name of the field in the render option. Also, in inSchema, property names should match the field names from the render options that this field depends upon. The following is an example of the manifest.

The field definition for render in the actions (fields field3 , field4  and field5  are defined in the same list as field6 ):

json
 
    {
      "field": "field6",
      "viewClass": "SelectView",
      "model": "ref6",
      "dependencies": [
        "field3",
        "field4",
        "field5"
      ],
      "personalization": false
    }
 

The function definition for the model of the field:

json
 
    {
      "name": "ref6",
      "description": "",
      "method": "GET",
      "uri": "some uri",
      "inSchema": {
        "properties": {
          "field3": {
            "type": "string",
            "title": "field3"
          },
          "field4": {
            "type": "string",
            "title": "field4"
          },
          "field5": {
            "type": "string",
            "title": "field5"
          }
        }
      },
      "outSchema": {
        "properties": {
          "field6": {
            "type": "array",
            "title": "field6"
          }
        }
      }
    }
 

The format for the values from array is:

json
 
    [
      {
        "id": "value1",
        "name": "Value 1"
      },
      {
        "id": "value2",
        "name": "Value 2"
      }
    ]
 

This is a list of objects with the fields id (used during processing) and name (shown in the drop-down menu).

Dependencies

The dependencies field for the render options has a number of use cases. This example demonstrates how it works:

Select continent, and once you select the continent another select field appears which allows you to select a country, and once you select a country a third select field appears to select a city.

In this example, field0  is TextFieldView, and the other fields are SelectView. The dependencies are:

  • field1  has no dependencies
  • field2  depends on field1
  • field3  depends on field1  and field2
  • field4  depends on field3
  • field5  depends on field3  and field4
  • field6  depends on field3 , field4  and field5

The order in which the fields are resolved is numerical, from field1  to field6.

This is the state at the beginning:

If you choose a value for field1, the field2 gets its predefined values and becomes unlocked.

Choose the values for the next fields.

If you change the value of field2 , all the fields that transitively but not directly depend on it are erased and disabled, in this example field4 . Fields that directly depend on it are also be erased, but new predefined values are fetched and the fields are disabled, as they can be resolved. In this example field3 .

Making changes to the manifest

Take care when updating your manifest after users have implemented your integration. Adding optional variables to your inSchema and outSchema are likely to have minimal impact, but adding required variables to the inSchema may break users in production. If you need to make significant changes to your manifest, contact Infobip to help migrate customers to a new version of your manifest.

Tips for testing

To test your app, first ensure that you have access to and are familiar with the Infobip product. Depending on the communication channel you’d like to use, you may need to configure senders/numbers.

It’s recommended to create a simple app first, then start to layer on more complex experiences like managing additional variables, page navigation and OAuth.

See the Troubleshooting section for common issues.

Testing Answers chatbots

For Answers apps, we recommend setting up a bot outlining the full experience, to ensure all pieces are connected properly. You can also export the chatbot and provide it to customers to use as a template for their own chatbots.

Testing Moments - Flow elements

For Moments - Flow elements, we recommend setting up a flow outlining the full customer journey to ensure all pieces are connected properly. You can also save the flow as a template to use again.

For more information about using the Flow editor and managing a flow, see Manage flow.

Need assistance

Explore Infobip Tutorials

Encountering issues

Contact our support

What's new? Check out

Release Notes

Unsure about a term? See

Glossary

Research panel

Help shape the future of our products
Service Terms & ConditionsPrivacy policyTerms of use