WordPress

WordPress REST API

WordPress REST API is the JSON-over-HTTP interface built into WordPress core, served under /wp-json/. The block editor, mobile apps, and headless front ends all read and write content through it.

How it is measured

Routes are namespaced: /wp-json/wp/v2/posts, /wp-json/wp/v2/users, and your own under a plugin namespace such as /wp-json/shop/v1/. A collection returns up to 100 items per request with per_page, and the headers X-WP-Total and X-WP-TotalPages tell you how many exist. If pretty permalinks are off, the same route works at ?rest_route=/wp/v2/posts.

Authentication is a cookie plus an X-WP-Nonce header for logged-in browser requests, or an application password over HTTPS for scripts. Run curl -s https://example.com/wp-json/ to see every registered namespace.

Worked example

A decoupled Astro front end reads articles from /wp-json/wp/v2/posts?per_page=100&_embed. The build pulls 2,300 posts in 23 requests and takes 4 minutes. The responses carry full content, so each page is about 600 KB.

Adding _fields=id,slug,title,date,excerpt cuts the payload to 90 KB per request and the build to 70 seconds. A security scan also finds that /wp-json/wp/v2/users publicly lists author slugs, which the team hides for non-authors.

How it differs

The WordPress REST API is the current JSON interface, while XML-RPC is the older XML-based one served from xmlrpc.php. REST has per-route permission callbacks and is used by the editor itself. XML-RPC authenticates with a username and password on each call, and REST does not need it for any current core feature.

Common errors

Registering a route without a permission_callback. Leaving the users endpoint open and letting scanners collect login names. Blocking /wp-json/ at the firewall and breaking the block editor. Fetching with no per_page or _fields and downloading megabytes. Treating a 401 from a cached page as an auth bug when the nonce had expired.

In practice

Visit /wp-json/wp/v2/users in a private window and see what it returns. Read every custom route you have registered for a permission_callback. If you build a front end on it, always pass _fields and set up a caching layer in front.

See also

XML-RPC, WordPress

Sources

Count this on a real site.

Watch my website