REST Route Generator
Namespaced endpoints with a real args schema, sanitise and validate callbacks, and a permission callback that is never just __return_true by accident.
The endpoint
/wp-json/myplugin/v1/items
Methods
Each method gets its own callback.
Who can call it
permission_callback is required — omitting it throws a notice.
Readable by anyone and cached by proxies. Never expose private data or write operations here.
Arguments
Becomes the args schema — WordPress validates before your callback runs.
absint() → rest_validate_request_arg() · min/max
sanitize_text_field() → rest_validate_request_arg()
Extras
Also register a REST field
Adds a register_rest_field() example that extends the core post response.
Send cache headers
Adds a rest_post_dispatch filter with Cache-Control. Public GET routes only.
Paste into a plugin, an mu-plugin, or a functionality plugin.
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). /** * Register the /items endpoint. */ function myplugin_register_items_route() { register_rest_route( 'myplugin/v1', '/items', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'myplugin_items_get', 'permission_callback' => 'myplugin_items_permission', 'args' => array( 'per_page' => array( 'description' => __( 'How many items to return.', 'textdomain' ), 'type' => 'integer', 'default' => 10, 'minimum' => 1, 'maximum' => 50, 'sanitize_callback' => 'absint', 'validate_callback' => 'rest_validate_request_arg', ), 'search' => array( 'description' => __( 'Optional search term.', 'textdomain' ), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg', ), ), ), ) ); } add_action( 'rest_api_init', 'myplugin_register_items_route' ); /** * Permission check for /items. * * @return true|WP_Error */ function myplugin_items_permission() { return true; } /** * GET /items * * @param WP_REST_Request $request Request object. * @return WP_REST_Response|WP_Error */ function myplugin_items_get( $request ) { $per_page = $request->get_param( 'per_page' ); $search = $request->get_param( 'search' ); $query = new WP_Query( array( 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => $per_page, 'no_found_rows' => true, ) ); $items = array_map( static function ( $post ) { return array( 'id' => $post->ID, 'title' => get_the_title( $post ), 'link' => get_permalink( $post ), ); }, $query->posts ); return rest_ensure_response( $items ); }