How to return Meta data from the REST API?

The first parameter passed to register_meta() is always post for posts, Pages (post type of page) and custom post types.

However, the REST API Handbook says that:

Prior WordPress 4.9.8, meta fields set to show_in_rest using
register_meta are registered for all objects of a given type. If one
custom post type shows a meta field, all custom post types will show
that meta field. As of WordPress 4.9.8 it’s possible to use
register_meta with the object_subtype argument that allows one to
reduce the usage of the meta key to a particular post type.

So this should work:

register_meta('post', 'city', [
    'object_subtype' => 'my_post_type', // Limit to a post type.
    'type'           => 'string',
    'description'    => 'Cidade',
    'single'         => true,
    'show_in_rest'   => true,
]);

But then, the REST API Handbook also says:

Note that for meta fields registered on custom post types, the post
type must have custom-fields support. Otherwise the meta fields will
not appear in the REST API.

So make certain that your post type has support for custom-fields:

register_post_type(
    'my_post_type',
    array(
        'supports' => array( 'custom-fields', ... ), // custom-fields is required
        ...
    )
);

Alternate Solution

This one uses register_rest_field() and you can easily use my_post_type in the code. But this is of course a simplified example and you should check the handbook for more information:

add_action( 'rest_api_init', function () {
    register_rest_field( 'my_post_type', 'city', array(
        'get_callback' => function( $post_arr ) {
            return get_post_meta( $post_arr['id'], 'city', true );
        },
    ) );
} );

Also, the metadata will not be in meta, but instead in the top-level just as the meta property. Sample response body/string: (just part of the full response)

  • With register_meta(): ,"meta":{"city":"London"},

  • With register_rest_field(): ,"meta":[],"city":"London",

Leave a Comment