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 responses to “Writing a WP REST API endpoint in 2 minutes”

  1. Weston Ruter avatar

    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).

    1. Tom J Nowell avatar

      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 🙂

      1. Weston Ruter avatar

        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' ) ) )

      2. Weston Ruter avatar

        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.

        1. Weston Ruter avatar

          …and WordPress ate the code in my comment. In the first URL example, I tried to show the ampersand would get encoded an HTML entity and not be converted back into an ampersand when parsed by JS.

        2. Tom J Nowell avatar

          This makes sense, I’ll update the post and I fixed the ampersand in your example

          1. Weston Ruter avatar

            Thanks! Also you need to remove the literal double quotes in your example since wp_json_encode() will add them.

  2. Niels Lange avatar

    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?

    1. Tom J Nowell avatar

      good catch! rest_url is what I should have used, which does exactly what you suggested internally 🙂

  3. Anh Tran avatar

    Very easy to understand!

    By the way, I love the huge typography here! Easy to read 😉

  4. @ChuckReynolds avatar

    Nice! That’s absolutely the simplest example I’ve seen thus far. Cheers!

  5. […] y aussi en anglais : Writing a WP REST API endpoint in 2 minutes, qui comme son nom l’indique ne prend que 2 minutes. J’y […]

  6. […] Etudions la doc : Adding Custom Endpoints et Writing a WP REST API endpoint in 2 minutes […]

  7. […] Etudions la doc : Adding Custom Endpoints et Writing a WP REST API endpoint in 2 minutes […]

  8. […] [4] Writing a WP REST API endpoint in 2 minutes […]

  9. […] y aussi en anglais : Writing a WP REST API endpoint in 2 minutes, qui comme son nom l’indique ne prend que 2 minutes. J’y […]

  10. Joe Howes avatar

    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!!

    1. Tom J Nowell avatar

      These are standard hooks, and you’d use them the same way you’d use any other hook in WordPress, just as you might have done 3 or 6 years ago. I won’t go into how to use actions and filters though as it’s covered far better in the Developer Handbook on WordPress.org than I could in a comment

      1. Joe Howes avatar

        Understood.

        For anyone else like me who visits this page, this is the starting point that I assume Tom is referring to:

        https://codex.wordpress.org/Plugin_API

      2. Joe Howes avatar

        I have this working now.

        If you are authoring a theme (not a plugin), you can add the function and the REST route registration to your theme’s “functions.php” file.

        Very easy to understand and takes no time at all.

        Here is an answer to my StackOverflow question which lead me to this very simple and trivial answer:

        https://wordpress.stackexchange.com/questions/267491/when-adding-a-custom-rest-endpoint-where-do-you-put-the-endpoint-function-and/267496#267496

        1. Steven J Horkey avatar
          Steven J Horkey

          Thank you, THIS is what a helpful comment looks like.

  11. […] Read Tom’s blog post on making simple REST endpoint. […]

  12. […] I need to write a REST API endpoint, but lets assume we know nothing about REST APIs. Read more […]

  13. Bill avatar

    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.

    1. Tom J Nowell avatar

      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

  14. Jono avatar

    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 !

    1. Tom J Nowell avatar

      Thanks! In the last bit I was referring to the admin AJAX API that rest replaces

  15. Quint avatar

    Your post helped crystalize what an endpoint is, what a route is, and why it matters. Write more… 🙂 Thanks!

  16. […] Writing a WP REST API endpoint in 2 minutes […]

  17. […] Writing a WP REST API endpoint in 2 minutes – the REST API doesn’t have to be scary. […]

  18. Trường avatar
    Trường

    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

    1. Tom J Nowell avatar

      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.