register_rest_route()
Registers a REST API route and its endpoints. Simply put, registers the URL at which the specified PHP function will be triggered.
The function should be called on the action rest_api_init.
Since WP 5.5.0 the permission_callback parameter became mandatory! If you don't specify it, you will get the following notice in debug.log:
PHP Notice: register_rest_route was called incorrectly. The REST API route registration for /foo is missing the required argument permission_callback. For public REST API routes, use __return_true as the callback function.
Read more here: https://developer.wordpress.org/rest-api/extending-the-rest-api/routes-and-endpoints/#permissions-callback.
See also: WordPress REST API Tutorial.
No Hooks.
Returns
true|false. True on success and false on failure.
Usage template
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/my_slug/(?P<param_name>.+)', array(
'methods' => 'GET', // request method: GET, POST ...
'callback' => 'function_name', // request handler function. Must return the response to the request
'permission_callback' => 'function_name', // route access check function. Must return true/false
// description of passed parameters
'args' => array(
'param_name' => array(
'default' => null, // default value of the parameter
'required' => null, // whether the parameter is required. Can only be true
'validate_callback' => 'function_name', // parameter value validation function. Must return true/false
'sanitize_callback' => 'function_name', // parameter value sanitization function. Must return the sanitized value
),
'param_name2' => array(
...
)
...
),
) );
} );
Usage
register_rest_route( $namespace, $route, $args, $override );
- $namespace(string) (required)
- The first part of the route (URL) that comes after the REST prefix (/wp-json/). Must be unique, usually a unique name of your plugin or theme is used here, e.g.
myplugin/v1. See more about namespaces in REST. - $route(string) (required)
- The second part of the route (URL). Supports regular expressions, e.g.
/author/(?P<id>\d+). - $args(array)
Array of parameters for the endpoint.
With these parameters you can finely tune the endpoint request handling.If you need to create several endpoints, the array should contain nested arrays describing each endpoint.
The array for a single endpoint by default looks like this:
$args = [ 'methods' => 'GET', 'callback' => null, 'permission_callback' => null, 'args' => array(), ];
Example of how to specify multiple endpoints (methods):
$args = [ // common args 'args' => [ 'id' => [ 'description' => __( 'Unique identifier for the term.' ), 'type' => 'integer', ], ], // GET [ 'methods' => 'GET', 'callback' => null, 'permission_callback' => null, 'args' => [], ], // POST [ 'methods' => 'POST', 'callback' => null, 'permission_callback' => null, 'args' => [], ], ]
Description of all possible arguments see below.
The array created here is inserted as-is into the property WP_REST_Server::$endpoints.
- $override(boolean)
Determines whether to overwrite data if such a route already exists:
- true - override
- false - merge using array_merge().
Default: false
Arguments of the $args parameter
- methods(string/array)
Defines by which request method the endpoint will be available: GET (default), POST, PUT, PATCH, DELETE. Multiple methods can be specified as a comma-separated string or an array.
You can use predefined constants of the WP_REST_Server class:
WP_REST_Server::READABLE // GET WP_REST_Server::CREATABLE // POST WP_REST_Server::EDITABLE // POST, PUT, PATCH WP_REST_Server::DELETABLE // DELETE WP_REST_Server::ALLMETHODS // GET, POST, PUT, PATCH, DELETE
- callback(callback function)
Specifies the name of the function that will be triggered when accessing (requesting) the URL (rest route). In the function you should build and return the data. The returned data will be converted to JSON and output.
In this parameter you can use your own function or any other function that returns a result, for example get_posts().
The function specified in this parameter receives a parameter of the WP_REST_Request class, which contains the request parameters and allows forming an accurate response. For example, calling get_posts() directly will return results according to its default settings, but if you wrap it in your function and pass the received author ID parameter to get_posts(), you can filter posts by author (see the first example).
Since the function receives an object of class WP_REST_Request, we have methods available to get various information:
// Registers a route add_action( 'rest_api_init', function () { register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array( 'methods' => 'GET', 'callback' => 'my_rest_api_func', ) ); } ); // Access the URL http://wp-test.ru/wp-json/myplugin/v1/author/1 function my_rest_api_func( WP_REST_Request $request ) { // You can access parameters via direct array access on the object: $param = $request['id']; // 1 // Or using the method: $param = $request->get_param( 'id' ); // 1 // Array of all parameters $parameters = $request->get_params(); // Array([id] => 1) // If necessary, separate parameter groups are also available: $parameters = $request->get_url_params(); // Array([id] => 1) $parameters = $request->get_query_params(); // Array() // If you request http://wp-test.ru/wp-json/myplugin/v1/author/1?post=1 $parameters = $request->get_query_params(); // Array( [post] => 1 ) $parameters = $request->get_body_params(); // Array() $parameters = $request->get_json_params(); // null - there was no request with header Content-type: application/json $parameters = $request->get_default_params(); // Array() // Upload data are not merged, but may be available separately: $parameters = $request->get_file_params(); // ways to return data return new WP_REST_Response( true, 200 ); return new WP_Error( 'no_author', 'Invalid author', array( 'status' => 404 ) ); return 'строка'; return array( 'foo'=>'bar' ); // get WP_REST_Response object $response = rest_ensure_response( array( 'foo'=>'bar' ) ); $response->set_status( 401 ); $response->set_headers( [ 'X_REAL_IP' => '54.15.124.126', ] ); return $response; }- permission_callback(callback function) (required)
Allows checking the rights of the user requesting the route. Access will be granted if true is returned, and denied if false.
Since WordPress 5.5 this function must be specified!
Example of allowing access to all users:
register_rest_route( 'myplugin/v1', '/awesome-route', array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_awesome_func', 'permission_callback' => '__return_true' ) );
Example of checking user capabilities:
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_awesome_func', 'permission_callback' => 'my_awesome_permission_callback' ) ); function my_awesome_permission_callback ( WP_REST_Request $request ) { return current_user_can( 'edit_others_posts' ); }Let the function my_awesome_func() return posts of the specified user. If the user has the capability to edit others' posts (for example, an editor), the required data will be returned. If the current user does not have such rights, an error will be returned:
{ "code": "rest_forbidden", "message": "Sorry, you are not allowed to perform this action.", "data": { "status": 401 } }The same error will be returned if you don't pass a nonce; read more in the Authentication in WP REST API section.
- show_in_index(true/false)
- Whether to show the route in the index of all routes.
- args(array)
Possible endpoint parameters. Each array element describes one parameter. The element key is the name of the request parameter, and the value is a nested array describing that parameter.
Some parameter data is automatically added to the route schema (for example description, type, required ...). See rest_get_allowed_schema_keywords().
Possible arguments of the array:
description default required sanitize_callback validate_callback // validation and sanitization type string minLength / maxLength pattern format null boolean number / integer minimum / maximum exclusiveMinimum / exclusiveMaximum multipleOf array items minItems / maxItems uniqueItems object properties additionalProperties patternProperties minProperties / maxProperties enum oneOf / anyOf
REST data types. Validation and sanitization — see the full list of possible parameters and their descriptions there.
-
description(string) (appears in schema)
Description of the parameter. -
default(mixed) (appears in schema)
Default value for the argument if it is not provided.register_rest_route( 'myplugin/v1', '/author/(?P<key>\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_awesome_func', 'args' => array( 'key' => array( 'default' => 1 ), ), ) );
-
required(true/false) (appears in schema)
If set to true and the specified parameter is not defined (not included in the request), an error will be returned.The parameter must not be present at all in the request for this setting to take effect, i.e. if it is present but its value is empty, it is considered present with an empty value.
required makes no sense if default is set, because the argument will always have a value.
register_rest_route( 'myplugin/v1', '/author/(?P<key>\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_awesome_func', 'args' => array( 'key' => array( 'required' => false // or true - required parameter ), ), ) );
-
validate_callback(string/callback)
Data validation function. The function must return true if validation passed, and false otherwise.The function may also return a WP_Error object, in which case the message will be added to the response object. For example, if you return such an object:
new WP_Error( 'err', 'Must match `^[a-zA-Z0-9:_-]+$` regex.' )
The response will be:
{ "code": "rest_invalid_param", "message": "Invalid parameter: name", "data": { "status": 400, "params": { "name": "Must match `^[a-zA-Z0-9:_-]+$` regex." }, "details": { "name": { "code": "err", "message": "Must match `^[a-zA-Z0-9:_-]+$` regex.", "data": null } } } }Let the function my_awesome_func() return a list of posts of the specified author, then:
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', [ 'methods' => 'GET', 'callback' => 'my_awesome_func', 'args' => [ 'id' => [ 'validate_callback' => function( $param, $request, $key ) { return is_numeric( $param ); }, ], ], ] );Request posts of author with ID = 1 at the address (assuming posts exist):
http://wp-test.ru/wp-json/myplugin/v1/author/1
An array of posts will be returned. But if you access:
http://wp-test.ru/wp-json/myplugin/v1/author/vasya
An error will be returned:
{ "code": "rest_no_route", "message": "No route was found matching the URL and request method", "data": { "status": 404 } }Because the id parameter did not pass the is_numeric() check, since the value vasya is not a number.
You might wonder why not just specify the function is_numeric() like this:
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_awesome_func', 'args' => array( 'id' => array( 'validate_callback' => 'is_numeric' ), ), ) );
But, as you can see from the example above, three parameters $param, $request, $key will be passed to the specified function and if all of them are passed to is_numeric() — a warning-level error will occur.
[29-May-2018 12:07:54 UTC] PHP Warning: is_numeric() expects exactly 1 parameter, 3 given in \sites\example.com\wp-includes\rest-api\class-wp-rest-request.php on line 858
There is a ticket on this subject.
-
sanitize_callback(string/callback)
Data sanitization function. Similar to validate_callback, but instead of true/false you should return the sanitized incoming value. Or you can return a WP_Error object.register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_awesome_func', 'args' => array( 'id' => array( 'sanitize_callback' => function ( $param, $request, $key ) { return (int) $param; } ), ), ) ); -
type(string) (appears in schema)
The type of the parameter value. Possible values:array,object,string,number,integer,boolean,null. If another type is specified, a 400 error will be returned. More about this parameter. -
minimum / maximum(integer) (used in schema)
Minimum or maximum value of the parameter. Only for type = integer. -
format(string) (used in schema)
Additional string format. Values will be validated against the specified format. More.date-time— date in RFC3339 format. see rest_parse_date()uri— uri according to esc_url_raw().email— See is_email().ip— v4 or v6 ip address. See rest_is_ip_address()uuid— uuid code of any version. See wp_is_uuid()hex-color— 3 or 6 character hex color with prefix#. See rest_parse_hex_color().
-
enum(array) (used in schema)
List of possible parameter values (when the parameter has a limited set of possible values).
-
Examples
#1 Registers an API route with multiple parameters.
//The Following registers an api route with multiple parameters.
add_action( 'rest_api_init', 'add_custom_users_api');
function add_custom_users_api(){
register_rest_route( 'mmw/v1', '/users/market=(?P<market>[a-zA-Z0-9-]+)/lat=(?P<lat>[a-z0-9 .\-]+)/long=(?P<long>[a-z0-9 .\-]+)', [
'methods' => 'GET',
'callback' => 'get_custom_users_data',
'permission_callback' => 'permission_check',
] );
}
Make sure that your regex expressions are fine. If the data does not match then the URL will return a 404.
Some examples are:
(?P[a-zA-Z0-9-]+) for slug (you can change slug for your custom name).
(?P\d+) for id.
(?P[a-z0-9 .\-]+) for longitude or latitude.
// Customize the callback to your liking
function get_custom_users_data( $data ){
// get users by market
$users = mmw_get_custom_users();
foreach ( $users as $key => $user ) {
$market = $user['Market'];
$long = $user['long'];
$lat = $user['lat'];
if( intval($market) === intval( trim($data['market']) ) ){
$result[] = array(
'user_login' => $user->user_login,
'avatar_url' => get_avatar_url($user->ID),
'lat' => $lat,
'long' => $long
);
}
}
return $result;
} #2 Getting the posts of the specified author
WordPress has default methods for this purpose, but let's create our own simple version as an example:
// registers the route
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
// Here we register our permissions callback.
// The callback is fired before the main callback to check if
// the current user can access the endpoint.
'permission_callback' => 'prefix_get_private_data_permissions_check',
) );
} );
// Processes the request
function my_awesome_func( WP_REST_Request $request ) {
$posts = get_posts( array(
'author' => (int) $request['id'],
) );
if ( empty( $posts ) )
return new WP_Error('no_author_posts', 'No posts found', array( 'status' => 404 );
return $posts;
}
Now let's get the author's posts with ID = 1 using a GET request to the address:
http://wp-test.ru/wp-json/myplugin/v1/author/1
We'll get an answer in json format if the posts are found:
[
{
"ID": 280,
"post_author": "1",
"post_date": "2018-04-10 21:06:29",
"post_date_gmt": "2018-04-10 18:06:29",
{ "post_content": "Hi! This article should be an exception.\r\n\r\n[smr_slider id='1']"
"post_title": "more article",
"post_excerpt": "",
"post_status": "publish",
"comment_status": "open",
"ping_status": "open",
"post_password": "",
"post_name": "eshhyo-statya",
"to_ping": "",
"pinged": "",
"post_modified": "2018-05-25 11:34:03",
"post_modified_gmt": "2018-05-25 08:34:03",
"post_content_filtered": "",
"post_parent": 0,
"guid": "http://wp-test.ru/?p=280",
"menu_order": 0,
"post_type": "post",
"post_mime_type": "",
"comment_count": "0",
"filter": "raw"
},
{
"ID": 273,
...
}
...
]
We'll get the answer in json format if the author has no posts:
{
"code": "no_author_posts",
{ "message": "No posts found",
"data": {
"status": 404
}
}
You can refine the function to get only the values you want:
// Process the request
function my_awesome_func( WP_REST_Request $request ) {
// Get the posts of the specified author
$posts = get_posts( array(
'author' => (int) $request['id'],
) );
if( empty( $posts ) )
return new WP_Error('no_author_posts', 'No posts found', array( 'status' => 404 );
// Create your data to return
$posts = array_map( function ( $post ) {
$post_data['title'] = esc_html( $post->post_title );
$post_data['url'] = esc_url( get_the_permalink( $post ) );
$post_data['comments'] = (int) $post->comment_count;
$post_data['likes'] = (int) get_post_meta( $post->ID, 'likes', true );
return $post_data;
}, $posts );
return $posts;
}
If there are posts, get an answer:
[
{
{ "title": "more article",
"url": "http://wp-test.ru/eshhyo-statya",
"comments": 3,
"likes": 11
},
{
{ "title": "my article",
...
},
...
] #3 More examples
See REST API Tutorial under Creating Routes. There you will find, for example, an example of creating routes based on the Controller Class (OOP).
#4 Args is a named array that usually includes the keys ‘methods’ and ‘callback’.
method defines which HTTP methods are to be processed by the function defined by ‘callback’.
method can be a string of comma-separated HTTP methods or an array of strings of HTTP methods.
A common practice is to use the WP_REST_Server constants to set the 'method'.
WP_REST_Server::READABLE = 'GET' WP_REST_Server::EDITABLE = 'POST, PUT, PATCH' WP_REST_Server::DELETABLE = 'DELETE' WP_REST_Server::ALLMETHODS = 'GET, POST, PUT, PATCH, DELETE'
Example:
// Get a list of locations. // Method GET via wp-json/store-locator-plus//locations/ // // Calls the get_locations method of the current class when the route is matched. // register_rest_route( 'my-plugin-slug/v2' , '/locations/', [ 'methods' => 'GET', 'callback' => [ this, 'get_locations' ], 'permission_callback' => 'permission_check', ] );
#5 The second args array - parameters of parameter
args can also contain an optional args array of single parameter parameters.
The second args array contains the default arguments, required arguments, validation callback, and sanitization callback that are in place for each argument passed in with the REST request.
The key name of this array is the name of the parameter being passed.
Example
add_action( 'rest_api_init', function() {
register_rest_route( 'myplugin/v1', '/author/(?P\d+)', [
'methods' => 'GET',
'callback' => 'my_awesome_func',
'args' => [
'id' => [
'validate_callback' => function( $param, $request, $key ) {
return is_numeric( $param );
},
],
],
] );
} );
Changelog
| Since 4.4.0 | Introduced. |
| Since 5.1.0 | Added a _doing_it_wrong() notice when not called on or after the rest_api_init |
| Since 5.5.0 | Added a _doing_it_wrong() notice when the required permission_callback argument is not set. |