If you’ve ever wanted to connect your WordPress site with an external app, a mobile interface, or even a JavaScript frontend, you’ve probably heard about the WordPress REST API. It’s one of the most powerful features built into WordPress, allowing developers to send and receive data using standard HTTP requests — just like any other modern web application.

In this article, we’ll break down how to create a custom REST API endpoint in WordPress — step by step. You don’t need to be an expert; just a basic understanding of PHP and WordPress hooks will do.

What is the REST API?

Before diving in, let’s make sure we’re on the same page.

REST stands for Representational State Transfer. It’s a way of structuring APIs so different systems can communicate using standard web methods — like GET, POST, PUT, and DELETE.

In WordPress, REST API endpoints are simply URLs that return data in JSON format. You can use these endpoints to get information (like posts, users, or comments) or to send data (like adding a post or updating metadata).

Example:
If you visit

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

you’ll get a JSON list of all posts on your site.

That’s the default WordPress REST API in action.

Why Create a Custom Endpoint?

The default REST API covers a lot — posts, pages, users, comments, taxonomies, etc.
But sometimes, you need something more specific. For example:

  • You want to fetch only featured posts.
  • You want to expose a custom post type with specific fields.
  • You want to connect to an external service or provide filtered data.
  • You want a private API for a dashboard or app.

In such cases, you can register your own endpoint.

How It Works

Creating a custom REST API endpoint in WordPress mainly involves two things:

  1. Registering a route (the URL for your API endpoint)
  2. Writing a callback function (the logic that runs when someone calls that URL)

You can do this using the register_rest_route() function inside a plugin or your theme’s functions.php file.

Step-by-Step: Create a Custom Endpoint

Let’s build a simple endpoint that returns a list of recent posts with their titles, excerpts, and featured image URLs.

Step 1: Set Up a Basic Plugin File

You can place this code in your theme’s functions.php, but the cleaner way is to create a small plugin.

  1. Go to wp-content/plugins/
  2. Create a new folder: custom-api-endpoint
  3. Inside it, create a file: custom-api-endpoint.php
  4. Add this header:
<?php
/**
 * Plugin Name: Custom API Endpoint
 * Description: A simple plugin that adds a custom REST API endpoint.
 * Version: 1.0
 * Author: Rashed Hossain
 */

Now WordPress will recognize it as a plugin.

Step 2: Register a REST Route

Add this code below the plugin header:

add_action('rest_api_init', function () {
    register_rest_route('custom/v1', '/recent-posts', [
        'methods'  => 'GET',
        'callback' => 'get_recent_posts_data',
    ]);
});

Here’s what’s happening:

  • rest_api_init: This action runs when the REST API is initialized.
  • register_rest_route( $namespace, $route, $args ): This creates a new endpoint.

Let’s break down the parameters:

  • custom/v1: This is your namespace and version (like wp/v2 in the core API).
  • /recent-posts: This is your endpoint path.
  • 'methods' => 'GET': The HTTP method — you can also use 'POST', 'PUT', 'DELETE', or an array like ['GET', 'POST'].
  • 'callback': The function to run when the route is called.

Step 3: Create the Callback Function

Now we’ll define the function get_recent_posts_data:

function get_recent_posts_data($request) {
    $args = [
        'numberposts' => 5,
        'post_status' => 'publish',
    ];

    $posts = get_posts($args);
    $data = [];

    foreach ($posts as $post) {
        $post_id = $post->ID;

        $data[] = [
            'id'      => $post_id,
            'title'   => get_the_title($post_id),
            'excerpt' => get_the_excerpt($post_id),
            'image'   => get_the_post_thumbnail_url($post_id, 'full'),
            'link'    => get_permalink($post_id),
        ];
    }

    return rest_ensure_response($data);
}

Let’s unpack this:

  • We’re fetching the latest 5 published posts using get_posts().
  • For each post, we extract a few key details.
  • rest_ensure_response() ensures the output is properly formatted as JSON.

Step 4: Test It

Activate your plugin from the WordPress admin panel.
Then visit this URL in your browser:

https://yourwebsite.com/wp-json/custom/v1/recent-posts

You should see a JSON response that looks like this:

[
  {
    "id": 120,
    "title": "How to Speed Up WordPress",
    "excerpt": "Here are 10 ways to make your WordPress site faster...",
    "image": "https://example.com/wp-content/uploads/2025/10/image.jpg",
    "link": "https://example.com/how-to-speed-up-wordpress/"
  },
  ...
]

That’s it — your custom REST endpoint is live!

Step 5: Adding Parameters (Optional but Powerful)

Let’s make this API more flexible by allowing users to set the number of posts via a query parameter.

Update your register_rest_route() code:

register_rest_route('custom/v1', '/recent-posts', [
    'methods'  => 'GET',
    'callback' => 'get_recent_posts_data',
    'args'     => [
        'count' => [
            'default'           => 5,
            'sanitize_callback' => 'absint',
        ],
    ],
]);

Then update the callback to use it:

function get_recent_posts_data($request) {
    $count = $request->get_param('count');

    $args = [
        'numberposts' => $count,
        'post_status' => 'publish',
    ];

    // ... same as before
}

Now you can request:

https://yourwebsite.com/wp-json/custom/v1/recent-posts?count=10

and get 10 posts instead of 5.

Step 6: Adding Permissions

If you’re exposing sensitive data (like user details or private posts), you need to secure your endpoint.

You can add a permission callback to the route:

register_rest_route('custom/v1', '/private-data', [
    'methods'             => 'GET',
    'callback'            => 'get_private_data',
    'permission_callback' => function () {
        return current_user_can('manage_options');
    },
]);

This ensures only logged-in admins can access it.
If someone else tries, they’ll get a 401 Unauthorized error.

Step 7: Returning Error Responses

You can also return structured errors using WP_Error.

Example:

if (empty($posts)) {
    return new WP_Error('no_posts', 'No posts found', ['status' => 404]);
}

This keeps your API responses clean and predictable.

Step 8: Using the Endpoint in JavaScript

Once you have the endpoint, you can easily call it from any JavaScript frontend — for example, inside a React app:

fetch('https://yourwebsite.com/wp-json/custom/v1/recent-posts')
  .then(res => res.json())
  .then(data => console.log(data));

This opens up endless possibilities — from dashboards to mobile apps — all powered by WordPress data.

Wrapping Up

Creating custom REST API endpoints in WordPress gives you full control over what data your site exposes and how. You’re no longer limited to the built-in endpoints — you can design APIs tailored exactly to your use case.

Let’s recap what we did:

  1. Registered a new REST route using register_rest_route().
  2. Wrote a callback that returns data in JSON format.
  3. Added query parameters and permission checks.
  4. Tested the endpoint through the browser or external app.

With this foundation, you can build anything — a React front-end, a mobile app, or an integration with third-party services — all running on top of your WordPress backend.

The REST API turns WordPress into a true application framework, not just a CMS.