Create a REST API in WordPress (With Examples)

WordPress is an open-source CMS that empowers millions of websites and it becomes a powerful headless CMS when the WordPress REST API is harnessed. Learn how to create a WordPress API with example code.

REST API in WordPress

A WordPress REST API is a collection of endpoints that allows developers to interact with website data through HTTP requests. It is a structured and JSON based interface to retrieve, create, update and delete website data in a flexible way. In this post, we will learn how to access WordPress API endpoints and how to create custom endpoints with examples.

 

How to Access WordPress API Endpoints?

The REST API in WordPress is enabled by default since version 4.7 and later. The endpoints of the REST API can be accessed by appending /wp-json/ to the website URL to fetch website details, while for other endpoints like posts, pages and users, it can be accessed by appending /wp-json/wp/v2/ to the URL. The following are WordPress API endpoints available by default:

  • /posts: To get, create, update and delete posts.
  • /pages: To get, create, update and delete pages.
  • /categories: To get, create, update and delete categories.
  • /tags: To get, create, update and delete tags.
  • /comments: To get, create, update and delete comments.
  • /users: To get, create, update and delete users.

For the sake of example, we will be using the posts endpoints. So to get posts, we will use the endpoint with a GET request like this:

GET https://example.com/wp-json/wp/v2/posts

To create a post, we will need to send a POST request to the posts endpoint with authentication headers like this:

POST https://example.com/wp-json/wp/v2/posts

// Headers
Authorization: Basic base64encoded(username:password)
Content-Type: application/json

// Body
{
"title": "My New Post",
"content": "This is the content of the new post.",
"status": "publish"
}

To update a post, we will send a POST request to the posts endpoint with authentication headers like in the create post example:

POST https://example.com/wp-json/wp/v2/posts/1

// Headers
Authorization: Basic base64encoded(username:password)
Content-Type: application/json

// Body
{
"title": "Update post title",
}

To delete a post, we will send a DELETE request to the posts endpoint with authentication headers. The query parameter ?force=true can be used to force a post to be deleted instead of moving to trash like this:

DELETE https://example.com/wp-json/wp/v2/posts/1

// Headers
Authorization: Basic base64encoded(username:password)

These were the four basic examples of how to use built-in REST API endpoints in WordPress.

 

How to Register Custom REST API Endpoints in WordPress?

In addition to default REST endpoints in WordPress, it lets developers create their own custom REST API endpoints. We can manage website data efficiently through headless API requests by adding custom API routes/endpoints. Steps involved in registering a custom REST API endpoint in WordPress are as follows:

  • Add an action for rest_api_init, providing the function to register API endpoints.
  • Use the WordPress function register_rest_route() with three parameters inside the function. The first one is the endpoint prefix, the second one is the specific API endpoint and the third one is an array of arguments.
  • Add the request methods allowed for this specific endpoint.
  • Add the callback function to process the API request and return a response.
  • Add the permission check callback function if the endpoint requires a permission check.
// An action hook to register API routes, we can add multiple API routes
add_action('rest_api_init', 'custom_rest_routes');
function custom_rest_routes(): void
{
register_rest_route('custom-endpoint/v1', '/custom-posts/', [
'methods' => WP_REST_Server::ALLMETHODS,
'callback' => 'custom_posts_rest_callback',
'permission_callback' => 'custom_posts_rest_permissions_callback',
]);
}

// Callback to process the API request and return a proper response
function custom_posts_rest_callback(WP_REST_Request $request)
{
// The code logic to process the request goes here
}

// Limit the API access with a permission check callback
function custom_posts_rest_permissions_callback()
{
return current_user_can('manage_options');
}

This is a general example of registering any API endpoint in WordPress. We hook into the rest_api_init hook and register REST routes using the register_rest_route() function with a callback function to process the request and return the response and a permission callback function. The above code snippet can register a specific REST route for all HTTP methods. We can handle different HTTP methods differently. All these methods should then return a WP JSON response.

 

API Request to Get Post(s) in WordPress (GET Method)

The GET method is used to fetch data or a set of data from the server. It only retrieves data not modifies it, like retrieving all posts or retrieving a single post, providing the post ID as a parameter. The WP REST route for the GET method can be registered like this:

// API route to get all posts
register_rest_route('custom-endpoint/v1', '/custom-posts/', [
[
'methods' => WP_REST_Server::READABLE, // GET
'callback' => 'get_custom_posts',
'permission_callback' => 'custom_posts_rest_permissions_callback',
]
]);

// Callback to process request and return a proper response
function get_custom_posts(WP_REST_Request $request): WP_REST_Response
{
$posts = get_posts([
'post_type' => 'post',
'posts_per_page' => 5,
'post_status' => 'publish',
]);

$data = [];

foreach ($posts as $post) {
$data[] = [
'id' => $post->ID,
'title' => get_the_title($post->ID),
'content' => apply_filters('the_content', $post->post_content),
'date' => $post->post_date,
];
}

return new WP_REST_Response($data, 200);
}

// API route to get a specific post by ID
register_rest_route('custom-endpoint/v1', '/custom-posts/(?P<id>\d+)', [
[
'methods' => WP_REST_Server::READABLE, // GET
'callback' => 'get_custom_post',
'permission_callback' => 'custom_posts_rest_permissions_callback',
]
]);

// Callback to process request and return a proper response
function get_custom_post(WP_REST_Request $request): WP_REST_Response
{
$post_id = (int) $request['id'];

$post = get_post($post_id);

if (!$post) {
return new WP_REST_Response([
'message' => __('Failed to get post', 'text-domain')
], 400);
}

return new WP_REST_Response($post, 200);
}
 

API Request to Create a Post in WordPress (POST Method)

The POST method is used to create a new resource on the server, where the data is sent in the request body. The WP REST route for the POST method to create a resource can be registered like this:

// API route to create a new post
register_rest_route('custom-endpoint/v1', '/custom-posts/', [
[
'methods' => WP_REST_Server::CREATABLE, // POST
'callback' => 'custom_create_post',
'permission_callback' => 'custom_posts_rest_permissions_callback',
],
]);

// Callback to create a post and return a proper response
function create_custom_post(WP_REST_Request $request): WP_REST_Response
{
$title = sanitize_text_field($request->get_param('title'));
$content = wp_kses_post($request->get_param('content'));

$post_id = wp_insert_post([
'post_title' => $title,
'post_content' => $content,
'post_status' => 'publish',
'post_type' => 'post',
]);

if (is_wp_error($post_id)) {
return new WP_REST_Response([
'message' => __('Failed to create post', 'text-domain')
], 400);
}

return new WP_REST_Response([
'message' => __('Post created successfully', 'text-domain'),
'post_id' => $post_id
], 201);
}
 

API Request to Update a Post in WordPress (POST Method)

The update request uses the same POST method, with one difference that it accepts the ID of the resource to update. This does not create a new resource and the WP REST route for the POST method to update a resource can be registered like this:

// API route to update a post
register_rest_route('custom-endpoint/v1', '/custom-posts/(?P<id>\d+)', [
[
'methods' => WP_REST_Server::EDITABLE, // POST (Update)
'callback' => 'update_custom_post',
'permission_callback' => 'custom_posts_rest_permissions_callback',
]
]);

// Callback to update a post and return a proper response
function update_custom_post(WP_REST_Request $request): WP_REST_Response
{
$post_id = (int) $request['id'];

$title = sanitize_text_field($request->get_param('title'));
$content = wp_kses_post($request->get_param('content'));

$updated = wp_update_post([
'ID' => $post_id,
'post_title' => $title,
'post_content' => $content,
], true);

if (is_wp_error($updated)) {
return new WP_REST_Response([
'message' => __('Failed to update post', 'text-domain')
], 400);
}

return new WP_REST_Response([
'message' => __('Post updated successfully', 'text-domain'),
'post_id' => $post_id
], 200);
}
 

API Request to Delete a Post in WordPress (DELETE Method)

The DELETE method is used to delete a resource on the server and expects a resource ID. The WP REST route for the DELETE method can be registered like this:

// API route to delete a post by ID
register_rest_route('custom-endpoint/v1', '/custom-posts/(?P<id>\d+)', [
[
'methods' => WP_REST_Server::DELETABLE, // DELETE
'callback' => 'delete_custom_post',
'permission_callback' => 'custom_posts_rest_permissions_callback',
],
]);

// Callback to delete a post and return a proper response
function delete_custom_post(WP_REST_Request $request): WP_REST_Response
{
$post_id = (int) $request['id'];

$deleted = wp_delete_post($post_id, true); // true = force delete

if (!$deleted) {
return new WP_REST_Response([
'message' => __('Failed to delete post', 'text-domain')
], 400);
}

return new WP_REST_Response([
'message' => __('Post deleted successfully', 'text-domain'),
'post_id' => $post_id
], 200);
}

We just demonstrated how to create a custom REST API in WordPress with basic CRUD methods. The API can be accessed at https://example.com/wp-json/custom-endpoint/v1/custom-posts to get, add, update and delete posts. Always remember to add authentication to secure API calls when data is supposed to change and always sanitize user input for security.