Open a new browser tab and type your own domain followed by /wp-json/. Unless someone has deliberately locked it down, you’re looking at a wall of JSON: a machine-readable map of your posts, pages, users, media, taxonomies, and settings. That’s the WordPress REST API, and it’s been switched on by default on virtually every WordPress site since late 2016.
Most site owners have never opened that URL and have no idea it exists. It’s the quiet engine behind the block editor, the mobile app, and a growing pile of automations and headless front-ends. It’s also, by default, a public read-only window into parts of your site you probably assumed were private.
This guide covers what the REST API actually is, how to use it to automate real work, and the two or three settings worth tightening before someone else finds it first.
What the WordPress REST API Actually Is
The REST API is a set of URLs that hand back your site’s data as JSON instead of as a rendered web page. Ask /wp-json/wp/v2/posts and you get an array of your posts as structured data — title, content, author ID, date, categories — that any program can read. Ask the same endpoint with an HTTP POST and the right credentials, and you can create a post without ever loading wp-admin.
It landed in WordPress core in stages. The underlying infrastructure arrived in WordPress 4.4, and the content endpoints — posts, comments, terms, users, meta, settings, and more — merged into core with WordPress 4.7, released December 6, 2016. Since then, every standard install ships it turned on. The block editor you use every day talks to your site almost entirely through this API; that’s how it saves a draft without a full page reload.
The base route and the shape of a request
Everything hangs off one base route: /wp-json/. Under it sits the core namespace, wp/v2, and under that the individual endpoints. A few you’ll reach for constantly:
/wp-json/wp/v2/posts— posts, filterable by category, tag, author, date, and search term/wp-json/wp/v2/pages— pages/wp-json/wp/v2/media— the media library/wp-json/wp/v2/categoriesand/tags— your taxonomies/wp-json/wp/v2/users— author profiles (the one to watch; more on that below)/wp-json/wp/v2/settings— site settings, but only for authenticated administrators
If your permalinks are set to “Plain,” the pretty /wp-json/ route won’t resolve. WordPress still exposes the same data through a query-string form: ?rest_route=/wp/v2/posts. That fallback is handy when you’re debugging a site whose rewrite rules are broken.
How you’d actually call it
Reading is as simple as a GET request. From a terminal:
curl https://example.com/wp-json/wp/v2/posts?per_page=5
That returns your five most recent posts as JSON. Two response headers do the heavy lifting for pagination: X-WP-Total tells you how many items exist in total, and X-WP-TotalPages tells you how many pages of results there are at your current per_page size. The API caps per_page at 100, so pulling a large archive means walking through pages rather than asking for everything at once.
The REST API is what turns WordPress from a website into a content platform. It’s the reason you can run a React or Next.js front-end on your marketing site while editors keep working in the familiar WordPress dashboard, push new posts from a script the moment a product ships, or feed a chatbot your knowledge base. But the same door that lets your tools in is open to the public by default — so it’s worth understanding both halves.
What You Can Build With It
The reason to care about any of this is that the REST API removes the human from repetitive work. Anything you’d normally click through in the dashboard, a program can do on a schedule or in response to an event.
Headless and hybrid front-ends
In a headless setup, WordPress becomes a pure content store. Your editors write posts as usual, and a separate front-end — built in Next.js, Astro, or anything that speaks HTTP — fetches that content through the REST API and renders it however you like. You keep the editing experience people already know while getting a fast, modern, fully custom presentation layer. Plenty of teams run a hybrid version instead: a mostly-normal WordPress theme that pulls one or two dynamic sections (a live inventory count, a personalized block) from the API on the client side.
Automations and integrations
This is where a small business gets the most leverage. A few patterns we see constantly: a script that publishes a blog post the instant a new item lands in a spreadsheet, a nightly job that exports every post to a backup service, a webhook that posts a summary to Slack whenever an editor hits publish, or a CRM that reads your latest case studies to keep a sales microsite current. None of that requires a plugin — just an authenticated call to the right endpoint.
The last integration we wired up for a client was a two-line change in a no-code automation tool: when a form submission came in, create a draft post pre-filled with the submitter’s details so an editor could review and publish with one click. It replaced a copy-paste ritual that had been eating twenty minutes a day.
Feeding AI tools
The API’s structured output is a natural fit for the current wave of AI work. Because every post comes back as clean JSON with the fields already separated, it’s straightforward to pull your whole content library into a script that summarizes it, generates internal-link suggestions, or builds a retrieval index for a support chatbot. You’re not scraping rendered HTML and guessing where the article ends and the footer begins — the API already drew that line for you.
Authentication: Reading Is Open, Writing Is Not
Here’s the split that trips people up. Anonymous GET requests can read anything WordPress considers public — published posts, pages, and media. The moment you want to write data, read a draft, or touch anything private, you need to authenticate, and WordPress checks that the account you’re authenticating as actually has permission for that action.
Cookie authentication, for code running inside WordPress
When the block editor talks to the API, it’s already logged in through your browser session. WordPress protects those requests with a nonce — a short-lived token that proves the request came from your own admin screen and not a malicious site in another tab. If you’re writing a plugin or theme that calls the API from the front-end for a logged-in user, this is the mechanism you’ll use. It doesn’t work for anything outside the site itself.
Application Passwords, for everything external
For a script, a mobile app, or a third-party service, WordPress ships Application Passwords, added in WordPress 5.6 in December 2020. You generate one under Users → Profile, and it’s a dedicated credential — separate from your login password, revocable on its own, and scoped so you can hand one to each integration and pull it back without changing your real password. Requests send it using HTTP Basic Authentication, so the whole thing rides on your site running over HTTPS. By default WordPress won’t even offer Application Passwords on a connection that isn’t secure.
For larger or multi-user integrations, OAuth 2.0 flows are available through dedicated plugins, but for the vast majority of “let this one script post to my site” jobs, an Application Password is the right tool.
Give each integration its own Application Password, never your real login. If a script is compromised or a service you no longer use gets breached, you revoke that one credential and everything else keeps working. Treat them like the API keys they are: one per job, HTTPS only, and rotated when someone leaves the team.
The Part Nobody Warns You About: It’s Public by Default
Now for the half of this that’s a security topic rather than an automation one. Because the read side is open to anonymous visitors, a few endpoints hand out information you might have assumed was private, and one in particular deserves your attention.
The users endpoint and username enumeration
Visit /wp-json/wp/v2/users on most sites and you’ll get back a list of the accounts that have published posts, including each one’s display name and — critically — its slug, which is very often the exact login username. For an attacker, that’s half of a brute-force attempt handed over for free: they no longer have to guess your usernames, only your passwords. WordPress narrowed this endpoint years ago so it only exposes users who’ve authored public content, but on a typical blog that’s still your author accounts.
The last malware cleanup we did started exactly here. Before anything was compromised, the attacker had pulled the author list from the REST API, matched the admin username to a password from a public breach dump, and walked straight in through wp-login.php. No exploit, no clever trick — just a username the site was giving away and a password the owner had reused somewhere else years earlier.
What to actually do about it
You don’t need to disable the REST API to close the obvious gaps, and disabling it wholesale will break your block editor and any plugin that depends on it. A more surgical approach works better:
- Restrict the
usersendpoint for anonymous requests so it stops broadcasting usernames. Most reputable security plugins (Wordfence, iThemes, and others) offer this as a one-click toggle. - Require authentication for the entire API only if you genuinely run no public integrations — the
rest_authentication_errorsfilter lets a developer force every request to be logged in. This is a real hammer; use it knowingly, because it changes how the editor and plugins behave. - Enforce strong, unique passwords and rate-limit login attempts, since username enumeration only matters if the password is guessable. This is the same hardening you’d do anyway.
The goal isn’t to bolt the API shut. It’s to stop the parts that leak identity information while keeping the parts that make WordPress genuinely programmable.
Extending the API: Your Own Endpoints
The core endpoints cover the built-in content types, but the API is designed to be extended. If you’ve built a custom post type or you want a purpose-built endpoint that returns exactly the data your front-end needs, you register it yourself.
register_rest_route in practice
A developer adds a custom route by hooking register_rest_route() onto the rest_api_init action. You give it a namespace (something like myplugin/v1 so it doesn’t collide with core’s wp/v2), a route pattern, the HTTP methods it answers to, a callback that returns the data, and — this is the part people skip — a permission_callback that decides who’s allowed to call it. Since WordPress 5.5, leaving that permission check out throws a warning, because an endpoint with no gate is an endpoint anyone can hit.
Custom post types get REST support too, but not automatically. When you register the post type, you pass 'show_in_rest' => true, and optionally a custom rest_base for a cleaner URL. Miss that flag and your custom content simply won’t appear in the API — and, as a side effect, it won’t be editable in the block editor either, since the editor reaches your content through this same API.
Our own WordPress tools lean on the REST API for exactly this kind of programmatic work — bulk operations, background jobs, and admin interfaces that talk to your site the same way the block editor does. The full amplifi.plugins suite is MIT licensed and free, and the source is on GitHub if you want to see how custom endpoints and permission callbacks come together in real code.
View on GitHubPractical Tips Before You Ship an Integration
A handful of things will save you a debugging session:
- Discover, don’t hardcode. WordPress advertises its API location in an HTTP
Linkheader and a<link>tag in the page head pointing at/wp-json/. Well-behaved clients read that rather than assuming the path, which matters on sites in a subdirectory. - Every response includes a
_linkssection that points to related resources — an author, a featured image, the comments on a post. Following those links keeps your code from stitching together URLs by hand. - Use the
_fieldsparameter to ask only for the data you need.?_fields=id,title,linktrims a fat response down to three fields, which adds up fast across thousands of records. - Test writes against a staging site first. A misfired POST loop can create a few hundred draft posts faster than you’d think, and cleaning those up is its own afternoon.
Start read-only. Get comfortable pulling data out and seeing the shape of it before you ever send a request that changes something. The API is forgiving to read from and unforgiving to write to carelessly.
Frequently Asked Questions
The REST API is what makes WordPress genuinely programmable — the difference between a site you edit by hand and a platform your tools can build on. If you want a second set of eyes on an integration or a lockdown, that’s the kind of work we do.
Built by amplifi.studio — see also our WordPress security hardening checklist.