WP_REST_Terms_Controller
Core class used to manage terms associated with a taxonomy via the REST API.
Class Synopsis
class WP_REST_Terms_Controller extends WP_REST_Controller {
protected $taxonomy;
protected $meta;
protected $sort_column;
protected $total_terms;
protected $allow_batch = array( 'v1' => true );
public function __construct( string $taxonomy );
public function register_routes();
// Permission Checks
public function get_items_permissions_check( $request );
public function get_item_permissions_check( $request );
public function create_item_permissions_check( $request );
public function update_item_permissions_check( $request );
public function delete_item_permissions_check( $request );
public function check_read_terms_permission_for_post( $post, $request );
// CRUD Operations
public function get_items( $request );
public function get_item( $request );
public function create_item( $request );
public function update_item( $request );
public function delete_item( $request );
// Data Preparation
public function prepare_item_for_database( $request );
public function prepare_item_for_response( $item, $request );
protected function prepare_links( $term );
// Schema & Parameters
public function get_item_schema();
public function get_collection_params();
// Utilities
protected function get_term( $id );
protected function check_is_taxonomy_allowed( $taxonomy );
}
Endpoints
The endpoint path depends on the taxonomy’s rest_base:
| Taxonomy | Endpoint |
|---|---|
| category | /wp/v2/categories |
| post_tag | /wp/v2/tags |
| Custom | /wp/v2/{rest_base} |
| Method | Endpoint | Description |
|---|---|---|
| GET | /wp/v2/categories |
List categories |
| POST | /wp/v2/categories |
Create a category |
| GET | /wp/v2/categories/{id} |
Get a single category |
| POST/PUT/PATCH | /wp/v2/categories/{id} |
Update a category |
| DELETE | /wp/v2/categories/{id} |
Delete a category |
Constructor
public function __construct( string $taxonomy )
Parameters:
$taxonomy– Taxonomy key (e.g.,'category','post_tag')
Behavior:
- Sets
$this->taxonomyto the provided taxonomy - Gets
rest_baseandrest_namespacefrom taxonomy object - Creates
WP_REST_Term_Meta_Fieldsinstance
Collection Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
context |
string | ‘view’ | Scope under which request is made |
page |
integer | 1 | Current page |
per_page |
integer | 10 | Items per page (max 100) |
search |
string | – | Search string |
exclude |
array | [] | Exclude specific IDs |
include |
array | [] | Include specific IDs |
offset |
integer | – | Offset (non-hierarchical only) |
order |
string | ‘asc’ | Sort order (asc/desc) |
orderby |
string | ‘name’ | Sort field |
hide_empty |
boolean | false | Hide terms with no posts |
parent |
integer | – | Filter by parent ID (hierarchical only) |
post |
integer | – | Filter by post ID |
slug |
array | – | Filter by slugs |
Orderby Options
id– Term IDinclude– Order by include parametername– Term nameslug– Term sluginclude_slugs– Order by slug includeterm_group– Term groupdescription– Term descriptioncount– Post count
Schema Properties
| Property | Type | Context | Required | Description |
|---|---|---|---|---|
id |
integer | view, embed, edit | – | Term ID (readonly) |
count |
integer | view, edit | – | Post count (readonly) |
description |
string | view, edit | – | HTML description |
link |
string (uri) | view, embed, edit | – | Term archive URL (readonly) |
name |
string | view, embed, edit | create | Term name |
slug |
string | view, embed, edit | – | Term slug |
taxonomy |
string | view, embed, edit | – | Taxonomy key (readonly) |
parent |
integer | view, edit | – | Parent term ID (hierarchical only) |
meta |
object | view, edit | – | Term meta |
Permission Checks
get_items_permissions_check()
- Returns
falseif taxonomy doesn’t exist or isn’t allowed in REST - Requires
edit_termscapability foreditcontext - If filtering by
post, validates post read permission
get_item_permissions_check()
- Validates term exists and belongs to this taxonomy
- Requires
edit_termcapability foreditcontext
create_item_permissions_check()
- For hierarchical taxonomies: requires
edit_termscapability - For non-hierarchical taxonomies: requires
assign_termscapability
update_item_permissions_check()
- Requires
edit_termcapability
delete_item_permissions_check()
- Requires
delete_termcapability
check_read_terms_permission_for_post()
public function check_read_terms_permission_for_post( WP_Post $post, WP_REST_Request $request ): bool
Checks if terms for a post can be read:
- Post must be associated with this taxonomy
- Post is publicly viewable, or
- User can
read_post
Key Methods
get_term()
protected function get_term( int $id ): WP_Term|WP_Error
Gets the term if:
- ID is valid (> 0)
- Term exists
- Term belongs to this taxonomy
- Taxonomy is allowed in REST
check_is_taxonomy_allowed()
protected function check_is_taxonomy_allowed( string $taxonomy ): bool
Checks if taxonomy has show_in_rest enabled.
prepare_item_for_database()
public function prepare_item_for_database( WP_REST_Request $request ): object
Maps request fields to term properties:
name→nameslug→slugdescription→descriptionparent→parent(validates parent term exists)
prepare_item_for_response()
public function prepare_item_for_response( WP_Term $item, WP_REST_Request $request ): WP_REST_Response
Prepares term data for API response including links.
Response Links
| Relation | Description |
|---|---|
self |
Link to this term |
collection |
Link to terms collection |
about |
Link to taxonomy info |
up |
Link to parent term (hierarchical, embeddable) |
wp:post_type |
Links to posts with this term |
Deletion Behavior
DELETE /wp/v2/categories/{id}
Required Parameter:
force– Must betrue(terms don’t support trashing)
Response:
{
"deleted": true,
"previous": {
"id": 123,
"name": "Category Name",
"slug": "category-name",
...
}
}
Hierarchical vs Non-Hierarchical
The controller behavior varies based on taxonomy type:
Hierarchical (e.g., categories)
parentschema property includedparentcollection parameter availableoffsetparameter not available- Requires
edit_termsto create
Non-Hierarchical (e.g., tags)
- No
parentproperty offsetparameter available- Requires
assign_termsto create
Usage Example
// List categories
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'per_page', 100 );
$request->set_param( 'hide_empty', false );
$request->set_param( 'orderby', 'name' );
$controller = new WP_REST_Terms_Controller( 'category' );
$response = $controller->get_items( $request );
// Create a category
$request = new WP_REST_Request( 'POST', '/wp/v2/categories' );
$request->set_param( 'name', 'New Category' );
$request->set_param( 'description', 'Category description' );
$request->set_param( 'parent', 5 ); // Parent category ID
$response = $controller->create_item( $request );
// Get terms for a specific post
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'post', 123 );
$controller = new WP_REST_Terms_Controller( 'post_tag' );
$response = $controller->get_items( $request );
// Update a term
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/5' );
$request->set_param( 'name', 'Updated Name' );
$request->set_param( 'slug', 'updated-slug' );
$response = $controller->update_item( $request );
// Delete a term
$request = new WP_REST_Request( 'DELETE', '/wp/v2/categories/5' );
$request->set_param( 'force', true );
$response = $controller->delete_item( $request );
Custom Taxonomies
Register custom taxonomies with REST support:
register_taxonomy( 'genre', 'post', array(
'public' => true,
'show_in_rest' => true,
'rest_base' => 'genres',
'hierarchical' => true,
'labels' => array(
'name' => 'Genres',
'singular_name' => 'Genre',
),
));
// Endpoint automatically available at /wp/v2/genres
Term Existence Handling
When creating a term that already exists, the API returns an error with the existing term ID:
{
"code": "term_exists",
"message": "A term with the name provided already exists with this parent.",
"data": {
"status": 400,
"term_id": 123
}
}
Taxonomy Default Args
Since WordPress 6.8.0, taxonomies can define default query arguments that are respected:
register_taxonomy( 'custom_tax', 'post', array(
'show_in_rest' => true,
'args' => array(
'orderby' => 'term_order',
),
));
Source
wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
Since
WordPress 4.7.0
Changelog
| Version | Description |
|---|---|
| 4.7.0 | Introduced |
| 5.0.0 | Added rest_after_insert_{$taxonomy} action |
| 5.9.0 | Added batching support |
| 6.0.3 | Added check_read_terms_permission_for_post() |
| 6.8.0 | Respects taxonomy default query arguments |