REST API Controller Hooks
Overview
REST API controllers fire numerous hooks for filtering and action purposes. Most hooks include a dynamic portion based on the resource type (post type, taxonomy, etc.).
Common Hook Patterns
Dynamic Hook Names
Many hooks use the pattern rest_{action}_{type} where:
{action}– The operation (insert, prepare, delete, query){type}– Post type, taxonomy, or resource type
Example: rest_insert_post, rest_prepare_page, rest_delete_category
Post Controller Hooks
rest_{$post_type}_query
Filters WP_Query arguments when querying posts.
apply_filters( "rest_{$post_type}_query", array $args, WP_REST_Request $request );
Parameters:
$args– Array of arguments forWP_Query$request– The REST API request
Hook Names: rest_post_query, rest_page_query, rest_attachment_query
Since: 4.7.0
rest_pre_insert_{$post_type}
Filters a post before it is inserted via the REST API.
apply_filters( "rest_pre_insert_{$post_type}", stdClass $prepared_post, WP_REST_Request $request );
Parameters:
$prepared_post– Post object prepared for database$request– Request object
Hook Names: rest_pre_insert_post, rest_pre_insert_page
Since: 4.7.0
rest_insert_{$post_type}
Fires after a post is created or updated via the REST API.
do_action( "rest_insert_{$post_type}", WP_Post $post, WP_REST_Request $request, bool $creating );
Parameters:
$post– Inserted or updated post object$request– Request object$creating–truewhen creating,falsewhen updating
Hook Names: rest_insert_post, rest_insert_page, rest_insert_attachment
Since: 4.7.0
rest_after_insert_{$post_type}
Fires after a post is completely created or updated (after all meta/terms).
do_action( "rest_after_insert_{$post_type}", WP_Post $post, WP_REST_Request $request, bool $creating );
Parameters:
$post– Inserted or updated post object$request– Request object$creating–truewhen creating,falsewhen updating
Hook Names: rest_after_insert_post, rest_after_insert_page
Since: 5.0.0
rest_delete_{$post_type}
Fires after a post is deleted or trashed via the REST API.
do_action( "rest_delete_{$post_type}", WP_Post $post, WP_REST_Response $response, WP_REST_Request $request );
Parameters:
$post– Deleted or trashed post$response– Response data$request– Request sent to API
Hook Names: rest_delete_post, rest_delete_page, rest_delete_attachment
Since: 4.7.0
rest_prepare_{$post_type}
Filters the post data for a REST API response.
apply_filters( "rest_prepare_{$post_type}", WP_REST_Response $response, WP_Post $post, WP_REST_Request $request );
Parameters:
$response– Response object$post– Post object$request– Request object
Hook Names: rest_prepare_post, rest_prepare_page, rest_prepare_attachment
Since: 4.7.0
rest_{$post_type}_trashable
Filters whether a post is trashable.
apply_filters( "rest_{$post_type}_trashable", bool $supports_trash, WP_Post $post );
Parameters:
$supports_trash– Whether post type supports trashing$post– Post being considered
Since: 4.7.0
rest_{$post_type}_item_schema
Filters the post’s schema.
apply_filters( "rest_{$post_type}_item_schema", array $schema );
Parameters:
$schema– Item schema data
Since: 5.4.0
rest_{$post_type}_collection_params
Filters collection parameters for the posts controller.
apply_filters( "rest_{$post_type}_collection_params", array $query_params, WP_Post_Type $post_type );
Parameters:
$query_params– JSON Schema-formatted collection parameters$post_type– Post type object
Since: 4.7.0
rest_query_var-{$key}
Filters a specific query var for get_items().
apply_filters( "rest_query_var-{$key}", mixed $value );
Parameters:
$value– The query_var value
Since: 4.7.0
User Controller Hooks
rest_user_query
Filters WP_User_Query arguments.
apply_filters( 'rest_user_query', array $prepared_args, WP_REST_Request $request );
Parameters:
$prepared_args– Arguments forWP_User_Query$request– REST API request
Since: 4.7.0
rest_pre_insert_user
Filters user data before insertion.
apply_filters( 'rest_pre_insert_user', object $prepared_user, WP_REST_Request $request );
Parameters:
$prepared_user– User object$request– Request object
Since: 4.7.0
rest_insert_user
Fires after a user is created or updated.
do_action( 'rest_insert_user', WP_User $user, WP_REST_Request $request, bool $creating );
Parameters:
$user– Inserted or updated user object$request– Request object$creating–truewhen creating,falsewhen updating
Since: 4.7.0
rest_after_insert_user
Fires after a user is completely created or updated.
do_action( 'rest_after_insert_user', WP_User $user, WP_REST_Request $request, bool $creating );
Since: 5.0.0
rest_delete_user
Fires after a user is deleted.
do_action( 'rest_delete_user', WP_User $user, WP_REST_Response $response, WP_REST_Request $request );
Since: 4.7.0
rest_prepare_user
Filters user data for response.
apply_filters( 'rest_prepare_user', WP_REST_Response $response, WP_User $user, WP_REST_Request $request );
Since: 4.7.0
rest_user_collection_params
Filters collection parameters for users.
apply_filters( 'rest_user_collection_params', array $query_params );
Since: 4.7.0
Comment Controller Hooks
rest_comment_query
Filters WP_Comment_Query arguments.
apply_filters( 'rest_comment_query', array $prepared_args, WP_REST_Request $request );
Since: 4.7.0
rest_pre_insert_comment
Filters a comment before insertion.
apply_filters( 'rest_pre_insert_comment', array|WP_Error $prepared_comment, WP_REST_Request $request );
Parameters:
$prepared_comment– Prepared comment data (orWP_Errorto short-circuit)$request– Request object
Since: 4.7.0, 4.8.0 (can return WP_Error)
rest_insert_comment
Fires after a comment is created or updated.
do_action( 'rest_insert_comment', WP_Comment $comment, WP_REST_Request $request, bool $creating );
Since: 4.7.0
rest_after_insert_comment
Fires after a comment is completely created or updated.
do_action( 'rest_after_insert_comment', WP_Comment $comment, WP_REST_Request $request, bool $creating );
Since: 5.0.0
rest_delete_comment
Fires after a comment is deleted.
do_action( 'rest_delete_comment', WP_Comment $comment, WP_REST_Response $response, WP_REST_Request $request );
Since: 4.7.0
rest_prepare_comment
Filters comment data for response.
apply_filters( 'rest_prepare_comment', WP_REST_Response $response, WP_Comment $comment, WP_REST_Request $request );
Since: 4.7.0
rest_allow_anonymous_comments
Filters whether anonymous comments can be created.
apply_filters( 'rest_allow_anonymous_comments', bool $allow_anonymous, WP_REST_Request $request );
Parameters:
$allow_anonymous– Whether to allow (defaultfalse)$request– Request object
Since: 4.7.0
rest_comment_trashable
Filters whether a comment can be trashed.
apply_filters( 'rest_comment_trashable', bool $supports_trash, WP_Comment $comment );
Since: 4.7.0
Term Controller Hooks
rest_{$taxonomy}_query
Filters get_terms() arguments.
apply_filters( "rest_{$taxonomy}_query", array $prepared_args, WP_REST_Request $request );
Hook Names: rest_category_query, rest_post_tag_query
Since: 4.7.0
rest_pre_insert_{$taxonomy}
Filters term data before insertion.
apply_filters( "rest_pre_insert_{$taxonomy}", object $prepared_term, WP_REST_Request $request );
Hook Names: rest_pre_insert_category, rest_pre_insert_post_tag
Since: 4.7.0
rest_insert_{$taxonomy}
Fires after a term is created or updated.
do_action( "rest_insert_{$taxonomy}", WP_Term $term, WP_REST_Request $request, bool $creating );
Since: 4.7.0
rest_after_insert_{$taxonomy}
Fires after a term is completely created or updated.
do_action( "rest_after_insert_{$taxonomy}", WP_Term $term, WP_REST_Request $request, bool $creating );
Since: 5.0.0
rest_delete_{$taxonomy}
Fires after a term is deleted.
do_action( "rest_delete_{$taxonomy}", WP_Term $term, WP_REST_Response $response, WP_REST_Request $request );
Since: 4.7.0
rest_prepare_{$taxonomy}
Filters term data for response.
apply_filters( "rest_prepare_{$taxonomy}", WP_REST_Response $response, WP_Term $item, WP_REST_Request $request );
Hook Names: rest_prepare_category, rest_prepare_post_tag
Since: 4.7.0
rest_{$taxonomy}_collection_params
Filters collection parameters for terms.
apply_filters( "rest_{$taxonomy}_collection_params", array $query_params, WP_Taxonomy $taxonomy );
Since: 4.7.0
Revision Controller Hooks
rest_revision_query
Filters revision query arguments.
apply_filters( 'rest_revision_query', array $args, WP_REST_Request $request );
Since: 4.7.0
Attachment Controller Hooks
rest_insert_attachment
Fires after an attachment is created or updated.
do_action( 'rest_insert_attachment', WP_Post $attachment, WP_REST_Request $request, bool $creating );
Since: 4.7.0
rest_after_insert_attachment
Fires after an attachment is completely created or updated.
do_action( 'rest_after_insert_attachment', WP_Post $attachment, WP_REST_Request $request, bool $creating );
Since: 5.0.0
wp_prevent_unsupported_mime_type_uploads
Filters whether to prevent uploads of unsupported image types.
apply_filters( 'wp_prevent_unsupported_mime_type_uploads', bool $check_mime, string|null $mime_type );
Parameters:
$check_mime– Whether to prevent (defaulttrue)$mime_type– MIME type being uploaded
Since: 6.8.0
Meta Field Hooks
rest_preprocess_comment
Filters comment data after preparation for database.
apply_filters( 'rest_preprocess_comment', array $prepared_comment, WP_REST_Request $request );
Since: 4.7.0
Usage Examples
Modifying Post Query
add_filter( 'rest_post_query', function( $args, $request ) {
// Only show published posts to non-editors
if ( ! current_user_can( 'edit_posts' ) ) {
$args['post_status'] = 'publish';
}
return $args;
}, 10, 2 );
Adding Custom Data to Response
add_filter( 'rest_prepare_post', function( $response, $post, $request ) {
$response->data['reading_time'] = calculate_reading_time( $post->post_content );
return $response;
}, 10, 3 );
Preventing Anonymous Comments
add_filter( 'rest_allow_anonymous_comments', '__return_false' );
Modifying User Creation
add_action( 'rest_insert_user', function( $user, $request, $creating ) {
if ( $creating ) {
// Send welcome email
wp_mail( $user->user_email, 'Welcome!', 'Your account has been created.' );
}
}, 10, 3 );
Custom Term Validation
add_filter( 'rest_pre_insert_category', function( $prepared_term, $request ) {
if ( strlen( $prepared_term->name ) < 3 ) {
return new WP_Error(
'rest_term_name_too_short',
'Category name must be at least 3 characters.',
array( 'status' => 400 )
);
}
return $prepared_term;
}, 10, 2 );
Hook Execution Order
Create Operation
*_permissions_checkrest_pre_insert_{type}- Database insert
rest_insert_{type}- Meta/additional fields update
rest_after_insert_{type}rest_prepare_{type}
Update Operation
*_permissions_checkrest_pre_insert_{type}- Database update
rest_insert_{type}- Meta/additional fields update
rest_after_insert_{type}rest_prepare_{type}
Delete Operation
*_permissions_check- Database delete/trash
rest_delete_{type}rest_prepare_{type}(for response)
Read Operation
*_permissions_checkrest_{type}_query- Database query
rest_prepare_{type}(for each item)