HTTP Requests

Making HTTP requests as part of a bot's response is incredibly simple. Use a $ to specify making a request before responding. These are best illustrated through examples. The following syntax is best suited for handling responses that are returned as JSON data.

We have deprecated usage of the old-school ^httpGetJSONValue() and ^httpPost() shortcodes, we encourage all bot creators to move to using $ in their scripts.

GET Requests

Say you had an API at http://myapi.com/weather/<zipcode> that returned the following JSON data object when passed a zip code:

{
  "forecast": {
    "temp_low": "56 degrees",
    "temp_high": "78 degrees"
  }
}

To use the data from this API in a bot's response, you could write something like:

+ weather *
$ GET http://myapi.com/weather/<star>
- In <star>, looks like we have a high of ${{forecast.temp_high}} and a low of ${{forecast.temp_low}}.

Adding this line:

$ GET http://myapi.com/weather/<star>

tells Dexter to make an API call after receiving the incoming message but before responding. And any instances of ${{data.field.to.retrieve}} found in the response will be substituted with the value found at that field.

If you wanted to make multiple GET requests, you can name each one:

+ weather *
$ GET:name1 http://myapi.com/weather/<star>
$ GET:name2 http://myapi.com/traffic/<star>
- In <star>, looks like we have a high of ${{name1.forecast.temp_high}} and a low of ${{name1.forecast.temp_low}}. The traffic report: ${{name2.data.traffic_report}}

You can also use ${{data}} substitution within conditionals and pass them into JavaScript macros for even more advanced data manipulation:

> object get_actual_temp javascript
return parseInt(args[0].split(' ')[0]);
< object
 
+ weather *
$ GET http://myapi.com/weather/<star>
* <call>get_actual_temp ${{forecast.temp_high}}</call> >= 85 => Wow it is hot!
* <call>get_actual_temp ${{forecast.temp_high}}</call> < 30 => Wow it is cold!
- ${{forecast.temp_high}} seems pretty pleasant.
We make use of mustache tags to parse values provided back in the JSON object.

This means that a mustache tag using array syntax, like so: `${{property[0].name}}` will not work. Instead, the accurate tag will be indexed like so: ${{property.0.name}}.

URI Encoding the <star> Variable

If you're looking to capture multiple words (separated by spaces) in your <star> wildcard, we recommend an additional step of encoding the <star> value in a macro first before passing it into your GET request:

> object encode_uri javascript
return encodeURIComponent(args[0])
< object
 
+ lookup *
$ GET http://api.myencyclopedia.com/lookup/<call>encode_uri <star></call>
- According to Encyclopedia Witannica,  means to ${{data.entry.text}}.

POST Requests

POST requests are equally as simple. Say you want to log the choice a user has selected to your own servers:

+ select *
$ POST http://myapi.com <star>
- Thanks for your response!

<star> in your $ POST request will be sent to your servers.

If you're looking to send JSON to your server, you'll need to specify the Content-Type header specifically.


Custom Headers & POSTing JSON

If you want to add custom headers to your request, you must specify a headers and body in the data you send. A case is trying to POST JSON to a server.

You can use custom headers in both GET and POST requests.

+ details on *
$ GET http://myapi.com {"headers":{"Content-Type":"application/json", "Authorization": "Bearer 1234567abcdef"}}
- ${{data.0.product.name}} is priced at ${{data.0.product.price}} USD. There are only ${{data.0.product.inventory}} units left.
 
+ select *
$ POST http://myapi.com {"headers":{"Signature":"abcdef"}, "body": {"selection":"<star>"}}
- Thanks for your response!

Mustache Tags & Macros

Saving Mustache Tags to Variables

You can easily save the values in the mustache tags to variable names.

+ bookmark *
$ GET http://myapi.com/items/<star>
- <set bookmarked_item=${{data.0.product.name}}> Great,  has been added to your bookmarks.
Using Response Data in Macros

You can also use mustache tags as arguments within Javascript macros.

+ save * to cart
$ GET http://myapi.com/items/<star>
- <call> add_to_cart ${{data.0.product.id}}</call> Great, <star> has been added to your cart.
 
> object add_to_cart javascript
    var cart = rs.getUservar(rs.currentUser(), 'cart'); // this is an array
    var new_item = args[0];
    var new_cart = cart.push(new_item)
    rs.setUservar(rs.currentUser(), 'cart', new_cart);
< object
Response Text

To get the full response body from a request, you can use the ${{__text}} mustache tag.

This will return the full stringifed JSON response body, which may be a little overwhelming to display as text to the end user.

This section has been updated with a new approach for extracting the full text response of a HTTP request using this.httpData. The original approach recommended setting the full json text to a user variable, i.e. <set json=${{__text}}>. This approach, while still valid, is not favored to the approach described below.

If you need to do further manipulations on the contents of this response body (in a way that cannot be accessed with mustache syntax alone), you can also access the full text response of the HTTP request in a macro by calling on this.httpData, like so:

+ number of users
$ GET http://myapi.com/users/
- There are currently <call>count_users</call> users.
 
> object count_users javascript
    return this.httpData['users'].length;
< object

To access the response body when you have made multiple GET requests, append the nickname of the request to __text, like this ${{data1.__text}}}.

Response Status Code

Similar, you can get the status code of the response by using the ${{__status}} mustache tag.

Combine the status code with conditionals to have the bot respond differently depending on the result of the request.

+ who is user id *
$ GET http://myapi.com/users/
* ${{__status}} == 404 => This user does not exist.
- The user with id  is named ${{users.0.name}}.

Advanced: Using Multiple Requests

Being able to have your bot make smart responses based on responses from API calls opens up opportunities for the kinds of useful conversations you can have.

Consider using the responses from one request as input for another request, like we do in the following example:

// in banks topic
+ find (bank|banks) in *
$ GET https://api.superbank.com/banks/search/location/<star>
* ${{__status}} != 200 => Are you sure this is a real zipcode? Please try again with a different zipcode.
- The closest location in the <star> zip code is:
^ * Branch ${{banks.0.id}} at ${{banks.0.location}}\n
^ Text back HOURS if you would like to know the hours at this location. <set branch_id=${{banks.0.id}}>
 
+ hours
$ GET https://api.superbank.com/banks/branches/<get branch_id>
* ${{__status}} != 200 => That's not a valid branch id! Please try again with a valid branch id.
- The hours for the Superbank branch <get branch_id> is ${{branch.hours}}. Thanks for using Superbank! If you have any more questions, type HELP at any point.
Want more examples? Check out our new Onboarding Bot tutorial for an example of an API request in action.

HTTP $yntax Errors

We surface the most common user errors that can occur when using HTTP $ syntax in the message shown to the user. We recommend testing your trigger in the phone tester to see if any of the following common errors surface:

Error: Invalid $ command, should be in the format [:] [{"body": ..., "headers": ...}].

Please provide a valid HTTP method. We support GET, POST, PUT, and DELETE.

Error: Invalid request body json for the $ command.

If you are providing a request body with your method and API url, make sure you provide a valid JSON body, per the example above. * Double check that each key in the object is bound by double quotations(""). * Verify if the json body has the appropriate number of opening and closing braces. (i.e. {}) * Header fields are included in your json body as values in the "headers" key, and any optional message body fields should be values in the "body" key. * Are there any spaces in the provided url? We split the url and body based on spaces, so if there is a space in the url, we recommend encoding the url first.

Why doesn't any text show up in lieu of my ${{mustache}} syntax?

Does your request return a valid response? If there is data being returned in the response body -- verify quickly with ${{text}} or ${{status}}, then double-check that the path in the ${{mustache}} syntax is a valid json path in the response body. If the path is invalid, we will replace the ${{mustache}} syntax with an empty string.