Routes for Posts and Taxonomies

The Rest API can create routes for custom post types and taxonomies. These routes are created within the namespace wp/v2. The familiar controllers for these content types will be used, see Posts, Categories. This section shows how to enable REST API support when registering your post type or taxonomy. Below is the simplest and most convenient way to make all of this work.

Registration of a Post Type with REST API Support

REST API support is enabled in the function register_post_type() when registering a post type:

## Registering the post type book with REST API support
add_action( 'init', 'my_book_cpt' );
function my_book_cpt() {

	register_post_type( 'book', array(
		'label'        => 'Books',
		'public'       => true,
		... // other parameters

		// parameters related to REST
		'show_in_rest' => true,
		'rest_base'             => 'book',
		'rest_controller_class' => 'WP_REST_Posts_Controller',

	) );
}
show_in_rest = true
Enables REST API support. This parameter will add a new route and corresponding endpoints in the namespace wp/v2.
rest_base
A parameter to change the name of the type in the URL (by default, the post type name is specified there). For example, if you specify rest_base = books, instead of wp-json/wp/v2/book/, we will get the route wp-json/wp/v2/books.
rest_controller_class
A parameter where you need to specify a subclass of the class WP_REST_Controller. By default, this parameter uses the subclass WP_REST_Posts_Controller. If another controller is used, then the route will most likely no longer be in the namespace wp/v2.

Registration of a Taxonomy with REST API Support

REST API support is enabled in the function register_taxonomy() when registering a taxonomy:

## Registering the taxonomy genre with REST API support
add_action( 'init', 'my_book_taxonomy', 30 );
function my_book_taxonomy() {

  register_taxonomy( 'genre', array( 'book' ), array(
	'hierarchical'          => true,
	... // other parameters

	// parameters related to REST
	'show_in_rest'          => true,
	'rest_base'             => 'genre',
	'rest_controller_class' => 'WP_REST_Terms_Controller',
  ) );

}

Here everything works exactly the same as for post types:

  • REST API support is enabled through show_in_rest = true.
  • In rest_base, you can change the content type name in the route. By default, the taxonomy name is specified there.
  • In rest_controller_class, you can change the controller class. By default, it specifies the class WP_REST_Terms_Controller.

Adding REST API Support to Existing Content Types

If a custom post type or taxonomy was added by a theme or plugin (code that you cannot change), but you need to enable REST support, you can do this in several ways. You need to specify the same variables as described above.

Option 1:

This option uses the hooks register_post_type_args and register_taxonomy_args to change the parameters of the post type and taxonomy at the time of their registration. This option is more correct, however, in rare cases, it may not work (when a plugin or theme incorrectly registers the post type or taxonomy - not on the init hook, as recommended).

Example for a post type:

## Adding REST API support for an already existing post type
add_filter( 'register_post_type_args', 'my_custom_post_type_rest_support', 10, 2 );
function my_custom_post_type_rest_support( $args, $post_type ) {

	// make sure this is our post type
	if ( $post_type === 'planet' ) {
		$args['show_in_rest']          = true;
		$args['rest_base']             = 'planet';
		$args['rest_controller_class'] = 'WP_REST_Posts_Controller';
	}

	return $args;
}

Example for a taxonomy:

## Adding REST API support for an already existing taxonomy
add_action( 'register_taxonomy_args', 'my_custom_taxonomy_rest_support', 10, 2 );
function my_custom_taxonomy_rest_support( $args, $taxonomy ) {

	// make sure this is our taxonomy
	if ( $taxonomy === 'planet_class' ) {
		$args['show_in_rest']          = true;
		$args['rest_base']             = 'planet_class';
		$args['rest_controller_class'] = 'WP_REST_Terms_Controller';
	}

	return $args;
}
Option 2:

This option uses global variables $wp_post_types and $wp_taxonomies. This option is more stable compared to the previous one, but it looks more like a workaround smile

If the code does not work, try increasing the priority (specify 99 instead of 50). If the hook fires before the post type or taxonomy registration, the isset check will prevent an error, but REST support will not be added.

## Adding REST API support for an already existing post type
add_action( 'init', 'my_custom_post_type_rest_support', 50 );
function my_custom_post_type_rest_support() {
	global $wp_post_types;

	// make sure this is our post type
	$post_type = 'planet';
	if( isset( $wp_post_types[ $post_type ] ) ) {
		$wp_post_types[ $post_type ]->show_in_rest = true;
		$wp_post_types[ $post_type ]->rest_base = $post_type;
		$wp_post_types[ $post_type ]->rest_controller_class = 'WP_REST_Posts_Controller';
	}
}
## Adding REST API support for an already existing taxonomy
add_action( 'init', 'my_custom_taxonomy_rest_support', 50 );
function my_custom_taxonomy_rest_support() {
	global $wp_taxonomies;

	// make sure this is our taxonomy
	$tax_name = 'planet_class';
	if ( isset( $wp_taxonomies[ $tax_name ] ) ) {
		$wp_taxonomies[ $tax_name ]->show_in_rest = true;
		$wp_taxonomies[ $tax_name ]->rest_base = $tax_name;
		$wp_taxonomies[ $tax_name ]->rest_controller_class = 'WP_REST_Terms_Controller';
	}
}

Resource Relationships for Custom Types

Read about resource relationships in the section Links and Embeds

Custom post types and taxonomies created for them are automatically linked in the REST response. But what if, for example, you need to link two different post types? In WP, there are no special functions for this, but you can do it manually by specifying the links in the _link property of the corresponding controller.