In part 1 of this guide I had a look at the HTTP API in general. We learned what HTTP is, talked about the structure of HTTP requests and responses and how action types and URLs come together to determine what you receive in exchange for your request. In this post we are going to take a look at the WordPress HTTP API.

The WordPress HTTP API

Since around version 2.7 WordPress has had an API for handling HTTP. It is comprised of 9 functions, out of which you will probably only use a couple. The functions can be filed into two distinct groups – one for making requests, one for reading results.

wp_remote_get(), wp_remote_post(), wp_remote_head() use the GET, POST and HEAD methods respectively to request data from a given URL. The wp_remote_request() function is a general function that allows you to specify a URL and a method to go along with it.

The functions used for reading responses are similarly self-describing. wp_remote_retrieve_body() gets the response’s body, the wp_remote_retrieve_header() function gets a named header. The wp_remote_retrieve_headers() function returns all headers in array form, wp_remote_retrieve_response_code() gives you the response code and wp_remote_retrieve_response_message() returns the response message.

That’s basically all there is to it, all we need to do know is figure out how to specify headers to make proper requests.

Making Requests

Let’s use the wp_remote_get() function to make a request. We’ll use the first parameter to set the URL and the second to add arguments. You can find the full set of parameters supported in The Codex, I’ll focus on header information here.

To get a user’s status message from Twitter you’ll need to use the statuses/user_timeline.json path alongside the URL and pass a bearer token for authentication – which I have generated earlier. The bearer token needs to be added as an authorization header in the form of Bearer [TOKEN].

$token = 'Sijbwrf82wdaBief'; 
$response = wp_remote_get('', array(
    'headers' => array(
        'Authorization' => 'Bearer ' . $token

Making this request returns a wealth of information which can be obtained by printing out the $response variable. You can also use the wp_remote_retrieve type functions to get a part of the response.

Most of the time the body contains the necessary information, usually in JSON format. In PHP we can convert that to an array with ease:

$data = json_decode( $response['body'], true ) 

Accessing the Github API

Let’s build a quick example that will list our latest Github repos in a WordPress widget. First, you’ll need to log in to Github and go to your profile, edit it and go to “Personal access tokens” where you can generate a token.

Github Access Tokens
Github Access Tokens

As a next step, let’s create an empty widget template. This widget will have two options: a place for you to add your API token and a title. This is not the best method as it saves your token in the database, but is fine for our example purposes.

class My_Github_Widget extends WP_Widget {

	public function __construct() {
			'My Github Repos',
			array( 'description' => 'A widget that showcases your Github repos' )

	public function widget( $args, $instance ) {
		// Widget output

	public function form( $instance ) {
		$token = ! empty( $instance['token'] ) ? $instance['token'] : '';
		$title = ! empty( $instance['title'] ) ? $instance['title'] : 'From Github';
<label for="get_field_id( 'title' ); ?>">Title <input class="widefat" id="get_field_id( 'title' ); ?>" name="get_field_name( 'title' ); ?>" type="text" value="">

<label for="get_field_id( 'token' ); ?>">Github API Token <input class="widefat" id="get_field_id( 'token' ); ?>" name="get_field_name( 'token' ); ?>" type="text" value="">

<?php } }

I don’t want to go too much into how widgets are created here. If you want to know more, take a look at the Widgets API guide in the Codex. The important bit is that the content of the widget() method will output the content of our widget. Inside that function, we’ll connect to Github using an HTTP request then format and output the response. Here’s how all that is done – all the following code goes into the widget() method.

echo $args['before_widget']; 

if ( ! empty( $instance['title'] ) ) { 
  echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ). $args['after_title']; 

$args = array( 
  'headers' => array( 
    'Accept' => 'application/vnd.github.v3+json', 
    'Authorization' => 'token 3f4f654ab31c2f15e839c74c952e5de2f562f1ee' 

$response = wp_remote_get( '', $args ); 
$repos = json_decode( $response['body'], true ); 

if( !empty( $repos ) ) { 
  echo '<ul>'; 
  foreach( $repos as $repo ) { 
    echo '<li><a href="' . $repo['url'] . '" target="_blank">' . $repo['name'] . '</a></li>'; 
  echo '</ul>'; 

echo $args['after_widget'];

It starts with simply adding the widget’s wrapper element and title at the top and ends by closing the widget’s wrapper, the main section of the code is between the two.

First I set up my HTTP request headers. The first question may be: how do I know which parameters to add? The Authorization header is the most important bit, I read that in the Authentication section of the API docs.

The Accept header is not required but at the top of the very same docs page the guide encourages you to provide this.

I then use json_decode() on the body of the response and simply cycle through the resulting array, creating a list of links.

Next Steps

If you think that was easy, you’re totally right, it is! The difficult bit is making sure you have all angles covered without wasting resources. There are two issues with the code that would require our immediate attention.

If there is any issue with the API – which may include unknown errors, rate limited accounts and so on – we may bump into a big error. We’re just checking if the body is empty or not before we show the list.

If we have an error on our hands the body is likely to contain error information so it would not be empty in this case either. It is likely that we would list the elements of the error response, but since these would not have url and name properties we would end up with empty list elements and PHP warnings.

The second issue is that this is just wasteful. We’re connecting to an external service on every page load which may take a toll on our servers and may cause the account to be limited on Github. Even if this isn’t the case, how likely is your Github repo list to change between two page views, and how important is it to have up to the second info here?

I would personally recommend using transients in a case like this. A transient allows you to store the response of the request with an expiration time. If you set the expiration to a day the data will be retrieved from Github once, then straight from your database for the next 24 hours. After expiration it is retrieved from Github again and saved to the database.

This reduces your API calls from one per page load to one per day, which is a huge improvement and not much of a tradeoff either.


WordPress makes it easy to interact with APIs from around the web. Using a couple of built-in functions will allow you to pull in richer and more relevant data for your users.

Coupled with sanitization, error checking and a caching mechanism you can build an efficient application which is not only more useful, but is less resource intensive than you might image.

If you’ve used the WordPress HTTP API to connect WordPress with a third party API let us know, it would be great to hear about your work!

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.