Sync 2 WordPress websites using REST API custom endpoints

Luckily, I recently had to find a solution to sync data between 2 WordPress websites. I say luckily because it gave me the chance to use WP REST API’s custom endpoints.

The data to be synced was not very complex fortunately, mostly basic post data. In this particular case I had to sync 2 custom post types, actually some custom fields, the post status and the permalink.

Adding custom endpoints

I must admit, for me, this as clear as it can be. Especially in a WordPress environment, the structure for adding a custom endpoint is very straight-forward.

This is something similar to what I used:

register_rest_route( 'm_api/v1', '/custom', array(
   'methods'  => 'POST',
   'callback' => array( $this, 'handle_api_request' ), // In a class
) );

What this does is:

  1. It adds a new route in the form of: – of course, you can use whichever structure you wish.
  2. It only passes through POST requests unless otherwise specified.
  3. And also has support for custom variables in the url ( ids and such ) – more on this in the documentation.

In this case – being a “closed circuit” situation, I used a secret key to sign all requests and make sure nobody gets in the middle. Along with HTTPS and considering no secret data was being sent, it was enough. You might want to use different types of authentication.

I’m not going to share the rest of the plugin because this is the only relevant part to this subject. What I am going to share is how I handled things from the other plugin ( on the other website ).

Connecting to the your new endpoint

In the “client” plugin, which I used to initiate the updates, I used a very simple structure.

First, I hooked on the save_post action to listen for a change in the post. After I had the data collected and validated from the post, I used this function to make the call:

public static function make_request( $data ) {

   if ( ! empty( $data ) ) {

      $data['token'] = self::get_token( $data );

      wp_remote_post( self::API_URL, array(
         'body' => $data,
      ) );


As mentioned above, I use a secret key to sign the data and use the very nice function wp_remote_post to send the data to the other website.

On the other website, the endpoint takes over and passes the data to the assigned function to process it.

I find this structure very easy to set up with 2 small plugins: safe & simple.