WP_REST_Comments_Controller

Core controller used to access comments via the REST API.

Class Synopsis

php
class WP_REST_Comments_Controller extends WP_REST_Controller {
    protected $meta;
    
    public function __construct();
    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 );
    
    // 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
    protected function prepare_item_for_database( $request );
    public function prepare_item_for_response( $item, $request );
    protected function prepare_links( $comment );
    
    // Schema & Parameters
    public function get_item_schema();
    public function get_collection_params();
    
    // Utilities
    protected function get_comment( $id );
    protected function normalize_query_param( $query_param );
    protected function prepare_status_response( $comment_approved );
    protected function handle_status_param( $new_status, $comment_id );
    protected function check_read_permission( $comment, $request );
    protected function check_read_post_permission( $post, $request );
    protected function check_edit_permission( $comment );
    protected function check_is_comment_content_allowed( $prepared_comment );
    protected function check_post_type_supports_notes( $post_type );
    public function check_comment_author_email( $value, $request, $param );
}

Endpoints

MethodEndpointDescription
GET/wp/v2/commentsList comments
POST/wp/v2/commentsCreate a comment
GET/wp/v2/comments/{id}Get a single comment
POST/PUT/PATCH/wp/v2/comments/{id}Update a comment
DELETE/wp/v2/comments/{id}Delete a comment

Constructor

php
public function __construct()

Sets namespace to 'wp/v2', rest_base to 'comments', and creates WP_REST_Comment_Meta_Fields instance.

Collection Parameters

ParameterTypeDefaultDescription
contextstring‘view’Scope under which request is made
pageinteger1Current page
per_pageinteger10Items per page (max 100)
searchstringSearch string
afterdate-timeComments after date
beforedate-timeComments before date
authorarrayFilter by author IDs
author_excludearrayExclude author IDs
author_emailstringFilter by author email
excludearray[]Exclude specific IDs
includearray[]Include specific IDs
offsetintegerOffset for pagination
orderstring‘desc’Sort order (asc/desc)
orderbystring‘date_gmt’Sort field
parentarrayFilter by parent IDs
parent_excludearrayExclude parent IDs
postarrayFilter by post IDs
statusstring‘approve’Comment status
typestring‘comment’Comment type
passwordstringPost password (for protected posts)

Orderby Options

  • date – Comment date (local)
  • date_gmt – Comment date (GMT)
  • id – Comment ID
  • include – Order by include parameter
  • post – Post ID
  • parent – Parent comment ID
  • type – Comment type

Status Values

  • approve / approved – Approved comments
  • hold – Pending/unapproved comments
  • spam – Spam comments
  • trash – Trashed comments
  • all – All comments (requires capability)

Schema Properties

PropertyTypeContextDescription
idintegerview, edit, embedComment ID (readonly)
authorintegerview, edit, embedAuthor user ID (0 if guest)
author_emailstring (email)editAuthor email
author_ipstring (ip)editAuthor IP address
author_namestringview, edit, embedAuthor display name
author_urlstring (uri)view, edit, embedAuthor URL
author_user_agentstringeditAuthor user agent
contentobjectview, edit, embedComment content (raw/rendered)
datestring (date-time)view, edit, embedDate (site timezone)
date_gmtstring (date-time)view, editDate (GMT)
linkstring (uri)view, edit, embedComment permalink (readonly)
parentintegerview, edit, embedParent comment ID (default: 0)
postintegerview, editAssociated post ID (default: 0)
statusstringview, editComment status
typestringview, edit, embedComment type (readonly)
author_avatar_urlsobjectview, edit, embedAvatar URLs (readonly)
metaobjectview, editComment meta

Permission Checks

get_items_permissions_check()

  • Validates read permission for specified posts
  • Requires moderate_comments for comments without posts
  • Requires edit_posts for protected parameters:
    • author, author_exclude, author_email
    • type (when not ‘comment’)
    • status (when not ‘approve’)
  • Special handling for note type comments

get_item_permissions_check()

  • author, author_exclude, author_email
  • type (when not ‘comment’)
  • status (when not ‘approve’)

create_item_permissions_check()

  • author, author_exclude, author_email
  • type (when not ‘comment’)
  • status (when not ‘approve’)

update_item_permissions_check()

  • Validates comment exists
  • Requires moderate_comments for edit context (or edit_comment for notes)
  • Calls check_read_permission() and check_read_post_permission()

delete_item_permissions_check()

  • Requires login if comment_registration is enabled
  • Notes always require login
  • Anonymous comments require rest_allow_anonymous_comments filter
  • Validates author, author_ip, status settings require appropriate capabilities
  • Validates post exists and is not draft/trash
  • Validates comments are open for the post

Comment Types

The controller supports two comment types:

Regular Comments (comment)

  • Requires edit_comment capability (via check_edit_permission())

Notes (note)

  • Requires edit_comment capability

Key Methods

get_comment()

php
protected function get_comment( int $id ): WP_Comment|WP_Error

Gets the comment if ID is valid. Also validates the associated post exists.

check_read_permission()

php
protected function check_read_permission( WP_Comment $comment, WP_REST_Request $request ): bool

Checks if a comment can be read. Validates comment status and post visibility.

check_edit_permission()

php
protected function check_edit_permission( WP_Comment $comment ): bool

Checks if the user can edit a comment. Uses edit_comment capability.

check_is_comment_content_allowed()

php
protected function check_is_comment_content_allowed( array $prepared_comment ): bool

Validates that the comment content meets requirements (not empty for regular comments, may include note status for notes).

prepare_status_response()

php
protected function prepare_status_response( string $comment_approved ): string

Converts database status values to API status strings:

  • Standard user comments on posts
  • Subject to comment moderation, flood control, and duplicate checking
  • Anonymous submission possible if allowed

handle_status_param()

php
protected function handle_status_param( string $new_status, int $comment_id ): bool

Updates comment status using wp_set_comment_status().

normalize_query_param()

php
protected function normalize_query_param( string $query_param ): string

Maps API parameter names to WP_Comment_Query parameter names.

RelationDescription
selfLink to this comment
collectionLink to comments collection
authorLink to author user (embeddable, if logged in)
upLink to parent post (embeddable)
in-reply-toLink to parent comment (embeddable)
childrenLink to child comments (embeddable)

Deletion Behavior

DELETE /wp/v2/comments/{id}

Parameters:

  • Internal editorial notes (since WordPress 6.x)
  • Requires authentication
  • Not subject to moderation/flood control
  • Requires post type support ('note' comment type)

Trash Support: Controlled by EMPTY_TRASH_DAYS constant and rest_comment_trashable filter.

Response:

json
// With force=true
{
    "deleted": true,
    "previous": { ... }
}

// With force=false (trashed)
{
    "id": 123,
    "status": "trash",
    ...
}

Avatar URLs

If avatars are enabled, includes avatar URLs at multiple sizes:

json
{
    "author_avatar_urls": {
        "24": "https://secure.gravatar.com/avatar/...?s=24",
        "48": "https://secure.gravatar.com/avatar/...?s=48",
        "96": "https://secure.gravatar.com/avatar/...?s=96"
    }
}

Usage Example

php
// Get comments for a specific post
$request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
$request->set_param( 'post', 123 );
$request->set_param( 'per_page', 20 );
$request->set_param( 'orderby', 'date' );
$request->set_param( 'order', 'asc' );

$controller = new WP_REST_Comments_Controller();
$response = $controller->get_items( $request );

// Create a comment
$request = new WP_REST_Request( 'POST', '/wp/v2/comments' );
$request->set_param( 'post', 123 );
$request->set_param( 'content', 'Great article!' );
$request->set_param( 'author_name', 'John Doe' );
$request->set_param( 'author_email', '[email protected]' );

$response = $controller->create_item( $request );

// Reply to a comment
$request = new WP_REST_Request( 'POST', '/wp/v2/comments' );
$request->set_param( 'post', 123 );
$request->set_param( 'parent', 456 ); // Parent comment ID
$request->set_param( 'content', 'I agree!' );

$response = $controller->create_item( $request );

// Update comment status (moderate)
$request = new WP_REST_Request( 'POST', '/wp/v2/comments/123' );
$request->set_param( 'status', 'approved' );

$response = $controller->update_item( $request );

Anonymous Comments

By default, anonymous comment creation via REST API is disabled. Enable with:

php
add_filter( 'rest_allow_anonymous_comments', function( $allow, $request ) {
    return true;
}, 10, 2 );

Source

wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

Since

WordPress 4.7.0

Changelog

VersionDescription
4.7.0Introduced
4.8.0rest_pre_insert_comment can return WP_Error
5.0.0Added rest_after_insert_comment action