As you may or may not know, the WordPress JSON REST API is on the horizon for a future version of WordPress. This will be one of the most important and influential additions to WordPress core we may see, especially for those using WordPress as a framework to create web and mobile applications. The inclusion of a standard, easy to use and extendable API for WordPress opens up a myriad of new possibilities on how we build applications with WordPress in the future
But what if you don’t want to wait for inclusion of the WP-API or use the official plugin version of the WP-API, where do you go? Maybe you just have a small bit of information that you would like to access in a JSON format. This could be needed for an AJAX call within your site or to allow a third-party to access some of your data. I will show you a quick way to set up your own endpoint and return your data in JSON format.
Set Up Our Example
For our example, we have the highly critical task of creating a place to store our animated GIFs and provide an easy way to access the links from a third-party. We want to access this by passing in a tag and all we need to get back is the link to the gif and a short description of it. For this, we will create a new CPT with just the featured image and title and a non-hierarchical taxonomy.
function wds_gif_cpt_and_tax() { $cpt_args = array( 'label' => 'GIFs', 'show_ui' => true, 'supports' => array( 'title', 'thumbnail' ), ); register_post_type( 'wds_gif', $cpt_args ); $tax_args = array( 'label' => 'GIF Tags', ); register_taxonomy( 'wds_gif_tag', 'wds_gif', $tax_args ); } add_action( 'init', 'wds_gif_cpt_and_tax' );
Create our Endpoint
Next we will use part of the WordPress rewrite API to properly register a rewrite tag and then add a rewrite rule so we can access this at http://example.com/gifs/tag/
. For this, we use the functions add_rewrite_tag()
and add_rewrite_rule().
As you can see, we use a simple regular expression to parse out the tag that is being passed to the endpoint URL. We will be using this tag later to query our GIFs custom post type.
function wds_gif_endpoint() { add_rewrite_tag( '%wds_gif%', '([^&]+)' ); add_rewrite_rule( 'gifs/([^&]+)/?', 'index.php?wds_gif=$matches[1]', 'top' ); } add_action( 'init', 'wds_gif_endpoint' );
Outputting the Data
Now we need to get the data out to our new endpoint so we can have access to those crucial animated GIFs. We are first going to call the $wp_query
global so we can properly get find the rewrite tag from our URL. We are checking for the existence of the wds_gif
query string, which we rewrote to /gifs/
in our URL. If this doesn’t exist, we will return and bail out of this function. If it works, we set up our array which we will be passing out in JSON format and then run a standard WP_Query loop for our new custom post type. We are going to be running a taxonomy query on this for the tag which was passed after /gifs/
in the URL.
Upon completion of the loop, we will send out the array of data in JSON format using wp_send_json()
. This function will encode the array as JSON, echo it, and then run wp_die()
to end any other actions that may happen later.
function wds_gif_endpoint_data() { global $wp_query; $gif_tag = $wp_query->get( 'wds_gif' ); if ( ! $gif_tag ) { return; } $gif_data = array(); $args = array( 'post_type' => 'wds_gif', 'posts_per_page' => 100, 'wds_gif_tag' => esc_attr( $gif_tag ), ); $gif_query = new WP_Query( $args ); if ( $gif_query->have_posts() ) : while ( $gif_query->have_posts() ) : $gif_query->the_post(); $img_id = get_post_thumbnail_id(); $img = wp_get_attachment_image_src( $img_id, 'full' ); $gif_data[] = array( 'link' => esc_url( $img[0] ), 'title' => get_the_title(), ); endwhile; wp_reset_postdata(); endif; wp_send_json( $gif_data ); } add_action( 'template_redirect', 'wds_gif_endpoint_data' );
The Results
Now, you can enter your favorite animated GIFs into the WordPress admin under the new Custom Post Type and tag them with some proper keywords and you will be able to use an easy URL to access this data in JSON format by appending the slug of the tag in the URL. For example, you could use http://example.com/gifs/arrested-development
to access all of your favorite GIFs of the Bluths. You will be presented with a nice array of JSON data as seen below.
Why Use This Method?
Of course, this isn’t the only method to get your data. As stated above, the WP-API is on the horizon. That would open up a common API to all parts of WordPress that you can build upon and will be the standard in the future. Sometimes, though, you may need some quick and dirty data. This can be used to grant access to a third-party service or when you are making front-end AJAX calls on your own site.
You may ask, why wouldn’t you use admin-ajax.php
to make those AJAX calls? When using admin-ajax.php
, you are tapping into the WordPress admin and loading code that isn’t necessary. WordPress does not cache requests, for good reason, within wp-admin. If you have a high traffic site, or want the best possible performance, you definitely want to make use of caching whenever possible. Using admin-ajax.php
on the front-end could potentially bring down a high traffic site if not used properly. When you create your own endpoint, you can feel free to add in your caching as you see fit.
In Summary
This is an easy method to get some JSON data from your WordPress site. We wrote a small API to our site that can output the data that we need. We used the WP Rewrite API to create an easy to remember URL to access the data and then ran a standard WP_Query and output this in JSON Format. This can be used as a quick method to provide just the data you need and allows for higher performance including the use of caching when using AJAX on the front-end.
Thanks for the great example! I used this today
Using the ideas in this post, I’ve created a gist that can serve as a boilerplate / starter kit for making your own json endpoint. https://gist.github.com/daggerhart/eceead9a5ee73eea608e
Thanks again Dustin!
I know this is an older post, but I’ve got a very specific question about the code that might be useful to other people.
Specifically, when employing the method above, we get a 404 error on the results pages. This is an issue for our javascript wizard that’s connecting with the API.
Is there a way to send a valid header? One article I found suggested using admin-ajax.php, which you do not recommend.
Help? Advice? Anything would be appreciated! 😉
Answered my own question: adding status_header(200); just before the wp_send_json(); statement fixed the 404. Easy-peasy.
Thanks for leaving your solution here, Jason. In my basic application, I wasn’t checking the status at all when getting the json data. Your solution would set the headers properly when your application does. Thanks for adding to the value of the post.
Also, there was a CORS issue when I used status_header(). The solution was to add the following code to my plugin:
add_action( ‘init’, ‘handle_preflight’ );
function handle_preflight() {
header(“Access-Control-Allow-Origin: *”);
header(“Access-Control-Allow-Methods: GET”);
}
Thanks again. I was working on the same site. In that case, we wouldn’t have to worry about CORS.
Thanks Man!
You rescued me after few hours of banging my head against the wall. I got the correct JSON together with 404. All other answers in the internet where not relevant. None of the examples includes “status_header(200);”.
IOU.
Thank you for the helpful article on creating a custom endpoint in JSON.
It helped me a lot to achieve something.
However what’s the method you suggest to retrieve the data in the front end?
wp_remote_get(), file_get_contents() and curl isn’t working for me.
Can you please shed some light in it?
Its great, Thanks…
i need to create a a form in my website that connect with this url api : https://api.beds24.com/json/createAccount to give the possibility who buy an our sub account to create it self.. i have seen the script api jason:
{
“authentication”: {
“apiKey”: “apiKeyAsSetInAccountSettings”
},
“createAccount”: [
{
“username”: “username”,
“password”: “password”,
“apiKey”: “YourKeyToUseForTheNewAccount”,
“email”: “[email protected]”,
“role”: “0”
}
]
}
There is a sample PHP script here to modify property details: https://api.beds24.com/json/modifyProperty
It could be modified to work with the createAccount function and my form.
than i need also the response page from api translate in my web page
i need to create a form in my web page where the custmer nedd to add 4 element:
username”: “username”,
“password”: “password”,
“apiKey”: “YourKeyToUseForTheNewAccount”,
“email”: “[email protected]”,
“role”: “0”
the role is standard for hall and must be hide from the form
so also my api key for example
“authentication”: {
“apiKey”: “apiKeyAsSetInAccountSettings”
this code in the form need to point to this page https://office.bookinguide.cloud/api/json/createAccount
and retur in other url wit the eco of the new value
this i an action new sub account
here the complete script jason
{
“authentication”: {
“apiKey”: “apiKeyAsSetInAccountSettings”
},
“createAccount”: [
{
“username”: “username”,
“password”: “password”,
“apiKey”: “YourKeyToUseForTheNewAccount”,
“email”: “[email protected]”,
“role”: “0”
}
]
}
This is great :).
Is it any way to get $_POST parameter in this function?
So i can select json data filter by $_POST parameter.
Thank you.
Pardon me if I’m misunderstanding. Lets say we put your endpoint function on some custom page or in functions.php. Now requests sent from javascript will be served from functions.php which is loaded after wp core stretches its muscles. Requires wp_options wp-config and wp-load etc or maybe more files.
When sending request thru admin-ajax.php, Its a simple php file which also loads wp-load.php ajax-actions.php and later functions.php. Also wp-admin.php leaves the unwanted core files without loading. Whereas sending request to function residing anywhere in wordpress theme files will be loaded through whole wordpress environment?
Hi, thanks for the cool post. I’m not sure if your post about admin-ajax.php is correct. In my previous research as I understood it, it is just poorly named. It is ok to use it for front and back end applications. Do you have any link to further information about that point?