WordPress has several APIs build in:

by default they don't return custom post types or protected meta keys.

I want to access the protected meta fields of a plugin. I tried to follow the examples given here and here.

I did manage that the wp-json API would return custom post types by adding this code:

 * Add REST API support to an already registered post type.
add_action( 'init', 'my_custom_post_type_rest_support', 25 );

function my_custom_post_type_rest_support() {

  global $wp_post_types;

  // be sure to set this to the name of your post type!
  $post_type_name = 'tribe_venue';

  if( isset( $wp_post_types[ $post_type_name ] ) ) {
      $wp_post_types[$post_type_name]->show_in_rest = true;
      $wp_post_types[$post_type_name]->rest_base = $post_type_name;
      $wp_post_types[$post_type_name]->rest_controller_class = 'WP_REST_Posts_Controller';

  $post_type_name2 = 'tribe_events';

  if( isset( $wp_post_types[ $post_type_name2 ] ) ) {
      $wp_post_types[$post_type_name2]->show_in_rest = true;
      $wp_post_types[$post_type_name2]->rest_base = $post_type_name2;
      $wp_post_types[$post_type_name2]->rest_controller_class = 'WP_REST_Posts_Controller';

But I was not able to include protected meta keys in the response.

I tried the following code:

add_filter( 'is_protected_meta', function ( $protected, $key, $type ) {
    if ( $type === 'tribe_venue' && $key === '_VenueVenue' ) {
        return true;
    return $protected;
}, 10, 3 );

add_filter( 'rae_include_protected_meta', '__return_true' );

and the following code:

function custom_rest_api_allowed_public_metadata($allowed_meta_keys){
    $allowed_meta_keys[] = '_VenueVenue';
    $allowed_meta_keys[] = '_VenueAddress';
    $allowed_meta_keys[] = '_VenueCity';
    return $allowed_meta_keys;

add_filter( 'rest_api_allowed_public_metadata', 'custom_rest_api_allowed_public_metadata' );

but neither works.

Does anybody know what is needed so make such protected fields accessible through any of the APIs? Is there a working example anywhere?

  • Is your goal to include them with the default routes or just any solution like creating your custom route/endpoint just for this?
    – kraftner
    Jan 31, 2017 at 16:56

2 Answers 2


To me, the simplest solution would be creating additional field in JSON response and populating it with selected post meta:

function create_api_posts_meta_field() {

    // "tribe_venue" is your post type name, 
    // "protected-fields" is a name for new JSON field

    register_rest_field( 'tribe_venue', 'protected-fields', [
        'get_callback' => 'get_post_meta_for_api',
        'schema' => null,
    ] );

add_action( 'rest_api_init', 'create_api_posts_meta_field' );

 * Callback function to populate our JSON field
function get_post_meta_for_api( $object ) {

    $meta = get_post_meta( $object['id'] );

    return [
        'venue'   => $meta['_VenueVenue']   ?: '',
        'address' => $meta['_VenueAddress'] ?: '',
        'city'    => $meta['_VenueCity']    ?: '',

You should be able to see your meta data both in /wp-json/wp/v2/tribe_venue/ and /wp-json/wp/v2/tribe_venue/{POST_ID}


With the REST API, there's a rest_query_vars filter you can use:

function my_allow_meta_query( $valid_vars ) {

    $valid_vars = array_merge( $valid_vars, array( 'meta_key', 'meta_value') );

    return $valid_vars;

add_filter( 'rest_query_vars', 'my_allow_meta_query' );

This allows you to use a route like this to query a meta field:


There are also more complex ways you can do it. Check out the source link below.

Source: https://1fix.io/blog/2015/07/20/query-vars-wp-api/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.