How to catch all leftover routes inside a group?

I have a group of routes, prefixed by /api, that returns JSON results when the user requests something from them.
That means, when a user asks for a non-existing route under /api, I want to return a JSON with a custom error (basically the not found message wrapped in a JSON object). The regular not found page, used for static files for example, still exists.
I want to do something like this:

$app->group(‘/api’, function (Group $group) use ($app) {
$group->get(‘/{resource}/{id:[0-9]+/’, JsonHandler::class . ‘:get’);
//other routes…
//…
$group->any(‘/.*’, JsonHandler::class . ‘notFound’);
});

This throws a error from RegexBasedAbstract , "Static route \"\/api\/.*\" is shadowed by previously defined variable route \"\/api\/([^\/]+)\" for method \"GET\"", which is completely expected, since the first route does shadows the last.
How do I achieve this? I guess I could do it by writing a regex that negates all other regexes but uh, that doesnt seem like a great idea.

See the ‘unlimited optional parameters bit’ of the routing doc: Routing - Slim Framework

Quote:

$app->get('/news[/{params:.*}]', function ($request, $response, array $args) {
   // $params is an array of all the optional segments
   $params = explode('/', $args['params']);
   // ...
   
   return $response;
});

In this example, a URI of /news/2016/03/20 would result in the $params array containing three elements: ['2016', '03', '20'] .

The first route that matches wins. So when you order the routes correctly and then add a generic fallback route at the last position within the group that throws an HttpException it should work.

Ah I see, I have to explicitly match a named parameter like params:.*, just .* doesnt work.
Thanks.