7. APIs - What are these things eh?

Application Programming Interfaces (API) are basically ways for various systems to talk to each other. And share info. In a nice secure way, where the systems can ensure that data going out or coming in, is well controlled.


APIs come in loads of forms. Sometimes it's some ooooooolllldddddd stuff like a CTI (Computer Telephony Interface) for linking up a hard phone to a physically nearby computer. No joke. When customers talk about CTI, that's what they mean. A wired link between a user's deskphone, and their desktop computer.

They also exist as programming interfaces over HTTP. This was a huge thing in the early to mid 2010's. The first version of this was the ability to send information through the internet to some other computer in a format similar to HTML (I know I haven't covered HTML yet. Don't hate.). This was referred to as XML, and you'll still see it pop up from time to time (especially in the financial sector, where tech changes happen super slowly). These days we use REST (Representational state transfer). To bring it to normal person talk, it let's you send information, securely,  from one system to another in (mostly) JSON form.

Its big advantage is its focus on the full CRUD (Create, Read, Update, Delete) methodology. XML didn't implement CRUD very well, but RESTful APIs do this really well. CRUD was a database type thingy. See how I'm garbage at database type thingies? You don't need to be a boss at DB stuff (like Tyler Doyle is) to be a boss at RESTful architecture. You just have to get that basic idea.

I (some RC user) have a user extension I need to update. You have a RESTful endpoint that can handle CRUD good. So I need to send you a request to change that extension around. Maybe something so simple as changing the user's extension number?

In RESTful systems, we send the information through HTTP(s) with requests. Requests have multiple parts to them, and understanding them will be key to working with any modern API out there.

Things we gotta go over:

  1. HTTP Methods
  2. HTTP Base URLs
  3. HTTP Path Parameters
  4. HTTP Query Parameters
  5. HTTP Headers
  6. HTTP Bodies
  7. HTTP Responses

Oh goodness, it's nitty gritty time. Those above topics cover all the really important stuff that happens in a common REST request (everything you send through an API is a request). They're all super important, and most are required on each request.

HTTP Methods:

  1. POST - This is to create a new thing
  2. GET - This is to read information on an existing thing
  3. PUT - This is to update an existing thing
  4. DELETE - This to (who would've guessed?) delete an existing thing

HTTP Base URLs are easy to understand. It's the freakin website you're going to. Like, / (ya I know it's long. Talk to the ops guys), or https://www.google.com.

What's the 's' for you ask? Just means secure. Or SSL (secure socket layer) depending on which complete nerd you talk to. HTTP means hyper text transport layer. It was invented by some cool people in the 70s (NOT Al Gore). Thus the dope naming convention. But ya, it's how stuff moves around the web. http:// is probably a hack while https:// probably isn't.

HTTP Path Parameters

These are those things after the '/'. https://www.google.com/search <-- search is a particular webpage they want you to see, in this case at least. In the RC API world, this usually represents something like an account.

Think of it as sending your request through the right set of doors. In the RC Platform world, we have a base URL of https://platform.ringcentral.com/. Then, have to tell that system that we're specifically wanting to talk through the REST api with /restapi/v1.0/ (in this case version 1.0, and who knows if/when there's another version).

Then, we tell it what type of info we're wanting to interact with, like, a customer account /restapi/v1.0/account/{someAccountUid}. Alright we're getting somewhere huh? That {someAccountUid} is a path variable. You'll see that all over the place, but it can also be seen as /restapi/v1.0/account/:someAccountUid/. Either way, the person writing your documentation means that :someAccountUid or {someAccountUid} is a variable that you enter into your path. They will then use that to lookup an account UID on their backend.

Take it further, and you want to tell the RC platform about a particular extension? /restapi/v1.0/account/{someAccountUid}/extension/{someExtensionId}/. Bammo. You show the UID and Extension ID (same as mailbox ID) in the URL path parameters, and RC platform knows exactly who/what you mean.

With the RC platform, there's two path param shortcuts. /account/~/ and /extension/~/. That ~ character is called a tilde. When you put it in an RC platform path, it essentially means the account/user I'm currently logged in as. So if you're logged in as John Celoria, then /restapi/v1.0/account/~/extension/~/ would get you focused in on my extension info. Assuming, you had logged in as John Celoria when sending your requests...

HTTP Query Parameters

Ok we ran our mouth off around path parameters, so let's talk about Query Params. As you can probably guess, Query params are mostly for searching. Let's say you knew John Celoria's email address, but not his extension ID. If you knew my extension ID, you'd just put it in as a path parameter, but you don't. So you need to ask for information on me, by getting the RC platform back end to do a search.

Query params come at the end of path parameters, following a ?. Then, you've got to use some = signs to indicate what thing you're searching for.

/restapi/v1.0/account/~/extension?emailAddress=john.celoria@ringcentral.com. Dope! So the path parameters end before you signify an extension (mailbox) id. That means you either want a list of extensions, or you're going to provide some query parameters to help the RC platform back end narrow it down. In my case, an acceptable query param is by email, so I'm saying, look through all your extensions on this account that I'm signed in with, for an extension that has an email of john.celoria@ringcentral.com. Hopefully there's not multiple extensions with that email (not the RC wouldn't respond with multiple extensions, but emails should really really really be unique).

In these that you need to send multiple query parameters, you split them up with an &. So if I wanted to narrow way down, and search for extension with my email and my extension number, I could say this... /restapi/v1.0/account/~/extension?emailAddress=john.celoria@ringcentral.com&extensionNumber=70935 (I don't even know my extension number so I made that up, you get the idea). You can chain together all the query parameters you want with an &.

HTTP Headers

Maybe I should've put these sooner, but they signal valuable pieces of information to the systems you're talking to. That's an important distinction, as most APIs you're working with, are not going to harp on headers outside of Authentication.

Oh goodness. We've arrived. Auth. I'm not even going to touch it, except that it should (barring some cases that are in fact important, but way out of scope) go in the request headers. Usually this is as a header named "Authorization". This is one of those good old key/value pairs, and the first name of the value indicates that this is "Basic" auth or "Bearer" auth. Bearer is way more goodliest. Basic essentially means a mashup of your username and password. Bearer is this magic way of authenticating using temporary strings that the other system has assigned to you, after authenticating with your username/password so that you aren't constantly sending a username/password mashup.

In your requests, they will normally look like...

headers: {
    Authorization: "Bearer 1238172398aEXAMPLEaiudgiausghd"
}

I know you remember that JSON goodness. There's another common one, that won't change for you much. It's your "content-type" header. It's there to tell the other system how to interpret the body of your request. In almost all circumstance you'll interact with with RC platform, it will be "application/json". So...

headers: {
    Authorization: "Bearer 1238172398aEXAMPLEaiudgiausghd",
    "content-type": "application/json"
}

HTTP Body

So this is the "payload" you're sending to the other system. Let's say you're sending a request to update info on an extension. To do that, we piece together some things.

We've got our auth in the header that signifies who you are, we've got our path parameters to indicate all the way down to the exact extension you're trying to mess with, in this case there's no query parameters cause we aren't trying to search for some extension (we already indicated it), and lastly the body indicates what we want changed.

Phew. Mouthful. Here's some more info...

httpMethod: PUT
url: https://platform.ringcentral.com/restapi/v1.0/account/~/extension/1234
headers: {
    Authorization: "Bearer 1238172398aEXAMPLEaiudgiausghd",
    "content-type": "application/json"
}
body: {
   extensionNumber: 9876
}

Woohoo! That's some good stuff!!

As a real world example, this would be my attempt to change extension with an ID (mailbox ID) or 1234, to have an extension number of 9876! That's pretty cool! Remember though, all this is designed to let your program interface with the RC platform safely. You and I both know that you can't have duplicate extensions. So, if the extension ID exists on the account you indicated, and the authorization checks out, and the extension number isn't in use already on that account (or maybe they have site codes or something like that and it needs to be formatted as 1119876), then boom! RC platform will respond back with the updated info!!! DOPE!!

HTTP Responses

You need a heads up that something worked (or didn't) right? That's what responses are. They come back to you with the same fundamental parts. YOU are the base URL and path now, and there's headers (super useful for getting request ID information), and the body of the response, which generally tells you what the heck just happened.

In the case that my PUT request above, to change the extension number went ok, the body of response would be info about that particular extension I messed with.

If there was an error (like the extension number was in use, or didn't satisfy some formatting requirement) the body of the response would tell me.

HTTP StatusCode/StatusText

"John, you didn't put this in the table of contents for this topic". Ya whatever, deal. Long story short, the Status Code is a 3 digit number to signify how the request went. 2** is good, 4** is bad, and it will tell you what you messed up, 5** is bad, and the other end has no idea why.

You've seen "404 page not found" before, no doubt. That's a Status Code and the Status Text. Really short pieces of info to give you an idea of what happened. When you see a 5** code, that means something went way sideways on the other end, and you should probably gather logs (like the rcrequest-id header) to send over to the nerds, so they can find out what just happened on their end.


So last little thing. You saw the address in the picture for this post? Let's try that thing out.

https://swapi.dev is the base url.
/api/people means we're trying to use the programming interface, and are interested in people
?search=r2 means we're asking about a specific person, who, somewhere in their info (in our case name) contains the string "r2".

From Postman (really cool thing, don't worry about it right now). Comments after the // are mine...

GET /api/people?search=r2 HTTP/1.1

// headers (shortened down a bunch)
Referer: http://swapi.dev/api/people/?search=r2
HTTP/1.1 200 OK // <-- status code and text
Date: Thu, 24 Sep 2020 05:11:21 GMT
Content-Type: application/json

// body
{"count":1,"next":null,"previous":null,"results":[{"name":"R2-D2","height":"96","mass":"32","hair_color":"n/a","skin_color":"white, blue","eye_color":"red","birth_year":"33BBY","gender":"n/a","homeworld":"http://swapi.dev/api/planets/8/","films":["http://swapi.dev/api/films/1/","http://swapi.dev/api/films/2/","http://swapi.dev/api/films/3/","http://swapi.dev/api/films/4/","http://swapi.dev/api/films/5/","http://swapi.dev/api/films/6/"],"species":["http://swapi.dev/api/species/2/"],"vehicles":[],"starships":[],"created":"2014-12-10T15:11:50.376000Z","edited":"2014-12-20T21:17:50.311000Z","url":"http://swapi.dev/api/people/3/"}]}

The body response, formatted nicely looks like...

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "name": "R2-D2",
            "height": "96",
            "mass": "32",
            "hair_color": "n/a",
            "skin_color": "white, blue",
            "eye_color": "red",
            "birth_year": "33BBY",
            "gender": "n/a",
            "homeworld": "http://swapi.dev/api/planets/8/",
            "films": [
                "http://swapi.dev/api/films/1/",
                "http://swapi.dev/api/films/2/",
                "http://swapi.dev/api/films/3/",
                "http://swapi.dev/api/films/4/",
                "http://swapi.dev/api/films/5/",
                "http://swapi.dev/api/films/6/"
            ],
            "species": [
                "http://swapi.dev/api/species/2/"
            ],
            "vehicles": [],
            "starships": [],
            "created": "2014-12-10T15:11:50.376000Z",
            "edited": "2014-12-20T21:17:50.311000Z",
            "url": "http://swapi.dev/api/people/3/"
        }
    ]
}

(hint, it's the star wars api)

If I'd requested info on a specific person ID...

GET /api/people/3/ HTTP/1.1 // <-- includes an ID in that path

HTTP/1.1 200 OK
Content-Type: application/json

{"name":"R2-D2","height":"96","mass":"32","hair_color":"n/a","skin_color":"white, blue","eye_color":"red","birth_year":"33BBY","gender":"n/a","homeworld":"http://swapi.dev/api/planets/8/","films":["http://swapi.dev/api/films/1/","http://swapi.dev/api/films/2/","http://swapi.dev/api/films/3/","http://swapi.dev/api/films/4/","http://swapi.dev/api/films/5/","http://swapi.dev/api/films/6/"],"species":["http://swapi.dev/api/species/2/"],"vehicles":[],"starships":[],"created":"2014-12-10T15:11:50.376000Z","edited":"2014-12-20T21:17:50.311000Z","url":"http://swapi.dev/api/people/3/"}

Just one result/record is returned. Prettyfied it looks like

{
    "name": "R2-D2",
    "height": "96",
    "mass": "32",
    "hair_color": "n/a",
    "skin_color": "white, blue",
    "eye_color": "red",
    "birth_year": "33BBY",
    "gender": "n/a",
    "homeworld": "http://swapi.dev/api/planets/8/",
    "films": [
        "http://swapi.dev/api/films/1/",
        "http://swapi.dev/api/films/2/",
        "http://swapi.dev/api/films/3/",
        "http://swapi.dev/api/films/4/",
        "http://swapi.dev/api/films/5/",
        "http://swapi.dev/api/films/6/"
    ],
    "species": [
        "http://swapi.dev/api/species/2/"
    ],
    "vehicles": [],
    "starships": [],
    "created": "2014-12-10T15:11:50.376000Z",
    "edited": "2014-12-20T21:17:50.311000Z",
    "url": "http://swapi.dev/api/people/3/"
}

You see, when searching, or asking for a list of things, there's usually some info on the various results, and how many there are. When specifying an ID, you get info on just that one thing. Really useful thing to keep in mind when you get into the RC Platform.

Now let's try out an API in real time...