As mentioned in previous articles, WP has a rich set of built-in features for working with its API.
Today, we’ll look at how to create a custom endpoint to read data.
To implement a basic API in WordPress, we’ll need the action hook rest_api_init and the function register_rest_route.
Here is the complete code:
add_action('rest_api_init', function()
{
/**
* Read
*/
register_rest_route('app/v1', 'read', [
'methods' => WP_REST_Server::READABLE,
'permission_callback' => function(WP_REST_Request $Request)
{
//Sets
$test_string = $Request -> get_param('test_string');
if(empty( $test_string ))
{
return new WP_Error('test_string', 'Field test_string is required', [
'status' => 400
]);
}
return true;
},
'callback' => function(WP_REST_Request $Request)
{
$test_string = $Request -> get_param('test_string');
$test_integer = $Request -> get_param('test_integer');
$test_enum = $Request -> get_param('test_enum');
$test_array_integer = $Request -> get_param('test_array_integer');
return [
'test_string' => $test_string,
'test_integer' => $test_integer,
'test_enum' => $test_enum,
'test_array_integer' => $test_array_integer,
];
},
'args' => [
'test_string' => [
'description' => 'Some test string',
'type'=> 'string',
],
'test_integer' => [
'description' => 'Some test integer',
'type'=> 'integer',
'sanitize_callback' => 'absint',
],
'test_enum' => [
'description' => 'Some test enum',
'type' => 'string',
'enum' => ['yes', 'no'],
'required' => true,
],
'test_array_integer' => [
'description' => 'Some test array integer',
'type' => 'array',
'items' => [
'type' => 'integer',
],
'default' => [],
],
]
]);
});As you’ve probably guessed, to work with any WP API, we must wrap our code in a hook:
add_action('rest_api_init', function()
{
/**
* API code here
*/
});The core of our implementation is the WordPress function register_rest_route, which registers our custom endpoint. It takes four parameters:
$namespace – the first part of the route.
$route – the second part, can include regular expressions.
$args – an array of settings for the endpoint.
$override – whether to override an existing route.
Now let’s take a closer look at the third argument ($args). We use four keys:
methods – specifies the HTTP method (GET, POST, etc.).
permission_callback – a function that runs before the main callback, useful for permission checks (e.g., is the user the post author).
callback – the function that handles the logic of the endpoint.
args – an array of expected request parameters, including validation and default values.
For example, in permission_callback, we can define our validation:
'permission_callback' => function(WP_REST_Request $Request)
{
//Sets
$test_string = $Request -> get_param('test_string');
if(empty( $test_string ))
{
return new WP_Error('test_string', 'Field test_string is required', [
'status' => 400
]);
}
return true;
},In this code, we check whether the variable $test_string has a value. If it’s empty, we return an error and halt execution.
In the callback block, we simply return data from the GET request, although you could implement any logic here:
'callback' => function(WP_REST_Request $Request)
{
$test_string = $Request -> get_param('test_string');
$test_integer = $Request -> get_param('test_integer');
$test_enum = $Request -> get_param('test_enum');
$test_array_integer = $Request -> get_param('test_array_integer');
return [
'test_string' => $test_string,
'test_integer' => $test_integer,
'test_enum' => $test_enum,
'test_array_integer' => $test_array_integer,
];
},Under the “args” key, we list all the GET/POST parameters we plan to use:
'args' => [ 'test_string' => [ 'description' => 'Some test string', 'type'=> 'string', ], 'test_integer' => [ 'description' => 'Some test integer', 'type'=> 'integer', 'sanitize_callback' => 'absint', ], 'test_enum' => [ 'description' => 'Some test enum', 'type' => 'string', 'enum' => ['yes', 'no'], 'required' => true, ], 'test_array_integer' => [ 'description' => 'Some test array integer', 'type' => 'array', 'items' => [ 'type' => 'integer', ], 'default' => [], ], ]
Interestingly, you can still access any request variable via:
$Request -> get_param('test_xxx');But if it wasn’t listed in “args”, it won’t be filtered or validated.
As you can see, creating a custom endpoint in WordPress is quite straightforward, especially if you refer to the official documentation or read WP core code.
Good luck!
