Skip to content

Instantly share code, notes, and snippets.

@picsoung
Last active April 2, 2020 06:11
Show Gist options
  • Save picsoung/a25b63464750fc6b06a80ade0a81430a to your computer and use it in GitHub Desktop.
Save picsoung/a25b63464750fc6b06a80ade0a81430a to your computer and use it in GitHub Desktop.
Articles posted on APItools.com blog
title description layout author gh-author date categories tags
First day with APItools (at BattleHack)
This weekend I attended BattleHack hackathon in San Francisco and I thought I could give APItools a try. Here are some thoughts and feedback about using APItools in hackathon conditions.
blog
Nicolas
picsoung
2014-04-02
blog
hackathons CORS

Published on 09 April 2014, by Nicolas Grenié

Nicolas Grenié is Hacker in Residence at 3scale and he's been using APItools internally for quite a few weeks already. Last weekend it was the first time APItools was used in a hackathon with the following results in Nicolas' team :)

Thank you Nicolas for the write up!

Earlier this week 3scale announced the launch of a new tool for API consumers: APItools. APItools enables developers to monitor and manage API traffic. The magic of it resides in "middleware" that are Lua script to help you modify inbound or outbound traffic.

This weekend I attended BattleHack hackathon in San Francisco and I thought I could give APItools a try. Here are some thoughts and feedback about using APItools in hackathon conditions.

Our project

With my teammate Thibaut we wanted to build a hack using LeapMotion to create a kiosk for tourists. The kiosk could be at an airport or shopping malls and should help tourists (or anybody) find what is happening around.

In terms of technology we wanted to build a hack using Javascript without any backend, everything in the client. We wil get local tweets using Twitter API, local photos from Instagram API and local events using SeatGeek API.

How did we use APItools

APItools lets you create a service for each API you are going to use.

![Overview of services in APItools](https://www.evernote.com/shard/s37/sh/b977cf39-f5d2-447d-ac7e-791d58471ad7/faacc5eccea02cc4b904c3faed2a7330/deep/0/APItools-Traffic-Monitor.png =500x)

So we created one for each, Twitter, Instagram and Seatgeek.

In each service you will define what is the API backend you want to hit (Twitter : *http://api.twitter.com/1.1/). APItools will then give you a url to hit this API instead of hitting it directly. It acts as a proxy.

So, In your app instead of calling http://api.twitter.com/1.1/search/tweets.json to search on tweets you will call http://{id}.my.apitools.com/search/tweets.json

As we were building a 100% client-based application we used jQuery $.ajax method to call APIs, and we faces what most of the people are facing today the classic No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

Using APItools helped us solved this problem.

Here is how we did it

var api_root = "http://{id}.my.apitools.com/";
var api_url = api_root+"trends/place.json?id=2487956" //Trending topics in San Francisco
$.ajax({
       type: "GET",
       url: api_url,
       dataType: "jsonp",
       success: function (response, status, xhr) {
            console.log(response[0].trends);
       },
       error: function (xhr, err) {
         console.log(xhr);
         console.log(xhr.statusText);
       }
});

If you are familiar with Twitter API you know that requests has to be authenticated with Authorization Bearer header. You don't see it in the above code, it's normal, we used APItools pipeline tool to pass it. Like this all the requests we make to our APItools url are already authenticate to hit twitter API.

![interface of APItools pipeline](https://www.evernote.com/shard/s37/sh/6767074d-c55e-4977-923d-dad93e029c1b/d049c900ecb66b6f3f88101144b8b704/deep/0/APItools-Traffic-Monitor.png =500x)

![edition of a middleware](https://www.evernote.com/shard/s37/sh/9a072308-9543-4851-9e76-3c168376abd9/12bc0ddb42533c3c99731756f337509b/deep/0/APItools-Traffic-Monitor.png =500x)

Once you make calls in your application you can track them using Traces in APItools, you will see which one are passing and which one are failing, as well as all the information of the call (Headers, User-Agent,…).

![All traces](https://www.evernote.com/shard/s37/sh/d6eb93c9-e29c-45dd-99e5-0490bc7313a6/fa074f6f2a20e37c22f468f933bbfbb9/deep/0/APItools-Traffic-Monitor.png =500x)

![Info on request](https://www.evernote.com/shard/s37/sh/b2c9f21c-dfec-4cde-98ab-5cdc453508aa/72478408320230dcd2829384661f5152/deep/0/APItools-Traffic-Monitor.png =500x)

If you are into analytics you can also have graphs to visualize your calls easily.

In the end APItools helped us during the development phase when we were trying calls to see which one were failing and why. It also helped us when we reach the API limit on a twitter endpoint, we saw it immediately in Traces. It also very useful when you develop apps with no backend and you want to bypass CORS error.

I am looking forward using APItools at other hackathons and I encourage hackers to give it a try,

Disclosure I am a Developer Evangelist at 3scale, company behind APItools

layout title author description gh-author categories tags
blog
Develop Your First Yo App With APItools
Nicolas
I am pretty sure you already heard of Yo, the new fad from Silicon Valley. It lets you send a Yo to your friends, it's that simple. Recently, their were in the headlines for raising over $1M with this simple idea. But more thant spamming your friends with context-less Yos it could be really useful for notifications. People have built apps to get Yos when there was a goal during World Cup or to tell you when your server is down, possibilities are endless.
picsoung
blog
yo middleware

I am pretty sure you've already heard of Yo, the new fad from Silicon Valley. It lets you send Yoes to your friends, it's that simple. Recently, their were in the headlines for raising over $1M with this simple idea. But more than spamming your friends with context-less Yoes it could be really useful for notifications. People have built apps to get Yoes when a goal was scored during the World Cup or to send warnings when a server is down. Possibilities are endless.

They just released their API, and today I wanted to show you how one can benefit from using APItools and the Yo API.

In this tutorial, we are going to develop a simple app where people can subscribe to your Yo notifications. This app has the ability of sending indivual Yoes or group messages to all your subscribers.

Yo API let's you do all of these things:

  • Receiving Yoes
  • Sending a Yo to a user
  • Sending a Yo to all your subscribers

To follow this tutorial you'll need:

The App

The code of the app is pretty simple HTML with jQuery.

<html>
<head>
	<title>Yo me that</title>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>

Yo username <input type="text" id ="yoUsername">
<button id="yoOneButton">Yo ONE</button>
<button id="yoAllButton">Yo ALL</button>
</body>
</html>

and some Javascript to do action when buttons are clicked

<script type="text/javascript">

var apiURL = YoUR_APITOOLSERVICE_URL //will change later;

$("#yoOneButton").click(function(){
    //pass the username typed in input field
	yoOne($("#yoUsername").val());
});

$("#yoAllButton").click(function(){
	yoAll();
});

var yoOne = function(yoUsername){
	var url = apiURL;
	url += "yo/";
	$.post(url, {username:yoUsername})
	.done(function( data ) {
	  console.log(data);
	})
	.fail(function(xhr, textStatus, errorThrown) {
      console.log("Error",xhr.responseText);
	});
}

var yoAll =function(){
	var url = apiURL;
	url += "yoall/";

	$.post(url)
	.done(function( data ) {
	  console.log(data);
	})
	.fail(function(xhr, textStatus, errorThrown) {
      console.log("Error",xhr.responseText);
	});
}
</script>

It's pretty straighforward. And no backend is needed :)

Setting Up APItools

APItools acts as a proxy between your app and the API you are hitting. It's a great tool when you need to debug your API calls.

Setting up the Yo API on APItools is simple:

Create a service in APItools and in API URL field type http://api.justyo.co/

APItools Service Creation

Once this is done, APItools will give you an URL that looks like this http://TOKEN.my.apitools.com Instead of calling the Yo API directly, we're going to hit this URL.

Now go to your code and replace the placeholder YoUR_APITOOLSERVICE_URL by this new URL.

To test that everything works well, try to call the APItools service URL in a browser. You should see the call in the traces tab.

Setting Up Yo On APItools

When someone subscribes (or sends a Yo) to your notifications you can hit a callback URL. To change this call back URL, go to your Yo developer dashboard. You should see the list of developer accounts you created. On the one of your choice, change the callback URL for the APItools service URL and click the Update Callback URL button.

Yo Configuration

To test this, just send a Yo to your developer account. You should see the trace in your APItools traces tab.

Test trace seen from APItools

You can send individual or group Yoes using the tools available in Yo dashboard.

Making The App Work

Everything is in place but we need to add some logic to make the app work. When you hit a button in the app it makes a post request to APItools on /yo/ or /yoall/. Those calls are redirected to the Yo API.

If you try now, they will fail. And the first failure is the very common but annoying X-Origin CORS error. It does not allow you to call the API from the client, with no server. We can solve that with APItools :)

  1. Go on your APItools dashboard
  2. Click on Pipeline
  3. Add CORS header middleware from the list on the right sidebar

If you open the middleware you just added, you will see two lines of code that properly change the headers to solve the CORS error.

If you run the app again, you won't see the CORS error again. But our calls are still not authenticated to hit Yo API. Looking at the Yo API documentation you just need to pass the API token api_token. The API token could be found on Yo developer dashboard.

To do it in APItools

  1. Add a new middleware
  2. Add headers to pass JSON data request.headers['Content-Type']='application/json'
  3. Add the apiToken variable like that local apiToken = 'YO_API_TOKEN'
  4. Pass the token to the request request.body ='{"api_token":"'..apiToken..'"}'

Your middleware should look like this

return function(request, next_middleware)
  request.headers['Content-Type']='application/json
  local apiToken = 'YO_API_TOKEN'
  request.body ='{"api_token":"'..apiToken..'"}'
  return next_middleware()
end

Running your app, the "Yo all" button should work and all your subscribers should receive a Yo.

You could modify this middleware, for example, to also send a tweet to a user.

On the top add the split function

function split(s, delimiter)
    result = {}
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match)
    end
    return result
end

It hacks like typical split function in other languages.

In the app we are passing the username in the body, to retrieve it add those lines to your middleware

local body = request.body
local yoUsername = split(body,'=')[2]

and change the request.body =... to request.body = '{"username":"'.. string.upper(yoUsername) .. '","api_token":"'..apiToken..'"}'

The username needs to be uppercase. Your middleware now looks like this

return function(request, next_middleware)
  request.headers['Content-Type']='application/json
  local apiToken = 'YO_API_TOKEN'
  local body = request.body
  local yoUsername = split(body,'=')[2]
  request.body = '{"username":"'.. string.upper(yoUsername) .. '","api_token":"'..apiToken..'"}'
  return next_middleware()
end

You can now test it in your app. Check also the APItools traces to see that everything went well.

With the changes we've done the Yo all call is now broken. With one middleware we can apply different logic depending on the endpoint called.

Your final middleware should look like this

return function(request, next_middleware)
  local response
  local apiToken = 'YO_API_TOKEN'
  request.headers['Content-Type']='application/json'

  -- endpoint to send an individual yo is called
  if request.uri == '/yo/' then
    local body = request.body

    local yoUsername = split(body,'=')[2]
    console.log(yoUsername)

    request.body = '{"username":"'.. string.upper(yoUsername) .. '","api_token":"'..apiToken..'"}'

  -- endpoint to Yo all is called
	elseif request.uri =='/yoall/' then

      request.body ='{"api_token":"'..apiToken..'"}'

  -- callback url is called
  elseif request.uri == '/' then
    send.mail('[email protected]','New Yo subscriber', 'NEW Yo SUBSCRIBER '..request.args.username)
    send.notification({msg="new subscriber " .. request.args.username, level='info'})
  end
    console.log(request.body)

  return next_middleware()
end

And voilà... You finished your first Yo app, with no server :)

I hope you had a good time hacking with us! Can't wait to see what you come up with!

APItools and 3scale have partnered with Yo for their next hackathon in New York City on July 26th.

Come hack with Yo API as well as with some 3scale clients.

Here are couple of ideas of hacks to build with:

  • FlightStats - An API for everything about flights,airports, or airlines. Ex: Could send a Yo when a flight has arrived.
  • Evercam - An API for connected cameras. Ex: Send a Yo to a webcam to take a picture (photo booth)
  • Nutritionix - Nutrition information. Ex: Track your diet with Yo
  • Bitcasa - Storage API. Ex: Receive Yo when file change
  • WeatherUnlocked - Weather API. Ex: A morning Yo with today's weather.

Hope to see you there. Happy Hacking !

layout title author description gh-author categories tags
blog
Playing With Burning Man's API
Nicolas
Is that time of the year again, everyone’s excited about Burning Man but, did you know that they do have an API? Even if you’re planning on disconnecting from technology (...)
picsoung
blog
burning-man middleware

Is that time of the year again, everyone’s excited about Burning Man but, did you know that they do have an API? Even if you’re planning on disconnecting from technology while you’re there, there’s no reason why you wouldn’t use it beforehand to get ready for it. I had some fun building a quick and dirty app to tell me all the parties going on at Burning Man this year.

My Burning Man App

This simple app retrieves activities by type and time so you can pick and choose and plan a bit ahead. We know, we know… you want to play it by ear, just let go and stop where you feel like doing so when you're there.

But this may also be a good excuse to hack something with the Burning Man API ;-)

Using APItools To Reorganize The Content

I used APItools to modify the data exposed by the Burning Man API in three different ways:

  1. Split one same event held at different times into different events.
  2. Limit the amount of information retreived (since I didn’t need it all).
  3. Organize the content by category.

Let's see it step by step.

This is how my middleware to split one same event held at different times into different events looks like. It also reduces events and retrieves only the information needed (description, start time, end time, title, id, url, location, and category):

return function(request, next_middleware)

  local response = next_middleware()
  local events = json.decode(response.body)
  local newresponse ={}

  for i=1,#events do
    local currentEvent = events[i];

    for j=1,#currentEvent.occurrence_set do
      table.insert(newresponse,{
        title       = currentEvent.title,
        desc        = currentEvent.description,
        id          = currentEvent.id,
        host        = currentEvent.hosted_by_camp,
        url         = currentEvent.url,
        location    = currentEvent.other_location,
        category    = currentEvent.event_type.abbr,
        start_time  = currentEvent.occurrence_set[j].start_time,
        end_time    = currentEvent.occurrence_set[j].end_time
      })
    end
  end

  console.log("nb events ", tostring(#events));
  console.log("nb total ", tostring(#newresponse));

  response.body = json.encode(newresponse)

  return response
end

This is how my middleware to organize the content by category looks like:

return function(request, next_middleware)

  local response = next_middleware()
  local events = json.decode(response.body)
  local parties = {} -- categorized by 'prty' in Burning Man API
  -- repeat for each category of events

  local dataInfo ={}

  for i=1,#events do
    local currentEvent = events[i]

    if (currentEvent.category=='prty') then
      table.insert(parties,currentEvent)
    elseif(currentEvent.category=='work') then
      table.insert(workshops,currentEvent)
    -- repeat for each category of events
    end
  end

  dataInfo.nb_events = #events
  dataInfo.nb_parties = #parties
  -- repeat for each category of events


  console.log("nb events ", tostring(#events));
  local newresponse ={}
  newresponse.parties = parties
  newresponse.datainfo = dataInfo
  -- repeat for each category of events

  response.body = json.encode(newresponse)

  return response
end

And this is the result of calling the same API applying the mentioned modifications:

{
	"parties": [],
	"cares": [],
	"uncategorized": [],
	"workshops": [],
	"kids": [],
	"performances": [],
	"parades":[],
	"adults":[],
	"food": [],
	"games": [],
	"fire": [],
	"ceremonies": [],
	"datainfo": {}
}

Inside each array you can find events described like this:

{
	"desc": "??? what is ??? what ever you contribute you will receive. it's a place where questions are answered and answers are given. In a caravan full of wonder the possibilities are endless. Who and what the hell is going to happen? Look for ? marks way behind the temple.",
	"end_time": "2014-08-30 01:15:00",
	"title": "???",
	"id": 11517,
	"url": "",
	"location": "",
	"category": "prty",
	"start_time": "2014-08-29 22:00:00"
}

With these transformations, I am able not only to keep my app’s code clean but also to make it a bit faster by optimizing the requests made to Burning Man’s API.

Like it? Give it a swirl, request an invite to APItools Beta here.

layout title author description gh-author categories tags
blog
Creating Price Alerts With The Uber API
Nicolas
Just last week Uber launched their API. It allows searches, retrieval of user ride information, and price estimation calculation. The Uber API still doesn’t allow third parties to request an Uber car, but some interesting apps can already be built.
picsoung
blog
uber middleware

Introducing Traffic Monitor API

Just a couple of days ago Uber launched their API. It allows searches, retrieval of user ride information, and price estimation calculation. The [Uber API](https://developer.uber.com/'Uber API') still doesn’t allow third parties to request an Uber car, but some interesting apps can already be built.

Access for your apps can be requested here: https://developer.uber.com/ and here’s a link to its documentation: https://developer.uber.com/v1/endpoints/

Adding New Possibilities To The Uber API

It’s not news that Uber prices may vary depending on day times and demand. So we figured it’d be cool to have a way to get an alert when a trip price drops to the price you’re willing to pay.

We think this is a nice addition to the Uber API. And it may be useful both for end users – no interface needed, just receive an email when a fare suits your pocket :) – and for app developers to enhance their apps.

How To

To create a price alert, the first thing you need to do is to get the estimated price of a trip so you can compare with what the user is willing to pay.

I used APItools middleware for that, and also to analyze the response and compare it to what the user is willing to pay.

To get the estimate, you just need to pass the coordinates of the trip - both start and end points - to obtain the price estimate for each different type of Uber car available:

{
   "prices": [
       {
           "localized_display_name": "uberX",
           "low_estimate": "29",
           "display_name": "uberX",
           "product_id": "a1111c8c-c720-46c3-8534-2fcdd730040d",
           "surge_multiplier": 1,
           "estimate": "$29-38",
           "high_estimate": "38",
           "currency_code": "USD"
       },
       {
           "localized_display_name": "uberXL",
           "low_estimate": "49",
           "display_name": "uberXL",
           "product_id": "821415d8-3bd5-4e27-9604-194e4359a449",
           "surge_multiplier": 1,
           "estimate": "$49-63",
           "high_estimate": "63",
           "currency_code": "USD"
       },
       {
           "localized_display_name": "UberBLACK",
           "low_estimate": "76",
           "display_name": "UberBLACK",
           "product_id": "d4abaae7-f4d6-4152-91cc-77523e8165a4",
           "surge_multiplier": 1,
           "estimate": "$76-98",
           "high_estimate": "98",
           "currency_code": "USD"
       },
       {
           "localized_display_name": "UberSUV",
           "low_estimate": "90",
           "display_name": "UberSUV",
           "product_id": "8920cb5e-51a4-4fa4-acdf-dd86c5e18ae0",
           "surge_multiplier": 1,
           "estimate": "$90-114",
           "high_estimate": "114",
           "currency_code": "USD"
       }
   ]
}

Then I built a second middleware option to compare the price estimate with what the user is willing to pay, and to send an email alert if there’s a match. I had to take into account that more than one type of Uber car may meet the max price, in which case the user would only receive one email with all different types of Uber cars available.

return function(request, next_middleware)
  local max_price = 20
  local my_address = "[email protected]"
  
  local response = next_middleware()
  
  local result = json.decode(response.body)
  local prices = result.prices
  
  local message= ""
  local nb_results = 0
  
  for _,price in ipairs(prices) do
    if(max_price > tonumber(price.low_estimate)) then      
      if (nb_results ==0) then -- first result
        message = "You can go from " ..bucket.service.get("start_name").. " to "..bucket.service.get("end_name").. " for less than "..max_price..price.currency_code.. " on ".. price.display_name
      end 
     
      nb_results = nb_results +1
      if(nb_results >1) then
         message= message .. " OR for less than "..max_price..price.currency_code.. " on ".. price.display_name
      end
    end 
  end
  
  
 if (nb_results > 0) then
    send.mail(my_address,"Price alert on Uber",message)
 end
 
  -- deal with response
  return next_middleware()
end

Try it!

Try this and let us know what you think. Are you building an app with the Uber API? What other ideas have you come up with? We’d love to know!

APItools is in private beta, request your invitation here https://www.apitools.com

layout title author description gh-author categories tags
blog
A Slack Bot Without A Server
Nicolas
In the old days of the Internet there was IRC. IRC was a great chat system with channels and servers for every small community around the world. I've spent hours on it as a kid. But the thing that fascinated me the most on it were the bots people have created...
picsoung
blog
middleware, slack, bots, webhooks

In the old days of the Internet there was the IRC. IRC was a great chat system with channels and servers for every small community around the world. I've spent hours on it as a kid. But the thing that fascinated me the most about it were the bots people created. You would enter into a room and would be greeted by a bot, or play triva games with a bot... Silly bots, but fun. I looked many times at documentation to find out how to develop a bot. At that time, you would need serious knowledge of C, C++ or Delphi (yep...). I never built a bot...

Until today! Now you have the power to create a bot of your own with Slack. Slack is a platform for team communication based on chat. The power of Slack lays in it's openess thanks to its API.

In this tutorial I want to show you how you to create your first bot using APItools in a few lines of code, without a server.

Pre-requisites For This Tutorial

  1. A Slack account
  2. An APItools account
  3. Fun :)

The Bot

We're going to built a simple bot to get a cat emoji anytime someone says cat in a Slack channel. This is a silly example but we'll go through the basics to create any type of bot, for example, one that'd retrieve the status of a flight.

Example of the bot

The Principle

Every time the word cat is mentioned in a channel, the bot will call an APItools URL using a webhook. Using APItools middleware we will then send a message back to the Slack channel.

This could also be useful, for example, for a #newbies channel to, every time a 'company word' is mentioned (because, let's be honest, most companies develop their own lingo eventually), a definition of that word is shown.

Configuring Slack

You can hook many external services into Slack, some are already made and are very easy to install. You can find them in Slack's integrations page.

https://YOURORG.slack.com/services/new

In our case, we are going to use the "Outgoing WebHooks". Click on Add buttton to start.

Add Outgoing WebHook

In the next step, select the channel of your organization you want the bot to be active in. And the triggered words. Triggered words are the words that will make the bot react. In our case cat.

Go to the bottom of the page and give it a cute name as well as an avatar. We will come back later to this page to fill the other fields.

Conf bot

Configuring APItools

Step 1
  • Create a new traffic monitor
  • Create a new service. Use any API endpoint, for example the Echo API. https://echo-api.herokuapp.com
  • Copy your APItools URL, it should look like this https://SOMETHING.my.apitools.com/
  • Paste your APItools URL in the URL(s) field in your slack integration page https://SOMETHING.my.apitools.com/hook. This way Slack will be calling the webhook on that URL.

Test it: post a message containing cat in your channel on Slack.

If everything went well you should see a POST request on APItools, in the Traces tab. Look at the body of the request to see all the info that Slack is sending: in which channel the message was posted by whom and at what time.

Now we will use these data to answer with the bot.

Step 2

Next we will create a middleware module on APItools > Pipeline to handle the request sent by Slack.

-- fct to split a string by a delimeter
local function split(s, delimiter)
  local result = {}
  for match in (s..delimiter):gmatch("(.-)"..delimiter) do
    table.insert(result, match)
  end
  return result
end

-- convert hex to char
local hex_to_char = function(x)
  return string.char(tonumber(x, 16))
end

-- unespace special chars in URL
local unescape = function(url)
  return url:gsub("%%(%x%x)", hex_to_char)
end

return function(request, next_middleware)
  local response = next_middleware()
  local hookURL = "YOUR_HOOK_URL"
  
  if(request.uri == '/hook') then
    local params = split(request.body,'&')
    local decoded_params = {}
    
    -- turn urlencoded string into an object
    for i=1,#params do
      local p = split(params[i],'=')
      decoded_params[p[1]] = p[2]
    end
    msg = 'Hey '..decoded_params.user_name..' I heard you like cats '..'\xF0\x9F\x98\xB8'
    local r = http.json.post(hookURL,'{"text": "'..msg..'","channel":"#'.. decoded_params.channel_name..'","icon_emoji":":cat:"}')
  end
  return response
end

APItools middleware are written in Lua. Lua is really fast, and easy to learn. You can find all the middleware Lua API documentation here.

In the code above you will need to replace YOUR_HOOK_URL placeholder with an URL given by Slack so we can post in our channels. To get this URL we'll create an Incoming Webhook the same way we previously did. Again, you can customize your bot. Retrieve the Webhook URL and paste it in your middleware.

Let's get deeper in the code:

if(request.uri == '/hook') then makes sure we only execute the following code when the /hook endpoint is called.

The following function transforms the body of the request sent by Slack from an urlencoded object to a lua object.

for i=1,#params do
   local p = split(params[i],'=')
   decoded_params[p[1]] = p[2]
 end

This is how it looks before the transformation...

token=TOKEN&team_id=TEEAM_ID&team_domain=3scale&service_id=SERVICE_ID&channel_id=CHANNEL_ID&channel_name=pandas&timestamp=1420549633.000240&user_id=USER_ID&user_name=picsoung&text=cat+cat+cat&trigger_word=cat

... and after:

{
  channel_id = "CHANNEL_ID",
  channel_name = "pandas",
  service_id = "SERVICE_ID",
  team_domain = "3scale",
  team_id = "TEAM_ID",
  text = "cat+cat+cat",
  timestamp = "1420549700.000244",
  token = "TOKEN",
  trigger_word = "cat",
  user_id = "USER_ID",
  user_name = "picsoung"
}

local r = http.json.post(hookURL,'{"text": "'..msg..'","channel":"#'.. decoded_params.channel_name..'","icon_emoji":":cat:"}') makes a POST request containing the message to the channel, it also changes the icon of the bot with the cat emoji.

Step 3

Save your middleware and test your whole integration :)

Post a message containing cat and you should receive an answer from your bot.

Adding Complexity

If you followed till here, you'll have your bot working already. Congratulations! But that's not all, we could still add some complexity and do other fun stuff. For example, wouldn't it be cool if the bot would send back random cat GIFs? Let's do it then.

Complex Bot

To achieve that I am going to use the awesome Giphy API. And I am also going to create a new service on APItools to handle the requests to Giphy. Copy your APItools URL, you're going to need it in a second.

In our previous middleware (Step 2) change the code to add a random gif. After msg = 'Hey... you will need to add:

giphy_req = http.get('https://YOUR-APITOOLS-GIPHY-URL/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=cat')
image_url = json.decode(giphy_req.body).data.image_url 
msg = msg .. image_url

The code it's pretty straightforward: we are making a GET request to Giphy API throught an APItools service to get a random gif tagged as cat.

We are also extracting the GIF URL from the response and appending it to the message. By default, Slack recognizes image URLs and displays them directly in the body.

And that gives you a great example of combining APIs into your bot!

What Slack bot are you going to built now that you know how easy it is to create one? I'm already building some, more on that soon. Stay tuned!

layout title author description gh-author categories
blog
Slack + Uber: Get Uber Estimation Prices Before You Leave The Office
Nicolas
Since Uber launched its API back in August, I’ve been playing with it to built an app to track Uber price surges and most recently, a Slack bot to get Uber price estimations from one distance to another. Since we use Slack as our main internal communication tool at 3scale (...)
picsoung
uber bots slack

Since Uber launched its API back in August, I’ve been playing with it to built an app to track Uber price surges and most recently, a Slack bot to get Uber price estimations from one distance to another. Since we use Slack as our main internal communication tool at 3scale, it comes in very handy to have this bot available when you need an Uber to go to a meeting, an event, or just to get back home.

Pre-requisites

To build this bot I used

You can read more about creating bots for Slack with APItools here.

Installation Process

The code and the step by step installation process can be found on Github: https://github.com/picsoung/uberSlackBot

And this is basically how it works:

Schema Uber Bot for Slack

I created one monitor and 3 different services on APItools:

  • One to receive the webhook data from Slack. This part determines if the request is well formatted, and if not, it sends a message to the Slack channel giving feedback.
  • A second one to convert street names into latitude and longitude calling the Google API.
  • And a third one to call the Uber API, and get estimate price, then send the result back to Slack.

Feedback

I’d love to hear your thoughts about this, especially if you decide to implement it yourself. And if you have questions, please shoot me an email.

I hope you have fun with this!

Update: Thank you for adding this bot to the Slack Community-built Integrations page (Lua section): https://api.slack.com/community

layout title author description gh-author categories tags
blog
Hacking APItools during the 3scale Internal Hackathon
Nicolas
Last week, we had our first ever internal hackathon at 3scale. During two days we were able to take a break from our normal work life and start hacking on all the crazy ideas we had around our products (3scale, APItools or APIs.io).
picsoung
blog
hackathon middleware

Last week, we had our first ever internal hackathon at 3scale. During two days we were able to take a break from our normal work life and start hacking on all the crazy ideas we had around our products (3scale, APItools or APIs.io).

As I've been playing a lot lately with APItools I surely wanted to build something on top of it. My great colleague Didier, wanted to hack the Hue lights from his flat. We agreed there was something to do there, connecting APItools and Hue lights.

Geeks and Engineers in general love analytics and dashboards. It's a great way for them to understand and visualize what's hapenning in the complex systems they are building. Visual feedback is really appreciated in a workspace, it informs you without disturbing you with emails, or pop-up notifications. It's a quiet notification.

And that's how we came up with our hack idea, we wanted to build a system to monitor the health of your APItools service. It could be useful if you are using APItools as a layer to distribute your own API or if your application is using APIs through APItools. And we would give a visual feedback using the Hue lights, with the basic light code of a stoplight, green, orange, red.

While we were drawing ideas on a whiteboard we realized that the full potential of this idea was it's modularity. Why only provide Hue light feedback when we can also send text, emails, play a song, or send data to an Arduino?

We would provide a solution for hackers to add directly from a nice UI, middleware to their APItools service. Kind of a "one-click deploy" middleware service.

We decided to built a "one-click deploy" middleware service.

In an other article we will give deeper explanations on how we have achieved this using APItools' API.

Today wanted to share our story plugging our Hue Lights into APItools.

Didier's Story: Intro

As it's been told before, enthusiastic geeks wanted to somehow reveal the status of an API using HUE lights. This was accomplished in the end with a bit of hacking skills, great HUE API docs and the powerful APItools

HUE API, locally all run smoothly

Following the HUE API docs, it's really stright forward to control your lights with their API within your local WiFi network, basically you follow these 3 steps:

  • Get your HUE bridge IP (you can retrieve this and more info about your bridge with their broker service )
  • Authorize a new user
  • Start having fun controlling your lights with API calls! Yay!

However, we wanted to remote control our HUE bridge from our APItools Middleware, meaning not from our WiFi network but making calls from the vast Internet! And then things got a bit tricky...

Controlling over Das Internet

To address your bridge over the internet, first you have to get an account from Meet HUE, then you can use their web app and if you want to do it from your app, AFAIK, there's no way to automatically authenticate with your account and make calls to your bridge. So now it's when you set hack_mode: true.

A token, the holy token, that's what we need

We couldn't find a way to get it with an API call and at the time of this blog post, there's no documentation about it. But that didn't stop us, we continued with our hacking quest! What we had to do was:

  1. From your browser www.meethue.com/en-US/api/gettoken?devicename=<APP_NAME>&appid=hueapp&deviceid=<BRIDGE_ID>
  • Where APP_NAME is whatever your hacking project, app, pet, etc name is and BRIDGE_ID, as mentioned before, you can get it from their broker service.
  1. After accepting the device pairing, go to "Settings" and then "My apps". You will find a de-activate link for your HUE App, inspect the element and get the tokenId param.

Making tokenized calls

Now that we got the token, we can make calls to the API like this:

  • URL: https://www.meethue.com/api/sendmessage
  • Method: POST (always)
  • URL Params: token=<TOKEN> (the holy one)
  • Request headers content-type=application/x-www-form-urlencoded
  • body clipmessage={ bridgeId: "<BRIDGE_ID>", clipCommand: { url: "/api/0/<ENDPOINT>", method: "<METHOD>", body: <JSON_BODY> } }
    • BRIDGE_ID is the same one you obtained earlier
    • ENDPOINT are the API endpoints listed in the official API, but we replaced the username by 0
    • METHOD the same methods as documented in the official API
    • JSON_BODY the command body, for example { "on": true }

When our request was successfully made, the response will look like this {"code": 200, "message": "ok", "result": "ok"} Either way, it will display any eventual error:{"code": 109, "message": "I don't know that token.", "result": "error"}

Shooting calls from a Middleware

Now that we are succesfully making calls to the API, we are ready to code our Middleware! As you might already know, Middlewares are written in LUA, and that's good! it's super easy following the Middleware LUA API docs and if you never coded LUA before, learn it in 15 minutes.

Then you will be able to craft something like this:

  local hue_url = "https://www.meethue.com/api/sendmessage"
  local hue_token = "YoUrHoLymosTPReCIOUSToKENThatYOUProUDlYHaCKEdBeFORe"
  local hue_params = "?token=" .. hue_token
  local hue_bridge_id = "y0urbr1dg31d"
  local hue_status
  
  if error_codes[value] == "success" then
    hue_status =  25000 -- greenish
  elseif error_codes[value] == "warning" then
    hue_status =  10000 -- orange
  else
    hue_status =  0 -- red
  end
  
  body = json.encode({
          bridgeId= hue_bridge_id,
          clipCommand= {
            url= "/api/0/groups/0/action",
            method= "PUT",
            body= {
              on= true,
              hue= hue_status
            }
          }
        })
  
  hue_response = http.post(
                  hue_url .. hue_params,
                  "clipmessage=" .. body,
                  {
                    headers = {
                      ['Content-Type'] = 'application/x-www-form-urlencoded'
                    }
                  }
                )
  
  console.log("hue_response", hue_response)

Nice, isn't it!? So, this handcrafted code could be explain as it follows:

  1. We set our credentials and parameters to succesfully make use of our bridge via HUE API,
  2. Then set our hue_status variable with the HUE colour code we magically obtain from error_code[value] (this will be explain in a next blog post, but for now and in order to you be safe in the knowledge that you're not missing anything, there we store either "success", "warning" and "error" depending on the status code made in the last X minutes calls to the API we want to use.),
  3. The body we will send is constructed and...
  4. ... we finally made the call and log the response

Wrapping up

As you can tell by now, we had a really fun time hacking HUE lights with APItools. This digest version of our story doesn't say in how many different ways we use APItools, like in debugging our calls to the API we wanted to monitor, the HUE API itself and then our Middleware calls to the HUE API, meaning debugging APItools with APItools (YEAH! INCEPTION!). Now this proof of concept is really valuable since the possibilities of using APItools with HUE lights are endless and still they could been associated with other APIs/Gadgets/etc.

APItools inside APItools

layout title author description gh-author categories tags
blog
A Serverless Voting System Built Using Twilio, Firebase And APItools
Nicolas
Earlier this year I shared my experience creating a bot for Slack without a server. After that, I kept on experimenting using APItools to build apps and get them quickly up and running without much hassle (which, by the way, is a pretty handy skill to have at a hackathon). I’ve found it very easy to combine...
picsoung
blog
hackathon middleware mashups

Earlier this year I shared my experience creating a bot for Slack without a server. After that, I kept on experimenting using APItools to build apps and get them quickly up and running without much hassle (which, by the way, is a pretty handy skill to have at a hackathon). I’ve found it very easy to combine APItools with other services and APIs so I don’t need server.

My most recent project is a very simple - but certainly useful - voting system that I got working in just a few hours. It combines:

  • Twilio, a powerful API for text messages
  • Firebase, a great way to store and sync data in real time
  • APItools, which handles the communication between Twilio and Firebase without the need of a server.

Pre-requisites

For this project, you will need:

  • A Twilio phone number.
  • A Firebase account.
  • An APItools account, to handle the communication between Twilio and Firebase without the need of a server.

How Does It Work?

Your Twilio phone number will determine where your voting system can be used from. In my case, I have two numbers and people can vote both from the US and from Spain. Twilio has phone numbers available in a lot of countries, at least you’ll need to have one in the country you’re at right now (so you can test it!).

Imagine we want to use this at a hackathon for people to vote for the best project. People would just send a text message to your Twilio phone number indicating the name of the project (one word), and thumbs up or thumbs down emoji.

The request would be sent from Twilio to APItools, APItools would process the information (is it a positive or a negative vote?), and send to Firebase to show in our real-time dashboard.

And that’s it. Keep reading to learn how to built a real-time voting system step by step.

A Real Time Voting System, Step By Step

The first thing we need to do is to create an API service on APItools. This service does not need to be hitting an actual API endpoint (I chose the echo-api).

Once the APItools is ready, it’s time to set up the Twilio side. Connect to your Twilio account and go to your number dashboard.

Twilio - Choose a number

Select the phone number of your choice and access to its dashboard. In the dashboard you can set up Twilio to do whatever you want when a text is received on that number. In our case, a POST request to our service previously created in APItools. Twilio will send the details of the text message to APItools.

In the Twilio dashboard you have two options: “Configure with URL” or “Configure with applications”. I chose the application option as it’s easier to deploy on many numbers, but both work fine. The URL should be http://FOOBAR.my.apitools.com

Your Twilio Dashboard

You can now test if it’s working by sending a text message to your Twilio number. And you should see the trace of the text message in the APItools service that you created (‘Traces’ tab).

Check the call on APItools

In the incoming request you could retrieve all the info about the text: its content, the number of the sender, and also info about the number like city or zipcode. In our example we will only use the content of the message.

Now we’re going to add a middleware module to update the data on Firebase. If you’re not familiar with the concept of middleware on APItools take a look here. Firebase is a great backend service that is really useful when it comes to real-time. This will be helpful to update graphs when new votes come.

Continuing with the middleware, this is the code I wrote: https://gist.github.com/picsoung/75e1d83f1f2bafdad561

-- fct to split a string by a delimeter
local function split(s, delimiter)
    local result = {}
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match)
    end
    return result
end
 
-- funct to send data to Firebase
local function sendToFirebase(name, type)
  local firebaseURL = "https://YOURFIREBASE.firebaseio.com/votes/"..name.."/"..type..".json"
  
  -- get current value
  local current_value = http.get(firebaseURL)
  
  --value does not exist
  if(current_value.body == "null") then
    local postFB = http.put(firebaseURL,tostring(1)) -- first vote is 1
    console.log(postFB)
  else
    local val = tonumber(current_value.body) + 1 -- increment of 1
    local postFB = http.put(firebaseURL,tostring(val))
    console.log(postFB)
  end
end
 
return function(request, next_middleware)
  local response = next_middleware()
  local params = split(request.body,'&')
  local decoded_params = {}
  -- turn urlencoded string into an object
  for i=1,#params do
      local p = split(params[i],'=')
      decoded_params[p[1]] = p[2]
  end
  
  
  -- read content
  local message = split(decoded_params['Body'],'+')
  local name = message[1]
  local content = message[2]
  
  console.log(name,content)
  if(content == "%F0%9F%91%8D") then -- emoji thumbs up
    sendToFirebase(name,"good")
  elseif (content == "%F0%9F%91%8E") then -- emoji thumbs down
    sendToFirebase(name,"bad")
  end
  
  return response
end

It first reads the message from Twilio. The Body params looks like NAME emoji, so we use a custom function to split the string in two, that way we can get the name and the emoji.

Then we read the emoji to see if it’s a thumbs up or down.

And finally, we call the SendToFirebase function.

This SendToFirebase function uses the Firebase REST API. If there is already a resource corresponding to the name and the sentiment (good or bad), we simply increment the value. If not, we create this new resource.

And that’s it :)

When you send a text you should see the value increments in your Firebase. You can also use Firebase to display the votes in a dashboard in real time.

Further Ideas

You could build an awesome UI to display votes, but that’s not the purpose of our tutorial here. You could add more complexity to prevent voting twice from the same number. Or you could also send a text back to the voters. These are some of the ideas that I may be implementing to my real time voting system :)

Wrap Up

In the end I was able to deploy a working voting system using Twilio and Firebase in a matter of hours thanks to APItools. I did not have to host it on any server, everything is hosted on the cloud by other services, all for free.

APItools let me connect services together in a very seamless way. The middleware is very light, I wrote really only a few lines of code.

This is very rewarding, and I encourage everybody to give it a try, there are lot more things you can build using APItools.

layout title author description categories tags
blog
Air Quality Bot For Slack With Breezometer
Guest blog post by Ziv Lautman (Breezometer)
This blog post was originally published on BreezoMeter's blog, by Ziv Lautman. BreezoMeter was founded by a group of environmental engineers in 2014 with the goal of learning more about the quality of air we breathe in real time. BreezoMeter has cool real-time API...
blog
slack mashups guest-blog-posts

This blog post was originally published on BreezoMeter's blog, by Ziv Lautman. BreezoMeter was founded by a group of environmental engineers in 2014 with the goal of learning more about the quality of air we breathe in real time. BreezoMeter has cool real-time API that they also use to power their [app](https://play.google.com/store/apps/details?id=app.breezometer&hl=en 'BreezoMeter's App'). To find out how to check the quality of the air in different parts of the world, from Slack, just keep reading ;)

The beautiful thing about releasing an API is that you know how it starts, but you can never guess how it will end. I am not saying that as a cliche, it’s just that developers are so creative, that you can’t really expect or foresee the results of their work. In my wildest dreams I couldn’t guess BreezoMeter’s Air Quality API will be used for Slack, our favorite team communication platform. I also never thought it will be so much fun.

Breezometer's Bot for Slack

BreezoMeter-Slack Bot: When typing breez + street address/city name, one immediately get the air quality levels, including the air quality color (on the left) and the health recommendations BreezoMeter’s API offer

The truth is that we mainly use the BreezoMeter-Slack Bot as a fun game along the day… checking air quality in different places in US that we are not sure even exist. Air-Quality-Geeks and we are proud!

So who is the super creative & talented developer who created the BreezoMeter-Slack Bot? Nicolas Grenie, hacker in residence at 3scale that even wrote do it yourself/how to create the Bot on Github.

What it does? Just type in any channel “breez” + address and immediately get the air quality levels and health recommendations for:

Kids
Health
Indoor
Outdoor
Sport
All from BreezoMeter's API.

Here is a detailed video on how to *integrate BreezoMeter’s Air Quality API into Slack – So you could also have fun – and breathe clean, healthy air (Based on the great guide Nicolas built)!

<iframe width="537" height="302" src="https://www.youtube.com/embed/qYcAyt2Gs5w" frameborder="0" allowfullscreen></iframe>

*Don’t forget to open this tab before starting :)

layout title author description gh-author categories tags
blog
Hacking APItools' Traffic Monitor API
Nicolas
During our internal hackathon at 3scale we used APItools's traffic monitor API, here is our stoy, get inspired and hack with it too.
picsoung
blog
apitools hack

You may remember the last story we've shared about our internal hackathon at 3scale. Well, we didn't tell you everything about it, we have more to share with you :)

During our internal hackathon, Didier and myself decided to build an API health status light using APItools and Hue light. The hue light will turn green if everything goes well, and red if there is an issue with the API response (4XX errors).

As we stated in our previous story we wanted to build to a a "one-click deploy" middleware service. The idea was to authenticate users with their APItools account, they'd select a monitor and a service, and we'd add our middleware to that. As simple as one click for the user and a bit more complicated from the hacking side.

Using an undocumented API

APItools' own API is not really documented and not clearly exposed as an API. However, it is consumed by APItools itself. So we went back and forth doing stuff in the APItools UI and analized the XHR requests that were made to see what was needed. We also used this blog post which contains some info about APItools' API. And with the help of our APItools engineers Michal and Enrique, we were able to make it work.

When we started, this is the flow he had in mind:

  1. Authenticating a user
  2. Retrieving monitors
  3. Retrieving services from monitor
  4. Adding middleware to the service

Authenticating a user

At first we thought that people would just give us a username and a password and we would log easily them in as there is nothing like OAuth in APItools. But it turned out that authentication with username and password was not available in the API.

Instead we could auth the user with their APItools API key and the monitor id they wanted to use. However, we wouldn't be able to list existing monitors for a user. That reduced our idea but it was also simpler to hack during a hackathon.

Your API key can be found under the settings menu:

APItools API Key

And there will be your API key: APItools API Key

We also needed the monitor id which can be found by clicking on the monitor link. The URL should look like this http://MONITOR_ID.my.apitools.com

Once you have both the API key and the monitor Id you can authenticate the request to APItools.

Make a simple GET request to https://API_KEY@MONITOR_ID.my.apitools.com/ In the response of this request extract the cookie XSRF-TOKEN and save it for later.

Play with services

Once you are authenticated on one monitor you can play with the services attached to that monitor.

For example, if you want to get all the services of a monitor you can call https://API_KEY@MONITOR_ID.my.apitools.com/api/services This will give you something like

[
    {
        "_created_at": 1401357490.031,
        "_updated_at": 1415824067.348,
        "endpoints": [
            {
                "code": "b83c5a5e",
                "url": "http://wservice.viabicing.cat/getstations.php?v=1"
            }
        ],
        "name": "Bicing",
        "_id": 4
    },
    {
        "_created_at": 1407826870.911,
        "_updated_at": 1417456661.228,
        "_id": 8,
        "endpoints": [
            {
                "url": "https://echo-api.herokuapp.com/",
                "code": "echo560bfa1c"
            }
        ],
        "name": "Echo API",
        "demo": "echo",
        "description": "Echo is simple service which responds for every request with JSON containing the request information. Like looking in the mirror. Useful for debugging middlewares."
    },
    {
        "_created_at": 1412951138.981,
        "_updated_at": 1428397938.496,
        "endpoints": [
            {
                "code": "proxy",
                "url": "*"
            }
        ],
        "name": "Proxy",
        "_id": 9
    }
]

In our case, during the hackathon we decided to keep it simple and just push a new service every time. Here is the call to create a new service on APItools

host = https://API_KEY@MONITOR_ID.my.apitools.com/api/services;
HTTP.post(host,{
    auth: API_KEY+":"+MONITOR_ID,
    headers: {"X-XSRF-TOKEN": XSRF_TOKEN, "Content-Type" : "application/json"},
    data: {
      endpoints:[{
        url: ENDPOINT_OF_THE_API,
        code: URLify2(NAME_OF_THE_SERVICE)
      }],
      name:NAME_OF_THE_SERVICE
    }
});

And a few placeholders that have to be taken care of:

  • API_KEY - APIKEY of APItools
  • MONITOR_ID - Monitor ID where you want to add the service
  • XSRF_TOKEN - Token you got from previous call
  • ENDPOINT_OF_THE_API - What is the endpoint URL of the API? ex: api.github.com
  • NAME_OF_THE_SERVICE - Name of the service, could be anything, we use URLify to escape special chars.

This will give you:

{
    statusCode: 201,
    content: '{
        "_created_at": 1431097935.906,
        "_updated_at": 1431097935.906,
        "endpoints": [
            {
                "url": "ENDPOINT_OF_THE_API",
                "code": "NAME_OF_THE_SERVICE"
            }
        ],
        "name": "NAME_OF_THE_SERVICE",
        "_id": 69
    }',
    headers: {
        'content-type': 'application/json',
        date: 'Fri, 08May201515: 12: 15GMT',
        server: 'openresty/1.5.11.1',
        'set-cookie': [
            'apitools_conrad_auth=OyhITbhzJvy876/duhushidhihsiuhiuhihih+1R9o3utntTI6Q4++PSMrQI/myYzfuWQ5b2HKRjEi9H72Ugb0+fHsi5RjYQ+;Path=/;Secure;HttpOnly;'
        ],
        'content-length': '151',
        connection: 'keep-alive'
    },
    data: {
        _created_at: 1431097935.906,
        _updated_at: 1431097935.906,
        endpoints: [
            [
                Object
            ]
        ],
        name: 'NAME_OF_THE_SERVICE',
        _id: 69
    }
}

If the response returns a 201 status it means that service was sucessfuly created. Store data._id, we will need it later.

####Adding middleware to the service Once the new service has been created, middleware can be added. Middleware modules are small snippets of Lua code that are executed when you make a call through APItools.

Middleware modules can be turned on or off, depending on if you want them active or not. You can also change the order of the middleware modules choosing the order in which they are executed.

In theory using the API you can load all the existing middleware modules of a service and see in which order they are executed. But in our case we didn't need that and we simply flushed the existing middleware pipeline and pushed our own.

We have written a few snippets of Lua code we wanted to push as middleware modules.

The first thing to do is creating a middleware object.

mw_uuid = uuid(); //Generate a unique id to identify the middleware
code = // Load from lua file
middlewares = {};
middlewares[mw_uuid] = {
  active: true,
  code: code,
  description: "Middleware autogenerated by API Health Bar",
  name: "AutoDegeneratedMw",
  position: 0,
  uuid: mw_uuid
};

As you can see middleware modules are identified by a unique Id, we created a function uuid() to generate one but you are free to use any id you want.

The code in the middleware module has to be loaded from the file you already wrote. Feel free to change the name and the description.

Once you the middleware object is created you can push it to the service.

host = https://API_KEY@MONITOR_ID.my.apitools.com/api/services/serviceID/pipeline;
HTTP.post(host,{
  auth: API_KEY+":"+MONITOR_ID,
  headers: {"X-XSRF-TOKEN": XSRF_TOKEN, "Content-Type" : "application/json"},
  data: {
    _id: 1,
    middlewares: middlewares,
    service_id: SERVICE_ID,
  }
});

If everything went well you should have something like this

{
    statusCode: 200,
    content: '{
        "_created_at": 1431099220.474,
        "_updated_at": 1431099223.366,
        "middlewares": {
            "MIDDLEWARE_UUID": {
                "active": true,
                "position": 0,
                "code": YOUR_MIDDLEWARE_CODE,
                "name": "AutoDegeneratedMw",
                "uuid": MIDDLEWARE_UUID,
                "description": "Middleware autogenerated by API Health Bar"
            }
        },
        "_id": 71,
        "service_id": 71
    }',
    headers: {
        'content-type': 'application/json',
        date: 'Fri,08May201515: 33: 43GMT',
        server: 'openresty/1.5.11.1',
        'set-cookie': [
            'apitools_conrad_auth=NxNk0l4KmcS4h4jW6WCy4f+1R9o3utntTI6Q4++PSMrQI/myYzfuWQ5b2HKRhyMaIxBDryo4ekt76RdCMo;Path=/;Secure;HttpOnly;'
        ],
        'content-length': '2970',
        connection: 'keep-alive'
    },
    data: {
        _created_at: 1431099220.474,
        _updated_at: 1431099223.366,
        middlewares: {
            'MIDDLEWARE_UUID': [
                Object
            ]
        },
        _id: 71,
        service_id: 71
    }
}

That's just an overview of how we used APItools' API in our hack. You could do much more without the time constraint of a hackathon. Imagine being able to push your middleware modules, dedicated to your API or to your users, in just few clicks.

You can find some hints for other API methods looking at the code on Github.

Can't wait to see what you are going to build with it :)

Happy hacking!

layout title author description gh-author categories tags
blog
How To Create Timelines Using Cardstream and Typeform APIs
Nicolas
During my preparation for the StartupBus I got the chance to try out all the APIs we () decided to bring with us on the bus and expose to *buspreneurs*. Amongst the few selected APIs we have two of our awesome customers: Typeform and Cardstream.
picsoung
blog
apitools hack

During my preparation for the StartupBus I got the chance to try out all the APIs we (3scale) decided to bring with us on the bus and expose to buspreneurs. Amongst the few selected APIs we have two of our awesome customers: TypeForm and Cardstream.

You may have heard about Typeform, they have a great self-service form creation tool. In a few clicks, you can build beautiful forms and share them with your users. And you know what? They just launched an API! Using the Typeform API you can create surveys and receive answers on webhooks. They just opened their beta and are making improvements to the API daily.

Cardstream just launched their new API too. Creating feeds or activity streams has never been easier.

In my example I imagined that I wanted to display user stories on my site. Users would submit their stories using Typeform and we woud generate the stream using Cardstream. Easy.

Here is a schema of the setup.

Screenshot

The form is available here.

The final result can be found here.

####What you need

  1. Typeform.io developer account
  2. Cardstream developer account
  3. APItools account

####APItools configuration Create a first service pointing to the echo-api. We will use this service to receive the webhook sent by Typeform every time a user submits an answer.

Create a second service pointing to Cardstream API https://api.cardstreams.io/v1

####Typeform.io configuration

#####Create the form We are going to create a simple form with three text fields: one to get the name of the user, another one to get the title of the story and a last one to get the content of the story.

With just a simple call to the Typeform API we will generate this form and add a webhook. The answer of the call will give us useful information and we'll see how to use it in this tutorial.

Make a POST request on https://api.typeform.io/v0.2/forms passing headers X-API-TOKEN with your Typeform token and the JSON content as follows:

{
  "title": "My first typeform",
  "webhook_submit_url":"https://URL_TO_APITOOLS_SERVICE_FOR_WEBHOOK/",
  "fields": [
    {
      "type": "short_text",
      "question": "What is your name?"
    },
    {
      "type": "short_text",
      "question": "Title of your post"
    },
    {
      "type": "long_text",
      "question": "What is the story of your life?",
      "description": "Please describe it within 50 characters",
      "required": true
    }
  ]
}

Here you will have to replace URL_TO_APITOOLS_SERVICE_FOR_WEBHOOK by the URL of the first service you created.

Once this call is executed you will receive an answer from the Typeform API. It should look like this:

{
    "id": "Dbu0eA2rX7qVlQ",
    "design_id": 1,
    "fields": [
        {
            "type": "short_text",
            "question": "What is your name?",
            "position": 0,
            "choices": null,
            "id": 207973
        },
        {
            "type": "short_text",
            "question": "Title of your post",
            "position": 1,
            "choices": null,
            "id": 207974
        },
        {
            "type": "long_text",
            "question": "What is the story of your life?",
            "position": 2,
            "choices": null,
            "id": 207975
        }
    ],
    "links": {
        "form_render": {
            "get": "https://forms.typeform.io/to/Dbu0eA2rX7qVlQ"
        }
    },
    "title": "My first typeform",
    "webhook_submit_url": "URL_TO_APITOOLS_SERVICE_FOR_WEBHOOK"
}

Keep this answer somewhere, you will need the URL of the form to test it out, as well as the id of each field.

####Cardstream configuration On Cardstream developer portal you can create a new stream. Create one and save the ID somewhere.

#####Add middleware to handle webhook On the first service you have create we will now add a middleware module to pass the data to Cardstream.

Here is the code of the middleware:

return function(request, next_middleware)
  local response = next_middleware()
  local answers = json.decode(request.body).answers
  local title =""
  local user = ""
  local text = ""
  for i=1,#answers do
    if(answers[i].field_id == ID_OF_FIELD_FOR_USERNAME) then
      user = answers[i].data.value
    end
    if(answers[i].field_id == ID_OF_FIELD_FOR_TITLE) then
      title = answers[i].data.value
    end
    if(answers[i].field_id == ID_OF_FIELD_FOR_STORY) then
      text = answers[i].data.value
    end
  end
  
  -- call to cardstream
  local streamID = "CARDSTREAM_STREAM_ID"
  local cardstreamURL = "https://CARDSTREAM_APITOOLS_URL/streams/"..streamID.."/cards"
  local r = http.json.post(cardstreamURL,{title=title.." by "..user,description=text})
  console.log(r)
  return response
end

In this code you will change:

ID_OF_FIELD_FOR_USERNAME, ID_OF_FIELD_FOR_TITLE and ID_OF_FIELD_FOR_STORY with the IDs given by Typeform.

CARDSTREAM_STREAM_ID ID of stream you have created on Cardstream

and CARDSTREAM_APITOOLS_URL URL of the APItools service linked to Cardstream.

#####Test the flow To test that everything is working, submit an answer on your form. You should see the webhook call going through the APItools service and then calling the Cardstream service.

At the end, in the Cardstream portal (preview tab), you should see the working result.

You can then generate the embed code and paste it on your site. However, if you want to personalize te style and put your own cards anywhere you want and make them look however you want, you could also do that since the Cardstream API returns just JSON too.

And voila, it was that easy :) There are endless integrations you can build using Typeform API or Cardstream, we'd love to hear about what you're working on!

If you are interested in participating in StartupBus you still have time to apply here and attend the kickoff party on June 3rd in San Francisco.

layout title author description gh-author categories tags
blog
Consume APIs The Way You Want. Example Case: Ifeelgoods API
Nicolas
Consuming APIs they way you want… is that even possible? I was recently playing with Ifeelgoods API for one of my slack bots...
picsoung
blog
apitools hack

Consuming APIs the way you want… is that even possible? I was recently playing with Ifeelgoods API and found myself stuck because of a feature of their API that was not available. Was this a problem? Not at all, keep reading :)

####About Ifeelgoods API Ifeelgoods gives you the possibility to reward your users or customers or employers with digital goods. And they have an API to do that. For example, if you had a virtual currency, you could offer a shop where users could convert the virtual currency to actual tangible goods.

They offer a tone of different types of rewards so you can choose the ones you like. In my case, I needed to be able to sort the rewards list provided by price and category.

How many times have you wished this API provided this field, or was served in this format, or... ? I bet this has happened to you too.

####Enhancing The Ifeelgoods API With APItools So I decided to use APItools to sort this out and built a couple of middleware modules.

The first one is to get rewards filtered by category:

local indexOf = function( t, object )
  if "table" == type( t ) then
    for i = 1, #t do
        if object == t[i] then
            return i
        end
    end
    return -1
  else
    error("indexOf expects table for first argument, " .. type(t) .. " given")
  end
end

return function(request, next_middleware)
  local response = next_middleware()
  local data = json.decode(response.body).data

  -- CHANGE THIS TO THE CATEGORY YOU ARE INTERESTED IN
  local category='ecommerce'

  local r ={}
  for i=1,#data do
    if(indexOf(data[i].categories, category) ~= -1) then
     table.insert(r,data[i])
    end
  end

  response.body = json.encode({data=r})
  return response
end

And the second one is to get rewards filtered by price:

return function(request, next_middleware)
  local response = next_middleware()

  local data = json.decode(response.body).data

  -- CHANGE THIS TO WHATEVER YOU WANT
  local max_price = 9
  local min_price = 2

  local r={}
  for i=1,#data do
    if(tonumber(data[i].face_value)>= min_price and tonumber(data[i].face_value) <= max_price) then
      table.insert(r,data[i])
    end
  end

  response.body = json.encode({data=r})

  return response
end

With these two middleware modules I can just built my app consuming the Ifeelgoods API as if the sorting was available.

####Re-using Middleware Modules The beauty of this is that now anyone can re-use these middleware modules that I created with the Ifeelgoods API.

When you navigate APIs on APItools you’re able to see which middleware are available so let’s say you’re participating in a hackathon, just go and see if there are any middleware module available for the API you’re planning on using. To do that, you can either go to our list of APIs and see what's available. E.g.

Twitter API on APItools

Or create an account, add a service and go to 'Pipeline'. There you can search amongst all the middleware modules and just drag and drop the one you want to use to your pipeline:

Twitter API on APItools

I hope this is useful! If you're working with the Ifeelgoods API and using APItools, I'd love to learn more about your hack ;)

layout title author description gh-author categories tags
blog
Daily event suggestion using APItools
Nicolas
There are many things you can think of which would be nice get automatically delivery to you on a daily basis: picture of the day, song of the day, github project of the day, event of the day to mention just a few. We dediced to build a service to suggest events everyday and send it to Slack
picsoung
blog
mashups fun slack bot cron

There are many things you can think of which would be nice get automatically delivery to you on a daily basis: picture of the day, song of the day, github project of the day, event of the day to mention just a few. National Geographic has a page dedicated to show you a photo a day, and I’m sure there are others for other purposes.

The thing is that you have to go to all these places individually. Which is fine but, if you’re already using Slack, so don’t have to anymore. This is just another useful type of bot you can create and consume directly from Slack. And this is what we’ve done.

####Defining your bot #####Topic

In our case, we wanted to build a solution to pick an event of the day. You can personalize that depending on what your needs are:

  • Use an API which exposes events in your city
  • Use an API which exposes best conferences around the world about one topic your employees may be interested in e.g. devops

Just think of something that’s going to be useful for your company and for your employees.

In our case we chose the OpenAgenda API, mostly because of we were looking to events happening in France, to celebrate Bastille Day. OpenAgenda is widely use in France among cities, ministeries and associations. There is a good chance to find events every day around you.

#####Frequency

The second thing you could choose to do is make the Slack bot to post the event every day at the same time, or a couple of times a day, but always at the same time, so people know when to expect that information. To serves this purpose we’ve chosen Easycron. It lets you run cron job (regular job) for free. We will use it to call our endpoint once a day. We will setup it later.

####APIs + APItools = Win One more time, I’ve used APItools to log my requests and responses to the different APIs I used:

Benefits of using APItools with these APIs:

  • have access to OpenAgenda data and extract only what I am interested in
  • create a hook, that’s is callable from the outside (by the cron job)

####Creating the bot, step by step

#####Calling OpenAgenda API OpenAgenda API is where we will get the events from. From the returned events we will pick one to suggest to the user using a Slack bot.

Let’s start by creating a new service pointing to OpenAgenda API: https://api.openagenda.com/v1

APItools will generate a SOMETHING.apitools.com URL, remember it somewhere we will need it soon

#####Creating the hook What we call a hook would be the URL called on a regular basis to return a suggested event. This URL could be an APItools service.

Create a new APItools service pointing to the echo-api https://echo-api.herokuapp.com. Once the service is created, go add a middleware in the Pipeline section.

The code for the middleware could be found here

We left couple of placeholders in the code so you could modify the code for your own needs:

  • LATITUDEOFYOURPOINT and LONGITUDEOFYOURPOINT are the coordinates around where you want to find events, it could be your office, your home, or anything else
  • RADIUSINMETERS corresponds to the radius around the center point where the search for events will be performed, if the radius is too small you might not find events
  • OPENAGENDAAPI KEY is the API key issued by OpenAgenda to access their API, get one here
  • OPENAGENDA_[APItools](http://apitools.com)SERVICE_URL is the URL of the previously created service pointing to OpenAgenda service.

Once you have configured all these placeholders, you can test by calling the hook. Just make a GET request on the service URL. You should see the request passing through.

The rest of the code snippet is used to get current date and format it. You should not have to chance anything on this part.

Now we will add some logic into OpenAgenda service to extract the relevant info we need and post it on Slack.

Create a incoming webhook on Slack

To be able to post something on Slack we would need to create an incoming webhook.

Log on into your Slack team, and look in the integrations page add a new incoming webhook.

Give it a name, select where it should post, change it’s icon… and save the generated WebHook URL, we will need it for later. That’s the only configuration we would need on Slack.

#####Add middleware to OpenAgenda service

On the OpenAgenda service we will add a middleware to extract from all the events happening on the day, only one. We will give priority to events that are happening only on the date, if there are not we will randomly pick a recurring event.

The code for the snippet could be found here.

As in the previous snippet we left some placeholders:

  • INCOMINGWEBHOOKSLACKURL should be replaced by the URL of the incoming webhook we created on Slack earlier.
  • SLACKCHANNEL by the channel where you want to bot to post. Channel should be formatted as #channel_name

The rest of the code is pretty straightforward, looping through results, extracting relevant info and then posting to Slack with a POST request. The Slack part generate a complex JSON payload to be able to display as much info as possible about this event. You can check the relevant documentation here to understand it better.

Voilà, the bot

If everything went well, just go to the Slack channel you of your choice at the time you set it up and something like this should show up: screenshot of eventbot

And if a Slack notification is not enough, you could do the same but with the Sendgrid API and also get these events by email to you daily without much effort.

####Call the bot every day Everytime the URL of the hook is going to be call, the bot will be called. We need a service to call this URL on a regular basis. One simple way would be using cron services like Easycron. It lets you call any URL on a period you determine.

To finish the integration, create an account on EasyCron and setup your first cron to call your Hook URL.

screnshot of easycron

You can define a short period to test the bot. Once everything works well, make it call every day.

####Conclusion You now have a working integration called on a regular basis. You don’t have any backend code, everything is done in the cloud, on indepent micro-services. This showcase one of the many usecases of how you could use APItools to work with APIs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment