The WordPress HTTP API consists of a bunch of functions that will help you make HTTP calls a lot more easily. No need to fiddle around with file_get_contents or cURL anymore, just a single unified interface. This is awesome for interacting with third party APIs, especially REST-full ones like Twitter, Facebook, MailChimp, and others.

The Basics Of HTTP

We’ve all seen HTTP in action before. In fact, if this is your first time on the web ever and this is the first thing you are reading, you have already seen HTTP working its magic. HTTP is a network protocol used to deliver all files and data (resources) across the Interwebs.

There are basically two parts to the equation: the HTTP request and the HTTP response, or transaction. Both the request and the response are very similar in structure, they both have four parts:

  • An initial line
  • Zero or more header lines
  • A blank line
  • An optional body content

The Initial Line

Requests use the initial line to send three pieces of information: the method name, the path and the HTTP version. For example, when viewing the main Kinsta blog page, you would see this in the initial line of the request.

GET /blog/ HTTP/1.1

Responses provide three pieces of information as well, albeit somewhat different ones: The HTTP version, the response code and a description of the response. When making a request to the main Kinsta blog it will send an HTTP response with the following initial line:

HTTP/1.0 200 OK

Headers

Headers contain various bits of information about the request or the response. HTTP 1.1 defines 46 types of headers but only one is required (only for requests), the “Host” header. Take a look at the screenshot from my Chrome developer tools that shows some of the headers sent along with a request to the main Kinsta blog:

HTTP request headers sent

Body

The body usually contains data about the requested resource. If you send a GET request to the main Kinsta blog you should receive the HTML required to render the page (the resource) in the body content.

More Information

That’s all you need to know right now about HTTP. We’ll mostly be focussing on the method name (GET,POST,etc), headers and the body. If you’d like to learn more I recommend James Marshall’s explanation of HTTP, it’s a very well written primer for your HTTP needs.

About Restful APIs

Restful APIs, or the REST methodology aims to provide a simple and standard way to interact with an application (here you can learn more about the basics of the WordPress REST API). It is often used in conjunction with HTTP to create a very understandable system of interactions. It is based on paths and HTTP verbs.

HTTP Verbs are the same as the method names we saw earlier, the most common ones are: GET, POST, PUT, DELETE. I think PUT is the only ambiguous one here, think of it as an update command. When using these verbs together with paths we can construct a meaningful system:

GET /post/1/ would be used to retrieve the post with the ID of 1. DELETE /post/1/ would be used to delete the same post. We could also use PUT /post/1/ to update it, supplying relevant information in the request body and headers.

I’m sure you can see that just by appending an HTTP version to our codes above we actually have the initial line of an HTTP transaction, which is just one reason that this system is so powerful.

Using The WordPress HTTP API

Armed with all that knowledge we can easily take in how the WordPress HTTP API works. The four methods used to make requests and intercept the responses are:

  • wp_remote_get()
  • wp_remote_post()
  • wp_remote_head()
  • wp_remote_request()

The first two functions are self-explanatory, they use the GET and POST methods respectively in the request. The third function uses the HEAD method, something we haven’t talked about yet. This method is used to retrieve only the headers of a response. This can save a lot of overhead if we just need some metadata about a resource. The final function is a generic one, you can specify which method you would like to use within the function’s parameters.

There are five additional functions we can use to retrieve specific parts of the response. These are basically shotcuts to navigate the mass of data we receive:

  • wp_remote_retrieve_body()
  • wp_remote_retrieve_header()
  • wp_remote_retrieve_headers()
  • wp_remote_retrieve_response_code()
  • wp_remote_retrieve_response_message()

Our First HTTP Request

Let’s do a quick test by retrieving the header information from the Kinsta blog. You can do this anywhere within a plugin or a theme but you should obviously be within a test environment to make sure you don’t output unwanted text on a live site.

$response = wp_remote_head( 'https://kinsta.com/blog/' );
var_dump( $response )

As you can see from the response we get below, the body section is empty (since we are using the HEAD method) and all the headers are shown. To grab only the headers without all the other array members we could use the wp_remote_retrieve_headers() function.

array (size=5)
  'headers' => 
    array (size=13)
      'server' => string 'nginx' (length=5)
      'date' => string 'Wed, 22 Jul 2015 14:22:07 GMT' (length=29)
      'content-type' => string 'text/html; charset=UTF-8' (length=24)
      'connection' => string 'close' (length=5)
      'vary' => string 'Accept-Encoding' (length=15)
      'x-pingback' => string 'https://kinsta.com/xmlrpc.php' (length=29)
      'x-powered-by' => string 'HHVM/3.8.0' (length=10)
      'link' => string '; rel="https://github.com/WP-API/WP-API"' (length=68)
      'x-frame-options' => string 'DENY' (length=4)
      'x-content-type-options' => string 'nosniff' (length=7)
      'strict-transport-security' => string 'max-age=31536000' (length=16)
      'x-kinsta-cache' => string 'HIT' (length=3)
      'content-encoding' => string 'gzip' (length=4)
  'body' => string '' (length=0)
  'response' => 
    array (size=2)
      'code' => int 200
      'message' => string 'OK' (length=2)
  'cookies' => 
    array (size=0)
      empty
  'filename' => null

Making Sense Of APIs

twitter wordpress api

The biggest barrier I see for developers is the sheer amount of new stuff they need to put into place to make an API call work. you need to know about HTTP, how to make requests and also how to authenticate properly, without that, every single call will fail. Let’s look at an example through the Twitter API since they have great documentation.

We’ll be looking at the Application-only Authentication (which is an easier flow), I’ll be going through the same steps Twitter suggest. Before we begin, make sure to create a Twitter application.

You should be able to add the code below anywhere into a theme or a plugin but, like before, make sure to use a test site!

Step 1: Encode Consumer Key And Secret

Once you create an application you should have a consumer key and secret at hand. To make things easier, let’s create constants that hold this information for us.

define( 'TWITTER_CONSUMER_KEY', '12disnir382jeqwdasd23wdasi' );
define( 'TWITTER_CONSUMER_SECRET', '23wdajskduhtrq2c32cuq9r8uhuf' )

The three steps of creating an encoded version of these are laid out in the docs:

  • URL encode the consumer key and the consumer secret
  • Concatenate them with a colon
  • Base64 encode the whole string

In PHP this will be pretty easy to do, here goes!


$key = urlencode( TWITTER_CONSUMER_KEY );
$secret = urlencode( TWITTER_CONSUMER_SECRET );
$concatenated = $key . ':' . $secret;
$encoded = base64_encode( $concatenated );

Step 2: Getting a Bearer Token

Instead of using your actual password, you send Twitter your encoded string (which uses your API credentials) and you receive a temporary pass which is valid for a set amount of time. To do this we’ll be making an HTTP request, here’s what Twitter has to say:

  • The request must be a HTTP POST request.
  • The request must include an Authorization header with the value of Basic .
  • The request must include a Content-Type header with the value of application/x-www-form-urlencoded;charset=UTF-8.
  • The body of the request must be grant_type=client_credentials.

Let’s start with the basics. We know we need a POST request so we’ll be using wp_remote_post(). The function takes to parameters; the first one is the URL, the second holds optional arguments. The URL will be https://api.twitter.com/oauth2/token, we’ll use the second parameter to deal with all the other requirements.

$args = array(
    'headers' => array(
        'Authorization' => 'Basic ' . $encoded,
        'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
    ),
    'body' => 'grant_type=client_credentials'
);
$response = wp_remote_post( 'https://api.twitter.com/oauth2/token', $args );

Headers need to be added as an array, the header type being the key, the value the value of the array member; The body should be a string. If successful, you should see a response similar to the one below.

array (size=5)
  'headers' => 
    array (size=23)
      'cache-control' => string 'no-cache, no-store, must-revalidate, pre-check=0, post-check=0' (length=62)
      'content-disposition' => string 'attachment; filename=json.json' (length=30)
      'content-encoding' => string 'deflate' (length=7)
      'content-length' => string '142' (length=3)
      'content-type' => string 'application/json;charset=utf-8' (length=30)
      'date' => string 'Wed, 22 Jul 2015 14:47:37 GMT' (length=29)
      'expires' => string 'Tue, 31 Mar 1981 05:00:00 GMT' (length=29)
      'last-modified' => string 'Wed, 22 Jul 2015 14:47:37 GMT' (length=29)
      'ml' => string 'A' (length=1)
      'pragma' => string 'no-cache' (length=8)
      'server' => string 'tsa_b' (length=5)
      'set-cookie' => string 'guest_id=v1%3A14375720938219946; Domain=.twitter.com; Path=/; Expires=Fri, 21-Jul-2017 14:47:37 UTC' (length=100)
      'status' => string '200 OK' (length=6)
      'strict-transport-security' => string 'max-age=631138519' (length=17)
      'x-connection-hash' => string 'd8b10926f99dwef93rd7edbe5a71a97a' (length=32)
      'x-content-type-options' => string 'nosniff' (length=7)
      'x-frame-options' => string 'SAMEORIGIN' (length=10)
      'x-response-time' => string '34' (length=2)
      'x-transaction' => string 'ef0ebwefweece62ef' (length=16)
      'x-tsa-request-body-time' => string '0' (length=1)
      'x-twitter-response-tags' => string 'BouncerCompliant' (length=16)
      'x-ua-compatible' => string 'IE=edge,chrome=1' (length=16)
      'x-xss-protection' => string '1; mode=block' (length=13)
  'body' => string '{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAAAFoafQAAAAAAqg%2BxmuH83hjsod6crH5bKTUX9Arc%3D5dWpp0XCTDjyiXxMC7LDLg8JbzPdGlCsJi2R1qjY1FMksTAFyG"}' (length=155)
  'response' => 
    array (size=2)
      'code' => int 200
      'message' => string 'OK' (length=2)
  'cookies' => 
    array (size=1)
      0 => 
        object(WP_Http_Cookie)[303]
          public 'name' => string 'guest_id' (length=8)
          public 'value' => string 'v1:143757645770219946' (length=21)
          public 'expires' => int 1500648457
          public 'path' => string '/' (length=1)
          public 'domain' => string '.twitter.com' (length=12)
  'filename' => null

The main highlight of all that is the access token which can be found in the body of the response. Let’s retrieve that now using our handy WordPress functions. Continuing on from our previous example we could grab the access token using the following code:

$body = wp_remote_retrieve_body( $response );
$body = json_decode( $body, true );
$access_token = $body['access_token'];

Step 3: Use The Bearer Token

The last step is simply to use this bearer token in all other API calls. We need to add it as an “Authorization” header with the value: Bearer [bearer_token]. Let’s do a simple API call that will retrieve a user’s latest tweets using the user_timeline path.

$url = 'https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=danielpataki&count=3';
$args = array(
    'headers' => array(
        'Authorization' => 'Bearer ' . $access_token,
    ),
);

$response = wp_remote_get( $url, $args );
$tweets = json_decode( wp_remote_retrieve_body($response), true )

At the end of all that, the $tweets variable will contain an array of tweets. You can use various properties of this array to display the tweet or manipulate the data.

Conclusion

As you can see, using the WordPress HTTP API to connect to external services isn’t that difficult. Many of today’s modern APIs are built around the same REST principles – once you learn one, you’ll get the hang of others really quickly.

Keep in mind that whenever the documentation asks you to use the body, use the body and when it calls for headers, just add as many as needed. Then, look at the response, convert it to an array, grab the data you need and use it, it’s that simple.

If someone has worked with a particularly good or bad API before, or you have some tips an tricks using the WordPress HTTP API, let us know in the comments!

Daniel Pataki

Hi, my name is Daniel, I'm the CTO here at Kinsta. You may know me from Smashing Magazine, WPMU Dev, Tuts+ and other WordPress/Development magazines. Aside from WordPress and PHP I spend most of my time around Node, React, GraphQL and other technologies in the Javascript space.

When not working on making the best hosting solution in the Universe I collect board games, play table football in the office, travel or play guitar and sing in a pretty bad band.