Menu

WordPress REST API with Read and Post Examples

May 29, 2017 - WordPress

Main Resources

WP REST API
REST API Handbook
Nonce
Nonce tips and tricks

The WordPress REST API provides API endpoints for WordPress data types that allow developers to interact with sites remotely by sending and receiving JSON (JavaScript Object Notation) objects.

WordPress REST API is natively available in version 4.7 and above, for versions before you can use the plugin.

Show available routes

A route in WordPress REST API is a URI which can be mapped to different HTTP methods.

Example: https://ma.tt/wp-json/

/wp-json/

Example list of routes:

/wp/v2/posts
/wp/v2/pages    
/wp/v2/media    
/wp/v2/types    
/wp/v2/statuses 
/wp/v2/taxonomies   
/wp/v2/categories   
/wp/v2/tags 
/wp/v2/users    
/wp/v2/users/me 
/wp/v2/comments 
/wp/v2/settings

Within each route the JSON will also show us available endpoints. Each has a descriptionand options in enum.
For example in routes/wp/v2/posts we can see a bunch of available endpoints for GET method.
Here is a non-exclusive list:

page
per_page
search
author
offset
order
orderby
slug
status

Read

GET requests

/wp-json/wp/v2/posts
/wp-json/wp/v2/posts_categories=1&per_page=5
/wp-json/wp/v2/posts
/wp-json/wp/v2/pages    
/wp-json/wp/v2/media    
/wp-json/wp/v2/types    
/wp-json/wp/v2/statuses 
/wp-json/wp/v2/taxonomies   
/wp-json/wp/v2/categories   
/wp-json/wp/v2/tags 
/wp-json/wp/v2/users    
/wp-json/wp/v2/users/me 
/wp-json/wp/v2/comments 
/wp-json/wp/v2/settings

Display post on WordPress Page

Code example inspired by LearnWebCode.

In your theme create a new folder /js and put main.js in it

// main.js
console.log('JS works')

Open or create functions.php file in your themes folder and enqueue a script (aka the file main.js) with the following code:

// functions.php

function my_resources() {
    wp_enqueue_script(
        'main_js',     // name of the script
        get_template_directory_uri() . '/js/main.js', // location of the script
        NULL,          // dependencies
        1.0,               // script version
        true             //  loads script in the footer
    );
}

add_action('wp_enqueue_scripts', 'my_resources');

You can now test if the Javascript file was loaded by going to the main page of the blog and checking the console.

Next we will create a button on one of the pages so that we can execute main.js when we wish.

Open any page in the editor (I will use sample page) and add a button to the content:

<button id="load">Click me!</button>
<div id="surprise"></div>

Now, let’s change the main.js file and make sure the surprise is revealed when we click the button.

// load in the button
var showMeSurprise = document.getElementById( 'load' );

// if button is present on the page
if ( showMeSurprise ) {
// add event listener
  showMeSurprise.addEventListener( 'click', function () {
    var promise = new Promise( ( resolve, reject ) => {
        // get the posts from ma.tt
      var request = fetch( 'https://ma.tt/wp-json/wp/v2/posts' )  
        .then( response => {
           // Check if we got 2xx response from the server and resolve or reject
          response.ok ? resolve(response.json()) : reject( Error( response ) );
        } )
        .catch( error => {
          display( error );
        } );
    } );

    promise.then( data => {
      // save the name of the blog in a variable
      var title = data[ 1 ].title.rendered.toString();
            // add title to the page
      display( title );
      console.log( title );
    }, error => {
      console.log( error );
    } );
  } );
}

// helper function to display data
function display( data ) {
  var placeholder = document.getElementById( 'surprise' );
  var textnode = document.createTextNode( data );
  var theString = `<p>${data}</p>`;
  placeholder.innerHTML = theString;
  showMeSurprise.remove(); // remove button as the data is now loaded
}

Now, click the button and the title of the post will be displayed.

Create post and save it in WordPress

Here is a bit more complicated task – creating a new WordPress post! It is very similar to displaying it, however when we are publishing content we also need to make sure we authenticate ourselves as admins. In this example we will use Nonce.

We will start by adding a form to a desired WordPress Page (for example: sample page – where the button was previously placed)

<div id="admin-quick-add">
    <h3>Quick Add Post</h3>
    <input type="text" name="title" placeholder="Title">
    <textarea name="content" placeholder="Content" rows="8" cols="80"></textarea>
    <button type="button" id="quick-add">Create Post</button>
</div>

Now, we will update functions.php to add a nonce number the code below (function wp_localize_script was added)

// functions.php
function my_resources() {
   wp_enqueue_script(
        'main_js',
        get_template_directory_uri() . '/js/main.js',
        NULL, // dependency
        1.0, // version
        true  // loads script in footer)
    );

    wp_localize_script(
        'main_js',                // handle - name of script name
        'magicalData',            //  name - name of the object we want to output
        array('nonce' => wp_create_nonce('wp_rest')) // data - output
    );
}

It willl be displayed in the browser as:

Now, update main.js to listen for the submit button click and send the new post to WordPress.

// main.js
var quickAddButton = document.querySelector( '#quick-add' );
// console.log( magicalData.nonce );

if ( quickAddButton ) {
  quickAddButton.addEventListener( 'click', function () {
    console.log( 'new post button was clicked' );


    var formTitle = document.querySelector( '#admin-quick-add input[name="title"]' );
    var formContent = document.querySelector( '#admin-quick-add textarea[name="content"]' );

    var postContent = {
      'title': formTitle.value,
      'content': formContent.value,
      'status': 'publish' // or draft if you don't want to publish it
    };

    console.log( postContent );
    var createPost = new Promise( ( resolve, reject ) => {

      var headers = new Headers( {
        'Content-Type': 'application/json;charset=UTF-8',
        'X-WP-Nonce': magicalData.nonce
      } );

      var post = fetch( 'http://localhost/wprestapi/wp-json/wp/v2/posts', {
          credentials: 'same-origin',
          method: 'POST',
          body: JSON.stringify( postContent ),
          headers: headers
        } )
        .then( response => {
          console.log( response );
          if ( response.ok ) {
            return resolve( response );
          } else {
            reject( Error( response ) );
          }
        } )
        .catch( error => {
          console.log( error );
        } );
    } );

    createPost.then( data => {
      // display the name of the blog
      console.log( data );

    }, error => {
      console.log( error );
    } );
  } );
}

All done! Now, when you reload the page, add the title, content and click submit button, new post is published.