Wordpress - Why is my custom API endpoint not working?

Here's your problem:

register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(

Specifically the idea that this is possible:

http://my-domain.local/wp-content/plugins/my-project/api/v1/form

This is extremely unusual, and runs counter to what's in the docs, handbook, and tutorials.

REST API endpoints live at the REST API, which lives at the URL returned by rest_url(). They live at yoursite.com/wp-json. An endpoint is not a full URL path, or an independent API disconnected from the main API.

Instead, you need to define your endpoint names in terms of namespaces and endpoints, and visit the correct URL as described in the REST API's discovery mechanisms.

If we use this:

register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(

Then we would expect this:

example.com/wp-json/wp-content/plugins/my-project/api/v1/form/action

That URL is quite long, and has a number of problems:

  • The first parameter is a namespace, not a URL
  • it's not possible to correctly separate out v1 of the API from v2 due to the way that that /form component has been put in the first parameter, not the second. The first parameter is a namespace, the second a route
  • /action is /action, it doesn't get swapped out for GET OR POST

There are also problems with the callback function:

function api_method($data) {
    var_dump($data);

An endpoint needs to return its data, it cannot output it directly as var_dump would, otherwise the returned data is invalid JSON.

Finally, the methods parameter is incorrect:

'methods' => 'GET, POST',

methods doesn't take a comma separated list, no docs suggest doing this either. Instead, use the predefined values provided by the REST API such as WP_REST_Server::READABLE or WP_REST_Server::ALLMETHODS, these are all mentioned in the handbook and the official documentation for register_rest_route.

A better route to register would be:

    register_rest_route( 'my-project/form/v1', '/action', array(

Giving us:

example.com/wp-json/my-project/form/v1/action

Notice how I removed the plugin URL and the redundant /api fragment ( it's obvious it's an API already )


Maybe start with just GET. Your route looks weird as well. Try just:

register_rest_route('my-project/v1', '/action/', [
  'methods'  => WP_REST_Server::READABLE,
  'callback' => 'api_method',
]);

And your callback is not returning a valid response. Let your callback look more like this:

$data = [ 'foo' => 'bar' ];

$response = new WP_REST_Response($data, 200);

// Set headers.
$response->set_headers([ 'Cache-Control' => 'must-revalidate, no-cache, no-store, private' ]);

return $response;

Finally you must combine wp-json, the namespace my-project/v1 and your route action to the URL you now can check for what you get:

 https://my-domain.local/wp-json/my-project/v1/action