Writing a WP REST API endpoint in 2 minutes

I need to write a REST API endpoint, but lets assume we know nothing about REST APIs.

The Task

My homepage has a box that contains a magical word, and I’m going to use the REST API to grab this word and display it on my site:

<div id="tomsword">... word goes here ...</div>

I’m going to need:

  • A word to use, I’ve chosen “moomins”
  • A REST API endpoint on my site to send the word from
  • Some Javascript to ask the API for the magic word

The Endpoint

This parts easy. REST API endpoints live at /wp-json, and they have a namespace so your endpoints don’t clash with those of other plugins. My endpoint is going to live at tomjn.com/wp-json/tomjn/v1/test.

When my endpoint is called, I want to return the word “moomins”, so I’ve prepared a function to do just that:

function tomjn_rest_test() {
        return "moomins";
}

and I’ll register my endpoint, and tell WordPress what to do when it’s called like this:

add_action( 'rest_api_init', function () {
        register_rest_route( 'tomjn/v1', '/test/', array(
                'methods'             => 'GET',
                'permission_callback' => '__return_true',
                'callback'            => 'tomjn_rest_test'
        ) );
} );

Congrats! I now have an endpoint, and you can see it by visiting https://tomjn.com/wp-json/tomjn/v1/test :

As for what those parameters do:

  • tomjn/v1 is the namespace and beginning of the URL ( /wp-json/tomjn/v1/test )
  • /test/ is the name of the endpoint ( /wp-json/tomjn/v1/test )
  • 'methods' => 'GET' tells it to respond to normal browser GET requests, like <form method="get"... or just loading the page in a browser via the address bar
  • 'permission_callback' => '__return_true', is a chance to name a function that controls if the user can or cannot use this. I’ve chosen __return_true so everybody can use it
  • 'callback' => 'tomjn_rest_test' when someone uses this endpoint, call the tomjn_rest_test function to get the answer

Using our Endpoint in The Theme

Let’s write some javascript in our template:

<script>
jQuery.ajax({
    url: <?php echo wp_json_encode( esc_url_raw( rest_url( 'tomjn/v1/test' ) ) ); ?>
}).done(function( data ) {
    jQuery( '#tomsword' ).text( data );
});
</script>

It’s that simple! Now our homepage runs a bit of code when we load it, that fetches a word from a REST API, and puts it in a div.

Writing REST API endpoints is quick, and easier to secure. There’s no reason to use the AJAX API in the future.

33 thoughts on “Writing a WP REST API endpoint in 2 minutes

  1. Thanks for the post. Good intro to adding an endpoint and how to use.

    Should the PHP perhaps replace esc_url() with wp_json_encode()? The former adds HTML entities (which may not be interpreted properly by the JS parser) while the latter adds the double-quotes with JS esscaping for you (which ensures there won’t be a JS syntax error).

    • Possibly, my understanding is that the result of esc_url is always a URL, even if it’s a mangled one, which was my intention.

      It’s possible that wrapping it in another function such as wp_json_encode may avoid the situation you mentioned, but I’d err on secure but broken code over trying to make it always syntactically perfect. Having said that wp_json_encode would also prevent injection attacks 🙂

      • I think then that it could use esc_url_raw() because it doesn’t add HTML entities (for sake of use in href attributes). So like:

        echo wp_json_encode( esc_url_raw( rest_url( 'tomjn/v1/test' ) ) )

      • Here’s a simple example to illustrate the problem, in a script tag:


        console.info( "<?php echo esc_url( rest_url( '/wp/v2/posts/?s=test&status=draft' ) ) ?>" );

        Notice that this will output to the console:

        http://example.com/wp-json/wp/v2/posts/?s=test&#038;status=draft

        Notice how the query params are corrupted in the JS string value. However, doing the follow gets you the expected result printed to the console:

        console.info( <?php echo wp_json_encode( esc_url_raw( rest_url( '/wp/v2/posts/?s=test&status=draft' ) ) ) ?> );

        This isn’t really a problem in the example you give, but since the return value of rest_url() has a rest_url filter, it is possible that a plugin could be attempting to add query params to the REST URL and if they did, the params would be corrupted if passed through esc_url() in this context.

  2. Thanks for this great article Tom. This is by far the most understandable micro tutorial about custom WP REST API endpoints I’ve ever read.

    Unfortunately while following your steps I run into an issue. I needed to change get_rest_url( ‘tomjn/v1/test’ ) to get_rest_url( null, ‘tomjn/v1/test’ ). The first call only gave me the REST url (https://tomjn.com/wp-json), whereas the second call gave me the full path (https://tomjn.com/wp-json/tomjn/v1/test). Might this be a glitch on my machine?

  3. Pingback: Introduction – WordPress API tutoriel

  4. Pingback: Ajouter ses propres Endpoints – WordPress API tutoriel

  5. Pingback: Ajouter ses propres Endpoints – #1 – WordPress REST API

  6. Pingback: Références – WordPress REST API

  7. Pingback: Introduction – WordPress REST API

  8. Missing some key information here for those of us who have been away from WordPress for a very long time:

    – Where do I put the tomjn_rest_test() function? What’s the filename? I assume it lives in /wp-json/tomjn/v1/test, but every time I make an assumption I am wrong.

    – Where do I register the call? The same file? Somewhere else?

    Thanks man!!

  9. Pingback: Unicorn Heaven! Highlights From WordCamp Edinburgh 2017

  10. Pingback: Writing a WordPress REST endpoint in 2 minutes – Full-Stack Feed

  11. Very good explanation. Could you offer one or two examples of a more real-world scenario in which this kind of thing would be useful? I’d really like to start using the REST API more but I have yet to find a situation where I really need it for anything.

    • Any situation that involves JS contacting your site, be it to fetch posts, create posts, or retrieve other information. E.g. infinite scroll, form submissions, user settings, post widgets, etc

  12. I like the way you laid it out and made it feel so approachable 🙂

    Just noted your last sentence :

    “There’s no reason to use the AJAX API in the future.”

    Perhaps you mean :

    “There’s no reason NOT to use the AJAX API in the future.” ?

    Cheers !

  13. Pingback: Rest API instead on .JS file – WordPress Solutions Group

  14. Pingback: The Top 100 Most Commonly Used WordPress Functions - Vegibit

  15. Pingback: Weekly WordPress News: Should You Sell Themes or Plugins?

  16. I type link Rest API: …/wp-json/wp/v2/posts?orderby=rand&per_page=6 to get random post, but the result is only one time, the next times are not random anymore.
    How to to fix it?
    Thanks bro

    • Hey Trường, sounds like you have a general support question, you should ask on the .org forums.

      Keep in mind though, that asking the database to randomly order the posts is incredibly expensive, and super heavy on the database. It’s one of the worst things you can do for performance, wether you do it via WP_Query or the REST API or another method, always do it in JS, not the database.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.