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',
                '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 :

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.

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

Leave a Reply

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