Direct answer: yes, you can build an n8n WordPress integration without a plugin, and frankly, for most technical workflows, that is the better way to do it. Use a WordPress Application Password, authenticate from n8n’s HTTP Request node, and send JSON to the native WordPress REST API endpoint for posts or your Custom Post Type. If you want to publish into a CPT, it must be registered with show_in_rest => true, otherwise n8n is posting into a void and WordPress will act like your route never existed. The usual workflow is simple: Webhook node receives data → n8n transforms it → HTTP Request node posts it into WordPress. No plugin needed. No extra abstraction. No plugin-update roulette.
That matters more in 2026 than it did a few years ago. Technical teams are getting less patient with bloated plugin stacks and more willing to run API-native workflows that can be inspected, debugged, and extended without crossing their fingers after every WordPress update. If your publishing workflow depends on a plugin just to move structured JSON into WordPress, you are adding weight where you should be removing it.
What n8n WordPress integration means
Let’s define the thing properly, because too many posts on this topic stay fluffy and vague.

An n8n WordPress integration is a workflow where n8n acts as the automation and orchestration layer, while WordPress acts as the content destination through its REST API. n8n receives data from a webhook, app, form, spreadsheet, AI workflow, database, or internal tool, then sends a properly authenticated HTTP request to WordPress to create, update, or manage content.
That is the whole mechanism.
You are not “connecting WordPress to n8n” in some magical platform sense. You are sending structured HTTP requests to native WordPress API endpoints. Once you understand that, the setup stops feeling mysterious and starts feeling like normal engineering.
Why no-plugin is usually the smarter option
Here is the opinionated part: plugin-first thinking is often a bad habit.
A lot of WordPress users have been trained to solve every integration problem by installing something. Need forms? Plugin. Need SEO? Plugin. Need caching? Plugin. Need the API to talk to another system? Apparently another plugin. That instinct is understandable, but for this use case, it is usually wrong.
WordPress already has a REST API. WordPress already supports Application Passwords for external authentication. n8n already has a Webhook node and an HTTP Request node. So what exactly is the plugin doing for you besides sitting in the middle and becoming one more thing to maintain?
Here’s the operational reality:
| Approach | What happens technically | Operational outcome |
|---|---|---|
| Direct REST API from n8n | n8n sends authenticated JSON directly to WordPress endpoints | Clear debugging, fewer moving parts, easier scaling |
| Plugin-based connector | Plugin adds its own logic layer between n8n and WordPress | More update risk, less transparency, extra compatibility issues |
| Custom plugin when not needed | You create another middleware layer for basic HTTP operations | More code to support, no real gain for simple publishing workflows |
If all you need is “take incoming data and publish it into WordPress,” the native stack is enough. More than enough, actually.
How the architecture works
The clean version looks like this:
| Component | Job |
|---|---|
| n8n Webhook node | Receives the incoming payload |
| n8n Set / Edit Fields / Code node | Shapes the payload into the format WordPress expects |
| n8n HTTP Request node | Sends the authenticated request to WordPress |
| WordPress REST API | Accepts the JSON and creates the content object |
| WordPress Application Password | Authenticates the external request |
Custom Post Type with show_in_rest | Makes the CPT available in REST routes |
That is the architecture. Not glamorous. Very effective.
And this is why direct API work ages better than plugin-heavy setups: every layer has a visible purpose. You can inspect each request, each response, each header, each returned field. When something breaks, you can usually find the cause in minutes instead of guessing which plugin author forgot to test against the latest WordPress version.
Step-by-step auth setup
This is the part people mess up most often, and not because it is hard. Because they rush it.
Check that the WordPress REST API is reachable
Before touching n8n, make sure the site actually exposes its REST routes.
Your WordPress REST API root should be:
https://yourdomain.com/wp-json/
If that route is not reachable, stop there. Don’t start fiddling with credentials or webhook payloads. If the API root is unavailable, the problem lives at the site, server, firewall, or rewrite-rule level.
This sounds obvious, but a depressing number of integrations are debugged backwards. People start in n8n, then blame authentication, then blame payload formatting, when the WordPress endpoint itself was never accessible in the first place.
Create an Application Password in WordPress
For this setup, use a WordPress Application Password tied to the user account that will own the API writes.
Use a dedicated user whenever possible. Don’t lazily use your personal admin account for production automation unless you enjoy terrible audit trails and future confusion.
Create the password in the WordPress user profile, give it a recognizable label like n8n-publishing, and store it properly. WordPress shows it once. Lose it, and you regenerate it.
Add credentials in n8n
In n8n, store the WordPress credentials properly rather than hardcoding them all over your workflow.
Use:
| Field | Value |
|---|---|
| Username | WordPress username |
| Password | WordPress Application Password |
| Authentication type | Basic Auth |
| Base site URL | Your WordPress domain |
That gives the HTTP Request node what it needs to authenticate against WordPress. Clean, repeatable, easy to rotate later.
Force yourself to use HTTPS
This should not even need saying in 2026, yet here we are.
If you are sending Basic Auth credentials over anything except HTTPS, you are not doing a professional integration. You are improvising in public.
Use HTTPS. Always.
Expose your Custom Post Type to REST
This is the biggest gotcha in the entire setup.
If you want n8n to publish into a Custom Post Type, that CPT must be registered with REST support. The crucial argument is:
'show_in_rest' => true
Example:
register_post_type('case-study', [
'label' => 'Case Studies',
'public' => true,
'show_in_rest' => true,
'supports' => ['title', 'editor', 'excerpt', 'thumbnail', 'custom-fields'],
]);
Without show_in_rest => true, WordPress does not expose the CPT route properly to the REST API. Then people spend an hour testing credentials, changing cURL syntax, re-saving permalinks, and muttering at n8n, when the actual problem is one line of post type registration.
Brutal, but common.
The short framework
For the AI-overview crowd and the impatient engineer alike, here is the compact version:
| Step | Action | Result |
|---|---|---|
| 1 | Create a WordPress Application Password | External authentication is ready |
| 2 | Confirm wp-json works | The REST API is reachable |
| 3 | Register CPT with show_in_rest => true | Your custom endpoint exists |
| 4 | Build Webhook → HTTP Request in n8n | Data can flow from trigger to WordPress |
| 5 | Test with cURL before production | You isolate auth and payload issues fast |
That is the real checklist. Not “install plugin, hope for best.”
The n8n workflow
The best starter workflow is almost boringly simple:
- Webhook
- Set or Edit Fields
- HTTP Request
The Webhook node receives inbound JSON. That might come from a form, an internal tool, a Google Sheet automation, another app, or your own backend. n8n then transforms that data so WordPress gets exactly the fields it expects. Then the HTTP Request node sends the authenticated POST request to the right WordPress REST route.
This is a good thing. Boring is good in automation. Boring means predictable.
Example payload entering the webhook
Suppose the webhook receives this:
{
"title": "How We Automated Content Publishing",
"content": "This article was created through n8n and pushed into WordPress without plugins.",
"slug": "automated-content-publishing",
"status": "publish"
}
That payload is enough to create a post or CPT entry if your endpoint and authentication are correct.
Example target endpoint
For standard WordPress posts:
POST https://yourdomain.com/wp-json/wp/v2/posts
For a Custom Post Type named case-study:
POST https://yourdomain.com/wp-json/wp/v2/case-study
That second route only works if the CPT is exposed through REST. Worth repeating because this is where people trip over their own shoelaces.
n8n HTTP Request node setup
Inside the HTTP Request node, configure it like this:
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://yourdomain.com/wp-json/wp/v2/case-study |
| Authentication | Basic Auth |
| Content Type | JSON |
| Body format | JSON |
| Send body | Enabled |
Example JSON body in n8n using expressions:
{
"title": "{{$json.title}}",
"content": "{{$json.content}}",
"slug": "{{$json.slug}}",
"status": "{{$json.status}}"
}
That is enough for a basic publishing flow.
If you want to create more advanced workflows later, you can add taxonomy assignment, featured media IDs, excerpts, custom meta, post status control, or editorial review branches. But the basic mechanism remains the same: authenticated JSON into a WordPress REST route.
Custom cURL examples
You asked for custom cURL examples, and yes, these matter. A lot.
You should always test the endpoint with cURL before assuming the problem is in n8n. cURL strips away workflow noise and lets you see whether the issue is route exposure, authentication, or payload shape.
Create a regular WordPress post
curl --request POST "https://yourdomain.com/wp-json/wp/v2/posts" \
--user "wp_username:YOUR_APPLICATION_PASSWORD" \
--header "Content-Type: application/json" \
--data '{
"title": "n8n to WordPress test post",
"content": "Posted through the WordPress REST API with no plugin.",
"status": "draft"
}'
Create a Custom Post Type entry
curl --request POST "https://yourdomain.com/wp-json/wp/v2/case-study" \
--user "wp_username:YOUR_APPLICATION_PASSWORD" \
--header "Content-Type: application/json" \
--data '{
"title": "Webhook-created case study",
"content": "This CPT entry was created from an n8n automation.",
"status": "publish",
"slug": "webhook-created-case-study"
}'
Inspect available REST routes
curl "https://yourdomain.com/wp-json/wp/v2/"
That last command is useful when you suspect the route itself is missing. If your CPT route is not in the output, stop blaming n8n. WordPress is not exposing the content type correctly.
Screenshot placement and what it should show
You wanted a screenshot of the n8n webhook node successfully posting to a Custom Post Type. Good. That kind of screenshot actually proves something.
Place it right after the section describing the workflow and before the troubleshooting section. That is where it has the most credibility value.
Use this caption:
n8n Webhook and HTTP Request nodes successfully creating a WordPress Custom Post Type entry through the native REST API
The screenshot should show:
| Screenshot element | Why it matters |
|---|---|
| Webhook node | Proves the trigger is real |
| HTTP Request node configured to the CPT endpoint | Proves the route and method |
| Successful execution status | Proves authentication and write permissions worked |
| Returned response body with post ID or link | Proves WordPress accepted the request |
Even better if you can pair it with a second screenshot from the WordPress admin showing the new CPT item. One screenshot shows the mechanism. The second shows the result. Together, they stop the post from sounding theoretical.
What docs usually don’t emphasize
This is the part people remember because it hurts when you ignore it.
The CPT route name may not match your assumptions
The route is not based on your feelings. It is based on the registered post type key or REST base.
If your post type is registered as case-study, the route might be /case-study, not /case-studies. If you expect one and the registration uses another, you get a 404 and start inventing conspiracy theories about WordPress REST bugs.
Check the real route.
Authentication success does not guarantee write success
A request can authenticate correctly and still fail because the user lacks capability, the post type does not accept the fields you sent, or the payload shape is invalid.
That is why testing only “can I authenticate?” is not enough. You need to test a real write with real data.
Test URL and production URL in n8n are not the same thing
This catches people more often than it should.
n8n gives you a test webhook URL and a production webhook URL. Teams test on one, deploy using another, and then complain the workflow “suddenly stopped working.” It did not suddenly stop. You moved from test mode into production without respecting the difference.
Reverse proxy setup can sabotage webhooks
If you are self-hosting n8n behind a reverse proxy and the webhook URL is being generated incorrectly, external systems may not be able to hit the webhook properly even though everything looks fine internally.
That is the kind of issue that burns time because every individual component appears healthy when inspected in isolation.
Custom fields are their own world
Posting title and content is the easy part. Posting custom fields is where workflows get interesting.
If your custom fields are not properly registered for REST exposure, WordPress may ignore them or reject them depending on the implementation. This is one of those maddening areas where people assume “the field exists in wp-admin, therefore the API will accept it.” No. Different layers. Different rules.
Pro-Tip
Pro-Tip: set your workflow to publish as
draftfirst, notpublish, until you have confirmed the route, field mapping, slug behavior, and user permissions in production. It is far easier to review good drafts than to clean up 40 malformed live entries created by an overconfident automation.
That is not just cautious. It is civilized.
Our Experience with n8n WordPress integration
Our experience with n8n WordPress integration is that it works extremely well when treated like a real API workflow and becomes frustrating when treated like a drag-and-drop toy.
The cleanest implementations always follow the same pattern. First, verify the WordPress route directly. Second, test auth with cURL. Third, make sure the CPT is actually in REST. Fourth, build the n8n workflow. Fifth, inspect the returned JSON, not just the green success checkmark.
The messy implementations do the opposite. They begin in n8n, skip route verification, skip cURL testing, assume the CPT is fine, hardcode credentials in a hurry, then complain that “WordPress REST is unreliable.” Usually it is not unreliable. Usually the setup was sloppy.
We also think a lot of people underestimate the strategic upside here. Once you have n8n publishing cleanly into WordPress over REST, WordPress stops being a fragile little island and becomes one node in a bigger content operations system. That matters. You can receive data from Airtable, internal tools, CRMs, AI pipelines, lead forms, scraping jobs, editorial spreadsheets, approval systems, and then funnel it into WordPress in a structured way.
That is much more interesting than “look, we connected WordPress to another plugin.”
And yes, there is a broader market shift here. In 2026, serious operators are moving away from plugin-heavy publishing workflows and toward modular automation stacks where every integration point is explicit. It is not just about speed. It is about control. The less invisible glue you rely on, the less likely your stack turns into a haunted house six months later.
Common errors and what they usually mean
| Symptom | Likely cause | Real fix |
|---|---|---|
404 Not Found | CPT route does not exist | Check show_in_rest => true and verify the actual route |
401 Unauthorized | Bad credentials | Recreate the Application Password and test again |
403 Forbidden | User lacks permissions or auth formatting is wrong | Check user role, capabilities, and exact credential values |
| Successful request but missing fields | Unsupported fields or unregistered custom data | Confirm field support and REST registration |
| Webhook works in testing but not live | Wrong production webhook setup | Verify you are using the right n8n webhook URL |
| Intermittent failures | Proxy, hosting, timeout, or workflow execution issues | Inspect environment and execution logs rather than guessing |
Hyperlinked valuable assets
A couple of assets are genuinely worth linking in the article body because they help technical readers verify implementation details without forcing ugly raw URLs into the page:
| Anchor text | Why it is worth linking |
|---|---|
| WordPress REST API handbook | Best core reference for routes, behavior, and object schemas |
| Application Passwords documentation | Useful when setting up auth correctly |
| REST support for Custom Post Types | Critical for the show_in_rest issue |
| n8n HTTP Request node docs | Helpful for node configuration details |
| n8n Webhook node docs | Useful for understanding test vs production webhooks |
Those are worth keeping because they are real assets, not filler links pretending to be useful.
Final thought
The technical barrier to a solid n8n WordPress integration is not high. The real barrier is whether you are willing to treat WordPress like an API-capable system instead of a plugin vending machine. So the uncomfortable question is this: if your content operations still depend on adding one more plugin every time you need WordPress to talk to another tool, are you building infrastructure, or just decorating technical debt?
If you want, I can also regenerate this in WordPress block format with a TopTut-style TL;DR box, screenshot placeholder, and cleaner H2/H3 structure for direct publishing.