Create a Post with WordPress REST API from Remote Website
In this tutorial, I will guide you through the process of creating a post with the WordPress REST API. First, we’re going to talk about authentication, then we will send an example REST API request, and finally, we talk a little bit about request parameters.
WordPress REST API Authentication
Some time ago we had to use some external plugins in order to create an authentication with WordPress REST API from another website. One of those plugins was Application Passwords.
But the super-good news is that this plugin has been merged into WordPress Core version 5.6, and you do not have to install it anymore.
Now let’s get a pair of Login and Password for the REST API examples below.
Login – is the username. You can get a password if you go to the bottom of the profile settings page.

misha, and the password is 1HEu PFKe dnqM lr4j xDJX My63, we will need it in the examples below.If you’re working on localhost, do not forget to open wp-config.php file and add the following constant there:
define( 'WP_ENVIRONMENT_TYPE', 'local' );Create a Post with REST API – Example
Below, you will find some PHP code examples written with WordPress HTTP API functions, because I think there is no particular reason to use cURL for that purpose. I hope you don’t come up with the question of where to insert the code because it is more like a developer tutorial and I suppose you already know that anyway.
But now let me remind you that we have two websites:
- The first website – is the website where the post should be created; the first website is also the one where we created our application password.
- The second website – is the website that will interact with the first one with REST API. It will have all the code.
Let’s create a simple draft right now!
$login = 'misha';
$password = '1HEu PFKe dnqM lr4j xDJX My63';
// create a post with WordPress REST API
wp_remote_post(
'https://WEBSITE-DOMAIN/wp-json/wp/v2/posts',
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$login:$password" )
),
'body' => array(
'title' => 'My test',
'status' => 'draft',
)
)
);Once you run the above code correctly, the post will appear on “Website 1”.

Handle server response messages
Sometimes posts are not going to be created with the code you’re using. The good idea is to check error messages from the server and display them to users. I learned it the hard way when I only started developing my Simple WP Crossposting plugin. Because, it is much better to display a message to a user why something is not working instead of answering an extra support ticket.
$request = wp_remote_post( ... );
if( 'Created' !== wp_remote_retrieve_response_message( $request ) ) {
// ok we have some errors here
$body = json_decode( wp_remote_retrieve_body( $request ) );
print_r( $body );
}For example, you can get an error “Unknown username. Check again or try your email address,” which occurs when you’re trying to use an incorrect username in basic authentication of your REST API requests. I got it once when I tried to use the application name instead.
On the other hand, you can display success messages also:
$request = wp_remote_post( ... );
if( 'Created' === wp_remote_retrieve_response_message( $request ) ) {
$body = json_decode( wp_remote_retrieve_body( $request ) );
printf( 'The post %s has been created successfully', $body->title->rendered );
}More parameters for REST API requests
In the above example, we just used title and status to create a post with REST API. But obviously. you will need more parameters for that, at least post content or maybe some metadata.
So, let’s take a look at the table below:
| Parameter | Description |
|---|---|
date | The post date in a format, for example, 2024-11-07 05:00:00 |
slug | The post slug. |
status | The post status, for example draft, or published, or pending. |
password | The post password (if it is a password-protected post). |
title | The post title. |
content | The post content. |
author | The post author ID; should exist on “Website 2” |
excerpt | The post excerpt. |
featured_media | The ID of the post featured image. |
comment_status | open or closed |
ping_status | open or closed |
meta | The associative array of post’s custom fields, more about custom fields in REST API requests you can read here. |
sticky | Is it a sticky post? true or false. |
template | The custom post template name when used. |
categories | The array of category IDs. |
tags | The array of tag IDs. |
You might be wondering, where is the type parameter, so we can create a custom post type with the REST API requests? The thing is that the type of a post is defined not by a request body parameter but by an endpoint, for example:
/wp/v2/posts– regular WordPress posts,/wp/v2/pages– pages,/wp/v2/{$rest_base}– custom post types.
The $rest_base variable could be just a post type name or set specifically during a post type registration.
Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
Awesome! Thanks for this quite nice tutorial. I have a question:
Why do I need “2 websites”? Can’t I run this script on the same WordPress installation that I want to automatize?
Regards.
Hi Aleksam,
Yes, as an example – Gutenberg works on REST API.
Hello again, Misha.
is there a way to get media files from a remote blog, using this authetication plugin?
Could you help me, please?
Regards!
Hi,
Sure, here is the tutorial. Just do not forget to pass
typeparameter which should beattachment.Sweet! Thanks.
How can i add posts to a Custom Post Type via API?
Just pass
typeparameter in the first exampleHello Misha,
Thanks for this post. I was wondering how can I do this using JS?
Thanks
Hey Moses,
Sorry, usually I remove comments with unformatted code, but at this time I just decided to remove the code only, because you’re asking a good question.
I didn’t have a chance to do this with JS yet, but maybe somebody from my website readers kindly answers your question.
Hey Misha, how can i update the category of my posts?
Hey Sam,
Did you try to pass
'categories' => array( 1, 5, 10 )?Hi Misha,
great stuff, thanks!
Say I wanted to update a certain data field of all available products in WooCommerce, how would you approach that?
I know how to do this for one specific ID at a time, but to run a loop or so for certain products containing certain values?
Best,
Kjetil
This do solve my problem .
Is it possible to Update also Custom Fields while Updating a post? How?
Thanks
Yes, of course. This tutorial is about publishing with custom fields, but updating is kind of similar.
Hello.
Can you help with this problem?
I use this post for create custom PostType, but I get the error “Sorry, you are not allowed to create records from the person of this user.” What can this be connected with?
Was inattentive, problem solved
You should mention both sites need to have a wp instalation :-)
Thank you for highlighting that we need to use “Login – is the username.” instead of using application password name which results into 401 unauthorized otherwise.
I’m working on a localhost and I’m following your instructions as I read them, and I was wondering why my Application Password view is different from yours. So, I searched for it and found that I should change
WP_ENVIRONMENT_TYPE. Then I continued with your tutorial to find out that you mentioned this too.Perhaps you can say put the note about the localhost before the screenshot so that people will not experience what I have (if they are like me who do as I read and not read all then do… hahaha)
Thanks for this tutorial. Keep it up!
i try this code in postman below the error.
how to solve the
"code": "rest_cannot_create","message": "Sorry, you are not allowed to create posts as this user.",
"data": {
"status": 401
}
To use the correct application password, not a user password