I have the following code in my plugin, which during development has been working perfectly fine (called within rest_api_init).

// ?rest_route=bridge/v1/test-data/process/bbe_examples
        'bridge/v1', '/(?P<participant>[a-zA-Z0-9-_]+)/process/(?P<section>[a-zA-Z0-9-_]+)', [
            'methods'  => 'GET',
            'callback' => [ $this->api, 'process' ],

<My URL>/index.php?rest_route=/bridge/v1/test-data/process/bbe_sortables&replace&_wpnonce=<thenonce> Works fine, regardless of whether they're enabled.

<My URL>/wp-json/bridge/v1/test-data/process/bbe_sortables&replace&_wpnonce=<thenonce> returns 404 rest_no_route when called.

These are both currently called by some generated buttons, which are generated using rest_url( "bridge/v1/test-data/process/" ) (the section is appended to the string during display).

I'm not entirely sure what's going wrong here. I assumed I had to generate the full URL with rest_url(), but when directly called via the browser or API system the response is the same.

  • The problem is with the bbe_sortables&replace in the pretty URL. If you change it to bbe_sortables?replace, that should work.
    – Sally CJ
    Commented Oct 29, 2018 at 13:59
  • Oh damn, I didn't think of that! Can you write that as a reply so I can mark that as resolved?
    – soup-bowl
    Commented Oct 29, 2018 at 14:38
  • I'm also well-aware that this almost completely violates the REST approach. I'm gradually integrating them, but this was - as it always is - a short term quick fix solution. Obviously it bit me, but there you go.
    – soup-bowl
    Commented Oct 29, 2018 at 15:36
  • Not sure what you mean by "violates the REST approach"? But I already posted an answer for the original question.
    – Sally CJ
    Commented Oct 30, 2018 at 1:20
  • Went on a ramble. This is a paginated request, and the page identifer was also an argument like this. I changed it to test-data/process/page/2 to make it more clearer. Some of my older API practices were coming in.
    – soup-bowl
    Commented Oct 30, 2018 at 9:01

1 Answer 1


The problem is with the bbe_sortables&replace in the permalink:

<My URL>/wp-json/bridge/v1/test-data/process/bbe_sortables&replace&_wpnonce=<thenonce>

which results in an invalid route, where the supposedly query string is seen as part of the route:


(the valid route for that URL is /bridge/v1/test-data/process/bbe_sortables)

and eventually the REST API throws the rest_no_route error.

To fix the problem, use add_query_arg() when generating the URL, to append the proper query string; e.g. with rest_url():

$url = add_query_arg( array(
    'replace'  => 'VALUE',
    '_wpnonce' => 'VALUE',
), rest_url( 'bridge/v1/test-data/process/bbe_sortables/' ) );

/* Sample $url output:

a) Permalinks enabled

b) Permalinks *not* enabled

Or if you're certain that permalinks are always enabled on the site, then this would be fine:

rest_url( 'bridge/v1/test-data/process/bbe_sortables/?replace=VALUE&_wpnonce=VALUE' )
  • 1
    Thank you for this! I'll use your approach instead, as I'm currently just string-appending the arguments. This method is much more ideal.
    – soup-bowl
    Commented Oct 30, 2018 at 8:58
  • You're welcome, and yes, unless absolutely not necessary, I'd always use add_query_arg() when appending query strings to a WordPress URL which could be "pretty" or "ugly" (index.php-based). :)
    – Sally CJ
    Commented Oct 30, 2018 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.