To publish posts programmatically with the WordPress REST API, you send an authenticated POST request to the /wp/v2/posts endpoint. The request body, formatted as JSON, must include a title, content, and a status like ‘publish’, ‘draft’, or ‘future’. Authentication is best handled using Application Passwords for server-side scripts. This method allows for automating content workflows, scheduling posts, and integrating external content sources directly into your WordPress site, transforming content management from a manual task into a scalable, automated workflow.

Understanding the WordPress REST API Fundamentals
The WordPress REST API is a developer-oriented interface for interacting with your site’s content. It provides a structured, predictable way to create, read, update, and delete WordPress content using standard HTTP methods. Instead of clicking buttons in the admin dashboard, you send requests to specific URLs, known as endpoints. The default route for the API is typically https://yourdomain.com/wp-json/wp/v2/. All data is sent and received in JSON (JavaScript Object Notation), a lightweight and human-readable format. For anyone looking to automate content, the primary endpoint of interest is /wp/v2/posts. Sending a request to this URL is the programmatic equivalent of clicking “Add New Post”. The entire WordPress content model, from posts and pages to users and comments, is accessible through these endpoints, as detailed in the official REST API handbook. This direct access is what enables services to offer powerful features like direct publishing to WordPress blogs.
Comparing Authentication Methods for API Access
Before you can create a post, you must prove to WordPress who you are. The API offers several ways to handle authentication, each suited for different scenarios. The choice of authentication method is a critical security decision that defines who can access your site and from where. While options like Basic Auth exist, they are not recommended for production environments due to security risks. For most programmatic publishing, Application Passwords are the modern, secure, and recommended standard. Third-party services might use OAuth 2.0, but this is often too complex for simple scripts. A detailed breakdown can be found within the WordPress developer resources on authentication.
| Method | Best Use Case | Pros | Cons |
|---|---|---|---|
| Application Passwords | Server-to-server scripts, cron jobs, CI/CD pipelines | Easy to generate, built into WordPress Core (since 5.6), individually revocable. | Transmitted over HTTP (requires HTTPS), tied to a user account’s permissions. |
| Basic Auth | Local development testing ONLY | Simple to implement (username:password). | Highly insecure; sends credentials in plaintext with every request. Must not be used in production. |
| JWT (JSON Web Tokens) | Headless WordPress, Single Page Applications (SPAs) | Stateless, can be used by client-side JavaScript, granular permissions. | Requires a dedicated plugin; adds complexity for token management and expiration. |
| OAuth 2.0 | Third-party applications needing user permission | Industry standard for delegated authorization; users do not share credentials directly. | Very complex to implement; requires a plugin and a multi-step token exchange process. Overkill for internal scripts. |
How to Create a New Post with a curl Command
curl is a command-line tool for transferring data with URLs. It’s the most direct way to test the WordPress REST API. To create a post, you’ll send a POST request to the /wp/v2/posts endpoint. The request must include an Authorization header and a JSON payload with the post’s data.
First, you need an Application Password. Here is how to create one:
- Log in to your WordPress admin dashboard.
- Go to Users > Profile.
- Scroll down to the “Application Passwords” section.
- Enter a name for your new application (e.g., “My Publishing Script”) and click “Add New Application Password”.
- WordPress will generate a password like
abcd efgh ijkl mnop qrst uvwx. Copy this immediately; it will not be shown again.
This password is used with your username for authentication. You’ll combine them as username:password and Base64 encode them.
Here is a complete curl example to create a new draft post:
Replace YOURBASE64ENCODED_STRING with your Base64-encoded username:password string. A successful request will return a 201 Created status code and the JSON object of the newly created post.

Publishing Posts with Python and JavaScript (Node.js)
While curl is great for testing, you’ll likely use a higher-level language for real automation. Python and JavaScript are popular choices.
Python Example using requests
Python’s requests library simplifies making HTTP requests. The process mirrors the curl command: set headers, create the JSON payload, and send a POST request.
JavaScript (Node.js) Example using axios
For Node.js environments, axios is a common promise-based HTTP client. The logic is identical: prepare authentication headers and post the JSON data.
Managing Post Status, Scheduling, and Updates
Programmatic publishing isn’t just about creating new posts; it’s about managing the entire content lifecycle. The REST API gives you full control over a post’s state.
The status field in your JSON payload is the key. You can set it to:
publish: Makes the post immediately live.draft: Saves the post as a draft.pending: Marks the post for review.private: Publishes the post privately, visible only to privileged users.future: Schedules the post to be published at a later time.
To schedule a post, you must set status to future and also provide a date field with a future date in ISO 8601 format (e.g., 2026-12-25T10:30:00). WordPress’s cron system will automatically publish the post at the specified time.
To update an existing post, you send a POST request to its specific endpoint: /wp/v2/posts/. The JSON payload only needs to include the fields you want to change. For example, to change a post’s title and publish a draft, you would send { "title": "New Updated Title", "status": "publish" } to https://yourdomain.com/wp-json/wp/v2/posts/123.
The choice of authentication method isn’t just a technical detail; it’s a security decision that defines who can access your site and from where.
Assigning Taxonomies: Categories and Tags Programmatically
A post without categories or tags is an organizational dead end. You can assign them during creation or with an update request. The API expects an array of integer IDs for the categories and tags fields.
To find the ID for a specific category or tag, you can either inspect the URL when editing it in the WordPress admin (it will contain tag_ID=XX) or query the API endpoints /wp/v2/categories and /wp/v2/tags to get a full list with their corresponding IDs.
Here’s how you would include them in your JSON payload:
Passing an empty array [] will remove all associated categories or tags from the post.
Working with Custom Post Types and Custom Fields (Meta)
Many sophisticated WordPress sites rely on Custom Post Types (CPTs) for content like ‘Events’, ‘Products’, or ‘Portfolio Items’. The REST API supports these out of the box, provided they were registered correctly. Each CPT gets its own endpoint, typically following the pattern /wp/v2/. For a ‘product’ CPT, the endpoint would be /wp/v2/products.
Similarly, custom fields (post meta) are accessible via the meta key in your JSON payload. For this to work, the custom field must be explicitly registered to be shown in the REST API. This is a security measure to prevent accidental data exposure.
You would add this code to your theme’s functions.php file or a custom plugin:
Once registered, you can set its value in your API request:
"meta": { "my_subtitle": "An engaging subtitle for the post" }
This functionality is essential for any headless WordPress implementation or advanced content integration.
Best Practices for Security and Error Handling
Using the REST API introduces a new entry point into your website, so security is paramount. Likewise, strong error handling makes your scripts reliable.
Security Best Practices:
- Enforce HTTPS: Never send credentials over an unencrypted connection. Use a valid SSL certificate.
- Use Application Passwords: Avoid using your primary user password. Application passwords can be individually revoked without affecting your main login.
- Principle of Least Privilege: Create a dedicated API user with the minimum role required (e.g., ‘Editor’ or ‘Author’, not ‘Administrator’).
- Secure Credential Storage: Do not hardcode API keys or passwords in your scripts. Use environment variables or a secure vault service. Many guides cover how to manage application secrets securely.
Handling API Responses:
Your script should always check the HTTP status code of the API response. Key codes include:
- 201 Created: Success. The post was created. The full post object is in the response body.
- 400 Bad Request: Your JSON is likely malformed or a required field is missing.
- 401 Unauthorized: Authentication failed. Check your username and application password.
- 403 Forbidden: Authentication worked, but the user lacks permissions (e.g., an ‘Author’ trying to edit another user’s post).
The response body for an error code will contain a JSON object with a specific code and message explaining what went wrong.
An API error message is not a failure; it’s a specific instruction from WordPress on what to fix in your next request.

Strategies for Bulk Publishing and Content Synchronization
Publishing one post is simple, but what about migrating 1,000 articles or synchronizing an external product database? Sending thousands of API requests in a rapid-fire loop can overload your server or trigger rate limits imposed by your host or security plugins. Smart strategies are needed for bulk operations.
- Implement a Queue: Instead of making API calls directly, push publishing jobs to a queue (using tools like Redis or RabbitMQ). A separate worker process can then pull jobs from the queue and execute them at a controlled pace.
- Pace Your Requests: If a queue is overkill, introduce a simple delay (e.g.,
sleep(1)in PHP orsetTimeoutin JavaScript) between each API call to avoid hammering the server. - Transactional Logic: For multi-step processes like creating a post and then uploading its images, design your script to handle failures at any step without leaving orphaned data.
These are the same principles that power large-scale content platforms. For instance, services that offer auto-publishing capabilities use a strong API-driven backend to syndicate content to thousands of sites. This approach is versatile, enabling automated blog publishing not just for WordPress, but for platforms like Shopify as well. Mastering these programmatic techniques provides complete control over your content pipeline. For those looking to bypass the development and maintenance of such systems, you can explore our automated content platform.
Frequently Asked Questions
How do I find the ID for a category or tag?
A simple method is to navigate to Posts > Categories (or Tags) in your WordPress admin. Hover your mouse over the category you need, and look at the link preview in the bottom of your browser. The URL will contain a string like tag_ID=27. That number, 27, is the ID. Alternatively, a GET request to the /wp/v2/categories endpoint will return a JSON array of all categories and their IDs.
Can I upload images and set a featured image via the REST API?
Yes, this is a two-step process. First, you must upload the image file by sending a POST request to the /wp/v2/media endpoint with the proper headers. This request is more complex than a simple text post. A successful upload will return a media object containing a new ID. Second, you create or update your post and set the featured_media field to this new media ID.
What are the most common permission errors when publishing?
The most frequent permission error is restforbidden, which returns a 403 Forbidden status code. This almost always means the user account tied to your Application Password does not have the necessary capabilities. For creating posts, the user needs the publishposts capability, which the ‘Editor’ and ‘Administrator’ roles have by default. ‘Author’ can create posts but not edit others’.
Is the REST API enabled by default in WordPress?
Yes, the REST API is a core feature and has been enabled by default since WordPress version 4.7. You can typically find it at https://yourdomain.com/wp-json/. However, some security plugins or hosting providers may disable it or restrict access. If you get a 404 error on the endpoint, you should check your security plugin settings or contact your host.

Leave a Reply