Getting Posts By Taxonomy Or Meta Field With WP-API v2.0

Mar 03, 2016 UPDATED:

Updated all routes in this post so now should be compatible with WP API V2 beta 12.

Feb 28, 2016 UPDATED: 

Just realised since v2 beta 4, /posts WP_Query vars was moved back to filter param. I'll update all routes in this post ASAP.

In the post adding fields to the JSON response of the WP REST API, you’ve learned about how to manipulate the data from the WP REST API (WP-API). Another topic I got asked very often, is how to get posts by certain filters – mostly taxonomy and meta field. So today let’s talk about it.

Before we get started, if you’re looking for the workarounds for WP-API v1.x, Josh has written great tutorials for you. Here are the links of them:

  1. Working with Taxonomies Using the JSON REST API
  2. Working with Meta Data Using the JSON REST API

In the following article, I’ll show you the quick answers and a more bigger picture beyond them. If you’re not interested in the later one, feel free to skip it.

The Quick Answers

*** Please note, starting from WP API v2 beta 4, you need to set "show_in_rest" => true when registering a custom post type or taxonomy, to get it exposed to the JSON response. ***

So here are them. If you want to get posts by taxonomy with WP-API v2.0, you can use the endpoint/route like this: (job-type is the taxonomy and manager is the term you want to match)


Please note if you set the query_var to false when registering the custom taxonomy, you’ll need to change the parameters to:


As to the default taxonomy – tag, the rule applies too:


But you need to be careful that with another default taxonomy – category, the parameter to use is categor_name, so it’s like:


Get Posts By Meta Field Is Not Available By Default

When it comes to meta fields, you might already know that this is not working with WP-API by default (for security reason). When using the terms “by default”, you must be very happy to expect a workaround to hack it. And almost everything magic in WordPress is related to a hook – action or filter, so which is to the rescue in this case?

That’s it: the rest_query_vars filter. Here’s how to use it:

With the hook, now you can use the route below to query posts by meta:


BTW, If you’re interested in getting custom post types worked with WP-API v2, please refer to the tips shared by @joneslloyd.

What about meta_query for complex meta key/value pairs?

If you want to query posts based on multiple meta key/value pairs, you must use meta_query to do so. As the example above, we also need to add it to the valid query variables, like this:

And then you can use meta_query with WP API v2. I know some people stuck in how to write arrays as GET/POST parameters, since meta_query is an array composited by arrays, which looks pretty scary when thinking of converting it to URL parameters for /posts route in WP API.

Luckily I found MailChimp have documented it in their API docs, be sure to check it out!

What’s The Bigger Picture?

When I was a junior developer (around 2007 – 2008), one of the things bothered me most is when the library or code I was working with wasn’t well documented. To be honest, back to those days I could barely get the job done even when the documentation was thoroughly. For example, I couldn’t build a web application with Zend framework on my own, which was very well documented then as I recall.

Years went by luckily I developed a few problem solving skills on programming, one of them is to refer to the source code when I can’t get clear answers from the documentation.

The series of building themes with AngularJS and WP REST API was focus on the AngularJS in the first 14 posts. But then I realized I need to spend more time with WP REST API since sometimes the questions from my readers can be solved easily if they understand better how the WP-API or WP_Query works.

It’s all about the query_vars

So let’s take a look at a simple but powerful function from the source code of WP-API:

This get_allowed_query_vars function is from the WP_REST_Posts_Controller class, which is in charge of what query variables (that we pass to the route like category and tag) can be used to get posts with WP-API.

This function does the following jobs:

  1. Line 16: Get all valid query variables from $wp->public_query_vars. We’ll introduce what exactly they are later.
  2. Line 18-33: If the user can edit_posts, she/he can access more query variables with $wp->private_query_vars, we’ll also talk about them later.
  3. Line 35: There are three more query variables added by WP-API: posts_per_page, ignore_sticky_posts and post_parent
  4. Line 47: At the end of this function, we can use the filter rest_query_vars to modify all the query variables available. For example we can add or remove variables here. (We just learned the trick minutes ago.)

The public and private query variables lists

There’s a page on the WordPress codex for this but it seems not quite completed, so let’s look into the source code again, but in WordPress itself this time.

Tracing to the wp-includes/class-wp.php, you’ll see the two variables we’re looking for: $public_query_vars and $private_query_vars. Besides these variables when we register custom post types or taxonomies, if we set the query_var to a string (can’t be empty string of course), it will be joined to the $public_query_vars family.

Why posts_per_page Doesn’t Work (At Least In v2.0-beta3)

Now we know how many query variables are available. But after some tests I found a very interesting fact: the posts_per_page parameter isn’t working.

I took another look at the source code of WP-API. From the same class (WP_REST_Posts_Controller), the get_items function helped me to figure that out:

At line 15 (from the gist above), you can see the WP-API actually gets posts_per_page from another parameter called per_page but not the posts_per_page itself. I haven’t investigate every piece of code in WP-API so I can’t think of a good reason why it does so.

From this issue on the GitHub repo of WP-API, I think the developers are still working on the arguments style (see this comment). It’s a very informative discussion so be sure to check that out.

Improving The Security Of Meta Query When Working With WP-API v2.0

If you’ve kept an eye on WP-API for a while, you must notice that every time someone asks about the “meta query”, she/he will be reminded that “there might be some security risks” if exposing meta values to the WP-API.

I never store any confidential or sensitive data in post meta so I really hope things can be easier. But since WordPress and WP-API don’t work that way, let’s see what else we can do.

Limiting The Meta Keys Can Be Queried

No matter which filter you use to add the meta_key and meta_value to the $valid_vars (you can use query_vars, rest_private_query_vars and rest_query_vars), you basically allow all meta fields can be queried. If it’s too risky to you, try to limit the meta_key to only allowed fields with rest_post_query filter.

I hope you enjoy this post and would love to spend more time to know WP-API v2.0 better. If you encounter any question when following the steps from this tutorial, just shoot me an email: yoren [at], or ping me on Twitter (@1fixdotio), and comments are much welcome. Talk soon!

143 thoughts on “Getting Posts By Taxonomy Or Meta Field With WP-API v2.0”

  1. really good post, thanks for sharing your experience.

    Looks to me that there’s still quite some work ahead for the API to be production ready. Nevertheless, I think it’s going to be a huge step forward for WP, really looking forward to have a stable release.

    • Hi Luca, Yep the WP-API is going to be a huge thing to all WordPresser. I’m glad that we’re in good hands. Looking forward to the core integration too!

  2. Just in case anyone comes across this later as of WP-API V2 beta 4 the use of meta_keys and meta_values (and any other request variables) is done with filter now. So you would need to change the request URL from


    As with a lot of things in V2 of the API this isn’t documented but I came across it after hours of searching in a GitHub Pull Request.

  3. hai YOREN CHANG,
    i am trying to display tags associated with specific post
    for example, i have post with name ” hello world” and attached tag to this post like “test”,”wp” .
    now i am trying to display “hellowolrd” post along with its tags (‘test’,’wp’).
    I look into json of that post but it does not contain tag lists.
    can you suggest how to retrieve tag information of post.
    thank you

    • Hi, Nithin, just do so by accessing the route like http://[YOUR-URL]/wp-json/wp/v2/terms/tag?post=[YOUR-POST-ID], you’ll get the tags collection for the post.

  4. Hi Yoren,

    possible that you have a type here in your code? I see a double “s” in $args…

    unset( $argss[‘meta_key’] );

  5. Hi,

    Am I right in thinking that you can do this to get around the “post_status” filter without using oAuth ?

    I want to filter posts by ‘post_status’ => ‘future’ , as I am querying future events CPT. But I need to use an oAuth to use this, hoping a custom end point will get around this problem ?


  6. Thanks Yoren for the writeup. Do you know how to list all the default taxonomy terms and the custom taxonomy terms? I’ve tried the below route but it returns “rest_no_route”. This is how it was done in WP-REST-API version 1 but isn’t working in version 2.



  7. Hi, you already helped me a lot! Thanks!

    I have a problem with my custom taxonomy.
    I register it like this:
    $municipality_args = array(
    ‘labels’ => $municipality_labels,
    ‘hierarchical’ => true,
    ‘public’ => true,
    ‘show_ui’ => true,
    ‘show_admin_column’ => true,
    ‘show_in_nav_menus’ => false,
    ‘show_tagcloud’ => false,
    register_taxonomy( ‘municipality’, array( ‘ilcms’ ), $municipality_args );

    When I visit “/wp-json/wp/v2/taxonomies/municipality” I get:
    code: “rest_forbidden”,
    message: “You don’t have permission to do this.”,
    data: {
    status: 403

    Any ideas?
    I can’t find any solution to allow it in the rest api.

      • Hey, Thomas,

        Try to add `’show_in_rest’ => true` to the `$municipality_args` array. Now the WP API required `show_in_rest` if you want to expose a custom post type or taxonomy to the JSON response.

    • I helped asking you 🙂

      Like custom post types, you should add :
      ‘show_in_rest’ => true,

      Like this:
      $municipality_args = array(
      ‘labels’ => $municipality_labels,
      ‘hierarchical’ => true,
      ‘public’ => true,
      ‘show_in_rest’ => true,
      ‘show_ui’ => true,
      ‘show_admin_column’ => true,
      ‘show_in_nav_menus’ => false,
      ‘show_tagcloud’ => false,

  8. hi , i am using v2 api on my website ..

    But i need two filter together by category + date.. i have used in v1 version but in v2 it is not working..
    can you tell me how it will use in v2

    Thank you

    • Hi, Ashish,

      I haven’t tested but parameters work in WP_Query class should work for posts route in WP API v2.

      So I guess you can try:


      • Did you get anywhere with this? I have the same issue. The query I want is:

        date_query’ => array(
        ‘after’ => ‘2016-01-08 23:59:59’,

        put passing in an object is confounding me.

        • I’ve worked out the following. If there’s a better/easier way I’d love to hear about it.

          /* Add a fields to be allowed to searched via API */
          function mt_allow_meta_query( $valid_vars ) {
          $valid_vars = array_merge( $valid_vars, array( ‘date_query’ ) ); // ‘meta_key’, ‘meta_value’,
          return $valid_vars;
          add_filter( ‘rest_query_vars’, ‘mt_allow_meta_query’ );

          /* Add custom search for above field to REST API */
          function mt_rest_query_support($args, $request) {
          if( $args[‘modified_since’] !== ” ) {
          $args[‘date_query’] = array( ‘column’ => ‘post_modified_gmt’, ‘after’ => $args[‘modified_since’] );
          unset( $args[‘modified_since’] );
          return $args;
          add_filter( ‘rest_post_query’, ‘mt_rest_query_support’, 10, 2 );

          • Hey Chris, I was going to write a snippet like this, glad you’ve done it! Just it would be much secure if we sanitize the $args[‘modified_since’] with sanitize_text_field().

  9. Hi Yoren,
    My question is a bit off topic but your blog seems to be most responsive and I’ve gotten my last question answered here. That’s why I’m back; anyhow:

    On WordPress XML-RPC api, there is a method to get the site options called wp.getOptions. This method is quite important as it provides relevant meta data regarding the wordpress site. I do not see this being available on the /wp-json/wp/v2/ so I wonder if I have to manually add this endpoint my self. I think it’s a fairly useful endpoint to have built-in with WP REST API.

    Some of the information returned from wp.getOptions includes data such as: admin_url, blog_tagline, blog_title, blog_url, date_format, …


    • Hi, Loc,

      It’s a very excellent question! To obtain some basic options, you can visit the site index like:


      There are only 3 options can be access by default: name, description and url. So if you’d like to add more, just add filter to “rest_index” like this:

      function my_rest_index( $response ) {
        $response->data['admin_email'] = get_option( 'admin_email' );
        return $response;
      add_filter( 'rest_index', 'my_rest_index' );

      Let me know if that works for you. Cheers.

  10. I hope you don’t mind me asking another question about REST API. It appears that date filtering is not enabled by default with WordPress Core. Therefore, the following would not work:

    I’ve seen others recommended adding the following code to the active theme’s functions.php file should do the trick, so I tried but haven’t seen the light of it.

    function add_additional_meta_json_query_vars($filters){
    array_push($filters, ‘date_query’);
    return $filters;
    add_filter(‘json_query_vars’, ‘add_additional_meta_json_query_vars’);

    add_filter( ‘json_query_vars’, function ( $vars ) {
    $vars[] = ‘date_query’;
    return $vars;
    } );

    Any suggestion would be greatly appreciated. Thanks.

    • Hey, Loc,

      Glad you came back! I’m not sure if you still use WP API v1, but I’m sure if you’re at WP API v2, the following code should make the `date_query` work very well:

      function my_rest_query_vars( $valid_vars ) {
      	$valid_vars = array_merge( $valid_vars, array( 'date_query' ) );
      	return $valid_vars;
      add_filter( 'rest_query_vars', 'my_rest_query_vars' );


  11. hello dear.
    i have some question, i hope u can help me.
    1- in my test WordPress site, i have about 12 post, when i call:
    the result is an array which just have 10 member.
    how can i get all of my post in a call?

    2- Is there any default way to call all post and in the result doesn’t contain the content part and only contain excerpt part.
    i think it’s may have a bad effect on my app, because of the size of the content part, may have.

    3- is there a way to call a specif number of post? like 10 of them per call or page by page.

    4- is there any way to call posts by they tag name? i can find the category’s, and in the category there is a link which is refer to the all posts whit that category; but link show the post in the site(HTML).

    and i just forget my other questions :)))).
    so, any way, your post help me, special thanks for your post.
    PS: sorry for my amazing English. 😀

  12. Hi, i need help with the api,

    I am listing all the taxonomies correct, and i want to get the post inside


    – post
    – post
    – post
    – post

    I am doing in angular js but when i list the posts inside i get all of then instead of the ones with the taxonomies.

    Can you give an example that works.


  13. Hi Yoren,

    I almost got it right, the problem is It lists the posts inside the taxonomy, but it shows all the posts, intead of showing only the posts in the taxonomy.

    Any idea how to do it?


    • Hey Adolf, from your original question I though you were fetching “terms for a certain post”. Now from your answer, it’s for fetching “posts from a certain term”. So I guess both answers are right 😉

  14. Well, my answer actually retrieves specific terms —> category_name of a given post id, say i got an id of 5433, it was able to retrieve names of category of that post like “event or people”. Anyway Yoren, i have one more question.
    From this: “$http.jsonp( url ).then(function(response) {”
    -How do i get the id of a post without doing this: “angular.forEach(, function( value, key )” gets the id that i need, but I want something like: or….Thank you!

      • $rootScope.filterPosts = function(url) {
        $http.jsonp( url ).then(function(response) {

        angular.forEach(, function( value, key ) {
        $rootScope.itemID =;
        // I just want something like $rootScope.itemID =
        //so no agular.forEach if possible
        }, function(response) {


  15. Hey, I use version 2.0beta8 of WP REST API. While doing a GET /wp-json/wp/v2/posts query, I don’t seem to be able to get the “terms” child for the posts displayed. These are the only fields displayed:
    id, date, date_gmt, guid, modified, modified_gmt, slug, type, link, title, content, excerpt, author, featured_image, comment_status, ping_status, sticky, format, _links
    I have five categories and all my posts are of the type “post”.
    Thus, additionally, while trying to create a post, I am unable to post to a category of my choice, any new post I create via wp-api gets the default category designation I’ve set from wordpress dashboard.
    Hope you can help.

    • Hi, S0ft,

      To get the terms of a certain post, you could use route like: to get the terms for that post in a certain taxonomy. The terms data won’t be come with the single post route.

      As to the second issue, I can’t be very helpful since I have no idea how you publish the post via WP API.

  16. Is it possible to get a return of a category name within the /v2/posts/ json return? I just want a list of categories that becomes available, then once they click on the category it returns a list of posts within that category.

  17. Hello Yoren,

    I’m back! So the way I get comments from an article is by querying “” using $http.jsonp. I just want to ask if how do I post comment/s into posts. I know I need to use $, but how about the URL to where I am going to put the comment/s? Thanks in advance.

  18. Hey Adolf,

    Good to see you again!

    The route to create a comment is, and you’ll need to pass a few arguments to it, just check the official documentation here:, and search for “Create a Comment”.

    I haven’t really dealt with comments so if it dosen’t work, feel free to correct me. Thanks!

  19. Hi there. Thanks for this post.

    Do you know how to query posts by nested objects in acf?

    I can get post by meta key value at one level, e.g:

    ‘acf’ {
    ‘key-1’: ‘value-1’


    But I would like to query by a key in an array from acf, so getting key/value-2:

    ‘acf’ {
    ‘key-1’: ‘value-1’,
    ‘nested’: [{
    ‘key-2’: ‘value-2’

    Have any idea how to achieve this?



  20. thank you for sharing this post.
    can you help me please how to get like this query with wp rest api v2?

    $posts = get_posts(array(
    ‘numberposts’ => -1,
    ‘post_type’ => ‘post’,
    ‘meta_query’ => array(
    ‘relation’ => ‘AND’,
    ‘key’ => ‘color’,
    ‘value’ => array(‘red’, ‘orange’),
    ‘compare’ => ‘IN’,
    ‘key’ => ‘featured’,
    ‘value’ => ‘1’,
    ‘compare’ => ‘=’,

    thank you.

  21. Hi Yoren! I love your site, I’ve been checking the resources and examples. Coming along nicely but running into issues with multiple value meta queries.

    I read through the mail chimp api link you provided but still struggling to get my query to work for multiple parameters.

    My functions.php file is including the meta_query param in the valid_vars

    I am querying advanced custom fields values and have made them available to query with the acf to rest plugin.

    I would like the values

    “article_type” => “4” and “show_on_home_page” => “yes”

    I have it working with just one value like so


    Do I need to include the compare and type values?

    How would I do it with both the show_on_home_page and article_type keys?

    Thank you so so much for your blog, I love to read through your tutorials and they are so helpful!

    Thank you for helping me if you can!

    • Hi Eric,

      Can you see if ?filter[meta_query][0][key]=article_type&filter[meta_query][0][value]=4&filter[meta_query][1][key]=show_on_home_page&filter[meta_query][1][value]=yes works?

      • YOREN!!! Thank you!!! I wasn’t using [meta_query] before each key and value!!!!

        Honestly I tried everything, (except this haha) Thank you it makes total sense!

        Once again, thank you for writing, sharing, responding and creating amazing content. You inspire me!

        – Eric

  22. I have custom post type in wp api. These CP’s belong to bbpress ( forum, topic, reply). I want to create topic under a forum. Right now i am able to create topic but not associate with forum. How to enable particular field for creation or updation. e.g parent_id is what it is for attaching topic to forum. It can also be post_parent. Tried both but didnt work out.

    Can you please help ?

  23. Hi, I have an issue with media_query on wp rest api V2

    I want filter posts with custom field named start_date after a spicific date.
    I think its possible with media_query but dont know how!

    /wp-json/wp/v2/project/?filter[meta_query][key]=start_date&filter[meta_query][key2]=DATE_ENTER_BY USER_ON_FRONTEND&filter[meta_query][compare]=”<="

    is that even possible?

  24. Hi yoren,

    I need to get post meta fields(table fields) based on particular property id and as well list of all properties are published with this api. I’ve added custom end point for getting this properties based on the property post type Here i want to get property_price & property_address details with metadata table.

    Kindly please help how to get the these fields with custom api responses.

    • Hi Sankar, the address is in your local environment so unfortunately I can’t see what you’re trying to do.

      • Hi yoren,

        I got the solution above query asked. But i have another solution here. For example while adding the real estate property we type of categories like apartment,house,office and these data’s are stored in terms table. Which type of json api method i need to get these list of all categories.

    • Hi Jane, can you test if this works:

      ?filter[meta_query][0][key]= meta_price&filter[meta_query][0][value][0]=50&filter[meta_query][0][value][1]=200&filter[meta_query][0][compare]=between

      • Hi Yoren,

        I’ve checked the above solution it not works.Above same scenario having with my project also but not getting the results as between query.

        • Hi,
          Probably a bit late but for those who have the same problem I found what was missing in this request. You just have to add &filter[meta_query][0][type]=numeric to the url because by default the values are considered as chars. So the full request would be:

          ?filter[meta_query][0][key]= meta_price&filter[meta_query][0][value][0]=50&filter[meta_query][0][value][1]=200&filter[meta_query][0][type]=numeric&filter[meta_query][0][compare]=between

  25. Hi Yoren,

    I’m using this wp rest api with my website for filter custom meta fields called price. So here need to filter the data used price range for this examples:



    Above both examples not getting exact match results to me. And i’ve added & using the custom `rest_query_vars` process only. And also its working with greater than or less than custom fields below example for reference.


    • Hi Sankar, there’s possibility that WP API doesn’t fully support complex meta_query for now. So we might need to hack around it by creating custom end points. I’ll reply to your email later.

    • Hi Sankar,
      Your first url is good, you just need to add &filter[meta_query][0][type]=numeric because by default the values are considered as strings or chars

  26. Hi YOREN !

    Great thread.

    It’s late an I’m sure your busy – quick question.

    My IONIC app developer is not receiving the json REST API call for the taxonomy and terms in the assigned wordpress taxonomy order.


    the call is returning the data by ID asc order.

    How do i get the taxonomy and terms in a hierarchy structure parent child in the correct order


    • hello Justin,

      Sorry for the late reply. You can modify the order of the terms by using “rest_{taxonomy}_query” filter. But if you need to set them in a hierarchical order, the best solution might be to create a custom endpoint.

  27. Hello, Really great site and article.
    I’m wondering if you can give me some hints about getting custom post types by category. Currently, I’m doing this:

    …to get the videos I’ve given a certain category. But instead it always returns the 30 most recent videos.
    I’ve added the required fields in the custom post type declaration to have the post type show up in REST.
    Any help would be greatly appreciated.

    • Hey Zach, as I’ve described in this post, you should category_name instead of category to filter this default tax.

  28. Hi,
    how to filter the custom post type using Between or >=
    custom_start_date = “in milliseconds”,
    custom_end_date = “in milliseconds”

    found int doc :The ‘type’ DATE works with the ‘compare’ value BETWEEN only if the date is stored at the format YYYY-MM-DD and tested with this format.
    can please help and very new to php and wordpress

  29. Hi Yoren,

    Need to filter the data’s using query vars with combination of two taxonomies. I’ve done following this url

    Expected Result : Need to get results for AND condition based
    Actual Result : Getting the results OR condition based.

    May I know how to get combination of two taxonomies based.

  30. Hi Yoren,

    thank you for your useful post.
    I carefully read it but somethings escapes me.

    I’m trying to filter the pages of my wp site by an acf field value.
    The name of my acf field is “on_app” and his value is a boolean “true/false”.

    I added the hook You show to my function.php and then I try to filter the pages with:

    but the response I receive is only []

    Where am I wrong?

    • Hey Filippo, can you use 1 / 2 to represent true / false? All value in URL param will be treated as strings so that may be why it doesn’t work.

  31. Hi,

    Is this disabled on the REST API of wordpress 4.7?

    Upgraded wordpress core and deactivated wp rest api v2 plugin and the meta_key filters do not work.

  32. This post is very old and doubt it’s still being monitored, but can one query custom post types by category? Something like



    I’ve found information about using a custom taxonomy with custom post types but would like to use the built in ones. Thanks for your advice.

    • In theory you can definitely do that as long as you register your CPT & custom post taxonomy with REST API support. Just I didn’t test about it so if I’m wrong, please let me know. 😉

  33. Is there a way to query posts by meta value now that `filter` has been removed from the API, without adding a plugin?

  34. Hi
    YOREN ,
    my site consists of taxonomies
    -fun activities
    so by using wp rest api how can i get specific taxonomy info .
    -Thanks in advance.

  35. Hi there so how would you do this: wp-json/wp/v2/posts/?filter[taxonomy]=job-type&filter[term]=manager with the new api?

    Any help would be most appreciated.


  36. Excellent website. Plenty of useful information here. I am sending it to some friends ans
    also sharing in delicious. And of course, thank you on your sweat!


Leave a Comment