Format

There are three types of messages. A Bubble is the most basic, plain message container, to which we can attach actual content (text, image, buttons, etc.).
Bubbles can then be combined into two kinds of complex messages: A Card is meant for presenting more detailed information on a specific content object. And a Selection is meant for presenting a set or choice of content objects.

(Content object is Mercury's term for the kind of things the bot can talk about on the basis of some provided datasource. This can be, for example, recipes, movies, flights, insurances, and the like.)

Bubbles

The general structure of a bubble simply comprises a list of attachments:

{
  "type": "Bubble",
  "attachments": [ ... ]
}

The currently covered attachment types are as follows.

Text

Text is a UTF-8 string, possibly together with formatting information.

{
  "type": "Text",
  "text": "Hi, Freddy! Schön dass du hier bist.",
  "format": "PLAIN",
  "role": "NONE"
}

The default format is PLAIN, but it can also indicate the markup used in the actual text string (such as Speech Markup, HTML, or anything that else that makes sense).

The role can be NONE (the default), TITLE, or SUBTITLE. The latter two are relevant for Selections and Cards.

Image

{
  "type": "Image",
  "path": "https://media.giphy.com/media/1WDyG7bCEKgOk/giphy.gif"
}

Video

{
  "type": "Video",
  "path": "https://www.youtube.com/watch?v=NeEpjHxZEUM"
}

The path can be either a web link or an ID if there is some content server that stores the video (as Facebook's CDN, for example).

Buttons

The different types of buttons are closely modeled after Facebook's button types. They specify a text, specifying what the user sees as button text and encoded as a text attachment, and either a payload or URL, which is what is triggered when user clicks on the button.

The general format of a button payload is the following:

{
  "game": <string>,
  "intent": <string>,
  "slots": [
    {
      "label": <string>,
      "value": <string>
    }
  ]
}

The covered button types are QuickReply, Postback, and Link.

Quick Reply Buttons contain a payload that is sent to the bot when the user clicks on it. They are non-persistent, i.e. when a user clicks on one of possibly several presented buttons, the buttons are removed from the interface and cannot be clicked another time. This is especially useful for options that are somewhat dependent on the context of the current dialog or message (such as "yes" and "no").

{
  "type": "Button",
  "buttonType": "QuickReply",
  "text": {
      "text": "Ja",
      "type": "Text",
      "format": "PLAIN",
      "role": "NONE"
  },
  "payload": {
      "game": "OptIn",
      "intent": "Yes",
      "slots": []
  }
}

Postback Buttons also contain a payload, but are persistent, i.e. they usually have a fixed place in the interface and don't disappear but can be clicked as often as the user wants. They should only contain payloads that are unambiguous and independent of the current dialog state.

{
  "type": "Button",
  "buttonType": "Postback",
  "text": {
      "text": "Hi!",
      "type": "Text",
      "format": "PLAIN",
      "role": "NONE"
  },
  "payload": {
    "game": "SmallTalk",
    "intent": "Greeting",
    "slots": [
      {
        "label": "formal",
        "value": "false"
      }
    ]
  }
}

Link Buttons contain a URL, which is opened when the user clicks on the button.

{
  "type": "Button",
  "buttonType": "Link",
  "text": {
     "type": "Text",
     "text": "Kontakt",
     "format": "PLAIN",
     "role": "NONE"
   },
   "url": "https://www.mercury.ai/#contact"
}

Cards

A Card is meant for presenting more detailed information on a specific content object. Its general structure is simply a list of bubbles, each bubble specifying a part of information about the content object.

{
  "type": "Card",
  "bubbles": [ ... ]
}

See the Examples section below for examples.

Selections

A Selection is meant for presenting a set or choice of content objects. Like a card, it is simply a list of bubbles; however, the semantics is different: here each bubble specifies one content object or more generally one option in a set of choices.

{
  "type": "Selection",
  "bubbles": [ ... ]
}

See the Examples section below for examples.

Examples

Here are some examples of how messages are rendered in Facebook and how their JSON serialization looks like.

Note that the buttons need a template field, that corresponds to the templates in the Web App's message builder.

Bubbles with text and image

{
  "type": "Bubble",
  "template": "image",
  "attachments": [
    {
      "type": "Image",
      "path": "http://example.com/attack-on-titan.png"
    }
  ]
}

{
  "type": "Bubble",
  "template": "text",
  "attachments": [
    {
      "type": "Text",
      "text": "Wie findest du \"Attack on Titan\"?",
      "format": "PLAIN",
      "role": "NONE"
    }
  ]
}

Bubble with quick reply buttons

{
  "type": "Bubble",
  "template": "text",
  "attachments": [
    {
      "type": "Text",
      "text": "Wo soll unser kleiner netter Chat denn hinführen? Ich könnte dir zum Beispiel sagen, welche Filme du ganz schlecht finden wirst.\n\nAlso, was darf's sein?",
      "format": "PLAIN",
      "role": "NONE"
    },
    {
      "type": "QuickReplyButton",
      "text": {
         "type": "Text",
         "text": "Filmtipps",
         "format": "PLAIN",
         "role": "NONE"
       },
       "payload": {
           "game": "FilmTipps",
           "intent": "Start",
           "slots": []
       }
    },
    {
      "type": "QuickReplyButton",
      "text": {
        "type": "Text",
        "text": "Kinoprogramm/Tickets",
        "format": "PLAIN",
        "role": "NONE"
      },
      "payload": {
          "game": "KinoProgramm",
          "intent": "Start",
          "slots": []
      }
    },
    {
      "type": "QuickReplyButton",
      "text": {
        "type": "Text",
        "text": "Schlechte-Filme-Test",
        "format": "PLAIN",
        "role": "NONE"
      },
      "payload": {
          "game": "FilmTest",
          "intent": "Start",
          "slots": []
      }
    },
    {
      "type": "QuickReplyButton",
      "text": {
        "type": "Text",
        "text": "Einfach nur reden",
        "format": "PLAIN",
        "role": "NONE"
      },
      "payload": {
          "game": "SmallTalk",
          "intent": "EinfachNurReden",
          "slots": []
      }
    }
  ]
}

Card

{
  "type": "Card",
  "template": "card",
  "path": null,
  "bubbles": [
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "Image",
          "path": "http://example.com/3-tage-in-quiberon.png"
        },
        {
          "type": "Text",
          "text": "3 Tage in Quiberon",
          "format": "PLAIN",
          "role": "TITLE"
        },
        {
          "type": "Text",
          "text": "Filmstart: 12. 04. 2018",
          "format": "PLAIN",
          "role": "SUBTITLE"
        }
      ]
    },
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "Text",
          "text": "Genres",
          "format": "PLAIN",
          "role": "TITLE"
        },
        {
          "type": "Text",
          "text": "Drama, Drama, Drama, Drama",
          "format": "PLAIN",
          "role": "SUBTITLE"
        }
      ]
    },
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "Text",
          "text": "Inhalt",
          "format": "PLAIN",
          "role": "TITLE"
        },
        {
          "type": "Text",
          "text": "Im Jahr 1981 ist Romy Schneider (Marie Bäumer) eine der berühmtesten Schausp...",
          "format": "PLAIN",
          "role": "SUBTITLE"
        },
        {
          "type": "PostbackButton",
          "text": {
            "type": "Text",
            "text": "Mehr",
            "format": "PLAIN",
            "role": "NONE"
          },
          "payload": {
            "game": "FilmInfo",
            "intent": "Show_description",
            "slots": [{
              "label": "id=",
              "value": "47"
            }]
          }
        }
      ]
    },
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "Text",
          "text": "Besetzung",
          "format": "PLAIN",
          "role": "TITLE"
        },
        {
          "type": "Text",
          "text": "Birgit Minichmary, Chraly Hübner, Marie Bäumer, Robert Gwisdek,...",
          "format": "PLAIN",
          "role": "SUBTITLE"
        },
        {
          "type": "PostbackButton",
          "text": {
            "type": "Text",
            "text": "Alle",
            "format": "PLAIN",
            "role": "NONE"
          },
          "payload": {
            "game": "FilmInfo",
            "intent": "Show_cast",
            "slots": [{
              "label": "id=",
              "value": "47"
            }]
          }
        }
      ]
    },
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "PostbackButton",
          "text": {
            "type": "Text",
            "text": "Wo läuft der?",
            "format": "PLAIN",
            "role": "NONE"
          },
          "payload": {
            "game": "CinemaSearch",
            "intent": "FindCinema",
            "slots": [{
              "label": "film=",
              "value": "47"
            }]
          }
        }
      ]
    }
  ]
}

Selection

{
  "type": "Selection",
  "template": "gallery",
  "bubbles": [
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "Text",
          "text": "Weit. Die Geschichte von einem Weg um die Welt",
          "format": "PLAIN",
          "role": "TITLE"
        },
        {
          "type": "Image",
          "path": "http://example.com/weit.png"
        },
        {
          "type": "PostbackButton",
          "text": {
            "type": "Text",
            "text": "Infos zum Film",
            "format": "PLAIN",
            "role": "NONE"
          },
          "payload": {
            "game": "FilmInfo",
            "intent": "ShowFilm",
            "slots": [{
              "label": "id=",
              "value": "23"
            }]
          }
        },
        {
          "type": "LinkButton",
          "text": {
            "type": "Text",
            "text": "Spielzeiten/Tickets",
            "format": "PLAIN",
            "role": "NONE"
          },
          "path": "https://www.example.com/film/weit"
        },
        {
          "type": "LinkButton",
          "text": {
            "type": "Text",
            "text": "Trailer",
            "format": "PLAIN",
            "role": "NONE"
          },
          "path": "https://www.youtube.com/watch"
        }                
      ]
    },
    {
      "type": "Bubble",
      "attachments": [
        {
          "type": "Text",
          "text": "Noch nicht genug?",
          "format": "PLAIN",
          "role": "TITLE"
        },
        {
          "type": "Text",
          "text": "Es laufen noch 110 weitere Filme.",
          "format": "PLAIN",
          "role": "SUBTITLE"
        },
        {
          "type": "PostbackButton",
          "text": {
            "type": "Text",
            "text": "Zeig an",
            "format": "PLAIN",
            "role": "NONE"
          },
          "payload": {
              "game": "KinoProgramm",
              "intent": "More",
              "slots": []
          }
        }                      
      ]
    }
  ]
}