register_rest_route

The timeline below displays how wordpress function register_rest_route has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.2

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook.
 * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set.
 *
 * @param string $route_namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route           The base URL for route you are adding.
 * @param array  $args            Optional. Either an array of options for the endpoint, or an array of arrays for
 *                                multiple methods. Default empty array.
 * @param bool   $override        Optional. If the route already exists, should we override it? True overrides,
 *                                false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($route_namespace, $route, $args = array(), $override = false)
{
    if (empty($route_namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    $clean_namespace = trim($route_namespace, '/');
    if ($clean_namespace !== $route_namespace) {
        _doing_it_wrong(__FUNCTION__, __('Namespace must not start or end with a slash.'), '5.4.2');
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
        if (!isset($arg_group['permission_callback'])) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: 1: The REST API route being registered, 2: The argument name, 3: The suggested function name. */
                __('The REST API route definition for %1$s is missing the required %2$s argument. For REST API routes that are intended to be public, use %3$s as the permission callback.'),
                '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>',
                '<code>permission_callback</code>',
                '<code>__return_true</code>'
            ), '5.5.0');
        }
        foreach ($arg_group['args'] as $arg) {
            if (!is_array($arg)) {
                _doing_it_wrong(__FUNCTION__, sprintf(
                    /* translators: 1: $args, 2: The REST API route being registered. */
                    __('REST API %1$s should be an array of arrays. Non-array value detected for %2$s.'),
                    '<code>$args</code>',
                    '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>'
                ), '6.1.0');
                break;
                // Leave the foreach loop once a non-array argument was found.
            }
        }
    }
    $full_route = '/' . $clean_namespace . '/' . trim($route, '/');
    rest_get_server()->register_route($clean_namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 6.1

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook.
 * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set.
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    $clean_namespace = trim($namespace, '/');
    if ($clean_namespace !== $namespace) {
        _doing_it_wrong(__FUNCTION__, __('Namespace must not start or end with a slash.'), '5.4.2');
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
        if (!isset($arg_group['permission_callback'])) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: 1: The REST API route being registered, 2: The argument name, 3: The suggested function name. */
                __('The REST API route definition for %1$s is missing the required %2$s argument. For REST API routes that are intended to be public, use %3$s as the permission callback.'),
                '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>',
                '<code>permission_callback</code>',
                '<code>__return_true</code>'
            ), '5.5.0');
        }
        foreach ($arg_group['args'] as $arg) {
            if (!is_array($arg)) {
                _doing_it_wrong(__FUNCTION__, sprintf(
                    /* translators: 1: $args, 2: The REST API route being registered. */
                    __('REST API %1$s should be an array of arrays. Non-array value detected for %2$s.'),
                    '<code>$args</code>',
                    '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>'
                ), '6.1.0');
                break;
                // Leave the foreach loop once a non-array argument was found.
            }
        }
    }
    $full_route = '/' . $clean_namespace . '/' . trim($route, '/');
    rest_get_server()->register_route($clean_namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 5.6

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook.
 * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set.
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    $clean_namespace = trim($namespace, '/');
    if ($clean_namespace !== $namespace) {
        _doing_it_wrong(__FUNCTION__, __('Namespace must not start or end with a slash.'), '5.4.2');
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
        if (!isset($arg_group['permission_callback'])) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: 1: The REST API route being registered, 2: The argument name, 3: The suggested function name. */
                __('The REST API route definition for %1$s is missing the required %2$s argument. For REST API routes that are intended to be public, use %3$s as the permission callback.'),
                '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>',
                '<code>permission_callback</code>',
                '<code>__return_true</code>'
            ), '5.5.0');
        }
    }
    $full_route = '/' . $clean_namespace . '/' . trim($route, '/');
    rest_get_server()->register_route($clean_namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 5.1

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook.
 * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set.
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    $clean_namespace = trim($namespace, '/');
    if ($clean_namespace !== $namespace) {
        _doing_it_wrong(__FUNCTION__, __('Namespace must not start or end with a slash.'), '5.4.2');
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
        if (!isset($arg_group['permission_callback'])) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: 1. The REST API route being registered. 2. The argument name. 3. The suggested function name. */
                __('The REST API route definition for %1$s is missing the required %2$s argument. For REST API routes that are intended to be public, use %3$s as the permission callback.'),
                '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>',
                '<code>permission_callback</code>',
                '<code>__return_true</code>'
            ), '5.5.0');
        }
    }
    $full_route = '/' . $clean_namespace . '/' . trim($route, '/');
    rest_get_server()->register_route($clean_namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 5.5

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a _doing_it_wrong() notice when not called on or after the rest_api_init hook.
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    $clean_namespace = trim($namespace, '/');
    if ($clean_namespace !== $namespace) {
        _doing_it_wrong(__FUNCTION__, __('Namespace must not start or end with a slash.'), '5.4.2');
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
        if (!isset($arg_group['permission_callback'])) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: 1. The REST API route being registered. 2. The argument name. 3. The suggested function name. */
                __('The REST API route definition for %1$s is missing the required %2$s argument. For REST API routes that are intended to be public, use %3$s as the permission callback.'),
                '<code>' . $clean_namespace . '/' . trim($route, '/') . '</code>',
                '<code>permission_callback</code>',
                '<code>__return_true</code>'
            ), '5.5.0');
        }
    }
    $full_route = '/' . $clean_namespace . '/' . trim($route, '/');
    rest_get_server()->register_route($clean_namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: .10

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a _doing_it_wrong() notice when not called on or after the rest_api_init hook.
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    $clean_namespace = trim($namespace, '/');
    if ($clean_namespace !== $namespace) {
        _doing_it_wrong(__FUNCTION__, __('Namespace must not start or end with a slash.'), '5.4.2');
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
    }
    $full_route = '/' . $clean_namespace . '/' . trim($route, '/');
    rest_get_server()->register_route($clean_namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 5.1

/**
 * Registers a REST API route.
 *
 * Note: Do not use before the {@see 'rest_api_init'} hook.
 *
 * @since 4.4.0
 * @since 5.1.0 Added a _doing_it_wrong() notice when not called on or after the rest_api_init hook.
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } elseif (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    if (!did_action('rest_api_init')) {
        _doing_it_wrong('register_rest_route', sprintf(
            /* translators: %s: rest_api_init */
            __('REST API routes must be registered on the %s action.'),
            '<code>rest_api_init</code>'
        ), '5.1.0');
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
    }
    $full_route = '/' . trim($namespace, '/') . '/' . trim($route, '/');
    rest_get_server()->register_route($namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 4.9

/**
 * Registers a REST API route.
 *
 * @since 4.4.0
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } else if (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
    }
    $full_route = '/' . trim($namespace, '/') . '/' . trim($route, '/');
    rest_get_server()->register_route($namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 7.2

/**
 * Registers a REST API route.
 *
 * @since 4.4.0
 *
 * @global WP_REST_Server $wp_rest_server ResponseHandler instance (usually WP_REST_Server).
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    /** @var WP_REST_Server $wp_rest_server */
    global $wp_rest_server;
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } else if (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    if (isset($args['args'])) {
        $common_args = $args['args'];
        unset($args['args']);
    } else {
        $common_args = array();
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($key)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
        $arg_group['args'] = array_merge($common_args, $arg_group['args']);
    }
    $full_route = '/' . trim($namespace, '/') . '/' . trim($route, '/');
    $wp_rest_server->register_route($namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 4.5

/**
 * Registers a REST API route.
 *
 * @since 4.4.0
 *
 * @global WP_REST_Server $wp_rest_server ResponseHandler instance (usually WP_REST_Server).
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    /** @var WP_REST_Server $wp_rest_server */
    global $wp_rest_server;
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', __('Routes must be namespaced with plugin or theme name and version.'), '4.4.0');
        return false;
    } else if (empty($route)) {
        _doing_it_wrong('register_rest_route', __('Route must be specified.'), '4.4.0');
        return false;
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($arg_group)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
    }
    $full_route = '/' . trim($namespace, '/') . '/' . trim($route, '/');
    $wp_rest_server->register_route($namespace, $full_route, $args, $override);
    return true;
}

WordPress Version: 4.4

/**
 * Registers a REST API route.
 *
 * @since 4.4.0
 *
 * @global WP_REST_Server $wp_rest_server ResponseHandler instance (usually WP_REST_Server).
 *
 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin.
 * @param string $route     The base URL for route you are adding.
 * @param array  $args      Optional. Either an array of options for the endpoint, or an array of arrays for
 *                          multiple methods. Default empty array.
 * @param bool   $override  Optional. If the route already exists, should we override it? True overrides,
 *                          false merges (with newer overriding if duplicate keys exist). Default false.
 * @return bool True on success, false on error.
 */
function register_rest_route($namespace, $route, $args = array(), $override = false)
{
    /** @var WP_REST_Server $wp_rest_server */
    global $wp_rest_server;
    if (empty($namespace)) {
        /*
         * Non-namespaced routes are not allowed, with the exception of the main
         * and namespace indexes. If you really need to register a
         * non-namespaced route, call `WP_REST_Server::register_route` directly.
         */
        _doing_it_wrong('register_rest_route', 'Routes must be namespaced with plugin or theme name and version.', '4.4.0');
        return false;
    } else if (empty($route)) {
        _doing_it_wrong('register_rest_route', 'Route must be specified.', '4.4.0');
        return false;
    }
    if (isset($args['callback'])) {
        // Upgrade a single set to multiple.
        $args = array($args);
    }
    $defaults = array('methods' => 'GET', 'callback' => null, 'args' => array());
    foreach ($args as $key => &$arg_group) {
        if (!is_numeric($arg_group)) {
            // Route option, skip here.
            continue;
        }
        $arg_group = array_merge($defaults, $arg_group);
    }
    $full_route = '/' . trim($namespace, '/') . '/' . trim($route, '/');
    $wp_rest_server->register_route($namespace, $full_route, $args, $override);
    return true;
}