I'm currently setting up a WP REST API, and the tool is really impressive and the amount of possibilities vast. I would however really love it to have a full documentation listing all of the possible keys you can provide for $args when calling register_rest_route, just as you have it with register_post_type.

We're slowly building our own documentation with the gathered information across different pages since more than a week now, but wondered if there isn't a full documentation on this?

1 Answer 1


full documentation listing all of the possible keys you can provide for $args when calling register_rest_route, just as you have it with register_post_type

register_rest_route(), as of writing, doesn't have such a documentation; however, you can call $request->get_attributes() inside of your endpoint callback to get the full (registration) options (including those not explicitly specified) for that specific endpoint.

  • Excerpt from https://developer.wordpress.org/rest-api/requests/#attributes:

    If we made a GET request to my-namespace/v1/books, and then we called $request->get_attributes() inside of our endpoint callback, we would be returned all of the registration options for the my-namespace/v1/books endpoint.

    In the attributes we will get a response containing supported methods, options, whether to show this endpoint in the index, a list of registered arguments for the endpoint, and our registered callbacks.

So for example, the following registers a route containing 2 endpoints:

add_action( 'rest_api_init', 'my_plugin_register_rest_routes' );
function my_plugin_register_rest_routes() {
    register_rest_route( 'my-plugin/v1', 'foo', array(
        // Endpoint 1 - Get an item.
            'callback'            => 'my_plugin_rest_get_foo',
            'permission_callback' => '__return_true',

        // Endpoint 2 - Create an item.
            'methods'             => 'POST',
            'callback'            => 'my_plugin_rest_create_foo',
            'permission_callback' => 'my_plugin_rest_create_foo_permissions_check',
            'args'                => my_plugin_rest_create_foo_arguments(),
            'show_in_index'       => false,
    ) );

function my_plugin_rest_get_foo( WP_REST_Request $request ) {
    return $request->get_attributes();

function my_plugin_rest_create_foo( WP_REST_Request $request ) {
    return array( $request->get_attributes(), $request->get_params() );

function my_plugin_rest_create_foo_permissions_check() {
    return current_user_can( 'manage_options' );

function my_plugin_rest_create_foo_arguments() {
    $args = array();

    $args['title'] = array(
        'type'              => 'string',
        'required'          => true,
        'sanitize_callback' => 'my_plugin_title_arg_sanitize_callback',

    $args['color'] = array(
        'type'     => 'string',
        'required' => true,
        'enum'     => array( 'red', 'green', 'blue' ),

    return $args;

function my_plugin_title_arg_sanitize_callback( $value, WP_REST_Request $request, $param ) {
    return wp_filter_kses( $value ); // allows basic HTML; e.g. <b> is OK, but not <hr />

And here's what the endpoint callback returned in my case (WordPress v6.0):

  • GET my-plugin/v1/foo

    Request via cURL:
    curl -X GET https://example.com/wp-json/my-plugin/v1/foo
    Sample response:
        "methods": {
            "GET": true
        "accept_json": false,
        "accept_raw": false,
        "show_in_index": true,
        "args": [],
        "callback": "my_plugin_rest_get_foo",
        "permission_callback": "__return_true"
  • POST my-plugin/v1/foo

    Request via cURL:
    curl --user "<username>:<application password>"
        -X POST https://example.com/wp-json/my-plugin/v1/foo
        -H "Content-Type: application/json"
        -d '{"title": "test with <b>HTML</b><hr /> yeah", "color": "blue"}'
    Sample response:
        "methods": {
            "POST": true
        "accept_json": false,
        "accept_raw": false,
        "show_in_index": false,
        "args": {
            "title": {
                "type": "string",
                "required": true,
                "sanitize_callback": "my_plugin_title_arg_sanitize_callback"
            "color": {
                "type": "string",
                "required": true,
                "enum": ["red", "green", "blue"]
        "callback": "my_plugin_rest_create_foo",
        "permission_callback": "my_plugin_rest_create_foo_permissions_check"
    }, {
        "title": "test with <b>HTML<\/b> yeah",
        "color": "blue"

So as you could see, each endpoint contains 7 top-level attributes, namely:

  • methods — One or more HTTP methods allowed for the endpoint.

  • args — Arguments for the endpoint.

  • callback — The main callback function for responding to the request.

  • permission_callback — A function which checks if the user can perform the action (reading, updating, etc.) before the real/main callback is called.

    Note: As of WordPress v5.5, if a permission_callback is not provided, the REST API will issue a _doing_it_wrong notice. So at bare minimum, an endpoint should always have both callback and permission_callback. And for REST API routes that are intended to be public, you can use __return_true as the permission callback.

  • show_in_index — A boolean indicating whether the endpoint should be included in the route index, e.g. at https://example.com/wp-json/my-plugin/v1 in my case.

    Note: You can omit your REST routes/endpoints from the index by using 'show_in_index' => false when registering your REST routes. However, the routes themselves will still be accessible. But you can use the permission callback to limit access to your endpoints.

  • accept_json and accept_raw — In REST API v1, (I believe) they were WP_JSON_Server::ACCEPT_JSON and WP_JSON_Server::ACCEPT_RAW respectively.

    But in REST API v2, those "accept_xxx" are false by default, so I don't know what these are for in REST API v2. Maybe they're defined just for back-compat? 🤔

And as for the first four attributes above, they're well-documented in the REST API handbook:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.