WordPress /wp-json/wp/v2/posts not working, 404 Error

I was having a problem saving drafts in the editor, and did a look through the network traffic debugger (in Firefox. To bring it up, press F12, and click on Network.) Most of the requests were working, but one was producing a 404 error.

Tapping on the “Save Draft” link resulted in a 404 error to the URL that started with /wp-json/. I wondered if this was a file or folder, but wp-json doesn’t exist.

Fix 1: fix the wp rewriter

wp-json is an endpoint managed by the URL rewriter. A quick fix is usually to “save the permalinks again” (also here.) to regenerate the rewriter’s data, and might also write out to .htaccess as well.

However, resaving permalinks didn’t work for me.

Fix 2: make sure you don’t have a complex reverse proxy config that’s missing a proxy for wp-json.

I’m running this instance of WP behind an Apache reverse proxy. I suspected a configuration error.

If you’re proxying specific URLs, you need to make sure there’s a line like this:

ProxyPass "/wp-json/" "http://backend/wp-json/"

This wasn’t my problem. (I suspected misconfiguration because I’d been using AddHeader to add a header identifying the Docker container that was serving the page. The header wasn’t returned in the 404 error response.)

Fix 3: .htaccess is wrong, or not read at all

WordPress is reliant on .htaccess being correct. So check the htaccess.

I found out my problem was that .htaccess wasn’t being read at all. If the Apache AllowOverride is not changed from its default value of “off”, the .htaccess file is never read.

So change the AllowOverride value (in the VirtualHost config, if that’s what you’re using). I’m using this:

AllowOverride FileInfo AuthConfig Indexes Limit

Restart the server, and it should now read the .htaccess file, and that should rewrite the /wp-json/ url into something WordPress can use.

I think Apache gets to the last rewrite rule:

RewriteRule . /index.php [L]

converts /wp-json/ to index.php/wp-json/, and executes index.php, because AcceptPathInfo is on. /wp-json/ is used by WP.