Running into a SalesForce REST mapping issue involving multiple wildcards in an url. Is this not supported? Is there anyway to supporting routing for nested resources?

My Setup

I have this REST structure

  • GET /teams/{teamid}/members (list team members)
  • POST /teams/{teamid}/members (create team member)
  • PUT /teams/{teamid}/members/{memberid} (update team member)
  • DELETE /teams/{teamid}/members/{memberid} (delete team member

And I setup the routing as followed:

  • REST_teams_id_members.cls @RestResource(urlMapping='/v1/teams/*/members')
  • REST_teams_id_members_id.cls @RestResource(urlMapping='/v1/teams/*/members/*')


This was working fine, but now I can only get one set of routes to work at any given time. Which ever one was compiled first gets precedence. So both GET /teams/123/members and DELETE/teams/123/members/345` get routed to the same class.

So If I compile REST_teams_id_member.cls (making the other class the first compiled), I get the following routing

  • GET /teams/{teamid}/members -> REST_teams_id_members_id.cls -> 405 Method Not Allowed
  • POST /teams/{teamid}/members -> REST_teams_id_members_id.cls -> 405 Method Not Allowed
  • PUT /teams/{teamid}/members/{memberid} -> REST_teams_id_members_id.cls -> Good
  • DELETE /teams/{teamid}/members/{memberid} -> REST_teams_id_members_id.cls -> Good

If I then compile REST_teams_id_members_id.cls (swapping the order), I get this routing

  • GET /teams/{teamid}/members -> REST_teams_id_members.cls -> Good
  • POST /teams/{teamid}/members -> REST_teams_id_members.cls -> Good
  • PUT /teams/{teamid}/members/{memberid} -> REST_teams_id_members.cls -> 405 Method Not Allowed
  • DELETE /teams/{teamid}/members/{memberid} -> REST_teams_id_members.cls -> 405 Method Not Allowed


I feel like I'm taking crazy pills, it doesn't make any sense how /teams/123/members/345 could possible match @RestResource(UrlMapping='/teams/*/members), and vice versa, I'm at a total loss for how /teams/123/members could route to @RestResource(UrlMapping='teams/*/members/*. They seem wholly distinct!!

We've got an imminent rollout and I'm complete stuck. Praying that SFSE community can help me out.

  • what happens if you try: REST2.CLS @RestResource(urlMapping='/v1/teams/*/members/*/')
    – NSjonas
    Commented Aug 21, 2014 at 19:01
  • just tried it, no dice, /teams/123/members/345 returns 404 with Could not find a match for URL /v1/teams_fix/123123/members/123123 Commented Aug 21, 2014 at 19:06
  • Have you tried putting both routes in the same class, so they compile togather?
    – NSjonas
    Commented Aug 21, 2014 at 19:22
  • each class can only have one route, if needed we're going to use a more generic route /v1/teams/*/members* that will match both, it just means that each function needs to do it's own internal routing management to return 405 for invalid URLs, i.e. GET /v1/teams/123/members/345 would need to be coded to return 405 GET Not Supported Commented Aug 21, 2014 at 19:57
  • using /v1/teams/*/members* produces the following compile error: (API_V1_REST_teams_id_members) Invalid URL mapping in class API_V1_REST_teams_id_members: A wildcard in a URL mapping must be preceded by a forward slash (/). (Line: 2) Commented Aug 21, 2014 at 21:34

3 Answers 3


While it's not clear why that doesn't already work, to get your code out the door, my suggestion is to build your own REST dispatching service. The following pseudo code implementation works as followed:

  1. Register for all REST requests for a particular url (e.g. /teams/*)
  2. Register different controllers (which implement the interface Dispatchable)
  3. In case the url matches the url of your dispatchable class, the method execute is executed

Pseudo Code

@RestResource(urlMapping = '/teams/*')
global class RestDispatcher
    static Map<String, List<Dispatchable>> dispatchables;
        dispatchables = new Map <String, List<Dispatchable>>
            'POST' => new List<Dispatchable>(),
            'GET' => new List<Dispatchable>()

        // register your class here e.g. dispatchables.get('POST').add(new DispatchableClass());

    global interface Dispatchable
        String getURLMapping(); // e.g. /teams/{teamNumber}/members/{memberId}
        void execute(Map<String, String> parameters);

    global static void doGET()

    global static void doPOST()

    private static void execute(String httpMethod)
        RestRequest request = RestContext.request;
        for (Dispatchable d : dispatchables.get(httpMethod))
            if(match(d.getURLMapping, request.requestURI))
                d.execute(getParamters(request.requestURI, d.getURLMapping()));

    global static Map<String, String> getParamters(String requestURI, String dispatcherURI)
        // To-Do: implement an extraction method here.
        return new Map<String, String>();

    global static boolean match(String dispatchURI, String reuquestURI)
        if(true) // To-Do: add a matching algorith here
            return true;
        return false;


Code: https://gist.github.com/cdeckert/6991034790b0a4c9a34c

  • 1
    was afraid of that, the main reason we developed an apex rest webservice (as opposed to building one ourselves and using REST/SOAP API to talk to salesforce) was because it had routing and parameter decoding out of the box. approach totally makes sense, just frustrated we have to manually code a feature that should work already Commented Aug 27, 2014 at 0:32
  • Hi Christian, thank you for your great dispatcher. There is a bug in getParameters(): The parameter name as the map key is set with the curly bracket. E. g. "teamNumber}" instead of "teamNumber". result.put(dispachableURIList.get(i).subString(1, dispachableURIList.get(i).length()), requestURIList.get(i)); should be result.put(dispachableURIList.get(i).subString(1, dispachableURIList.get(i).length()-1), requestURIList.get(i));
    – georg w.
    Commented Nov 11, 2015 at 11:29

As per the above suggestion, you will likely need to manage some of the routing yourself, however we can use regex to make this a simple process.

Below is some example code I have tested in the workbench:

global with sharing class TeamMemberService {

  global static String doGet() {

    Pattern listTeamMemberPattern = Pattern.compile('/teams/(\\d+)/members');

    Matcher match = listTeamMemberPattern.matcher(RestContext.request.requestURI);
    if(match.matches()) {
        return JSON.serializePretty('GET me team ' + match.group(1));
        return JSON.serializePretty('ERROR - incorrect route used');

    return JSON.serializePretty('ERROR - incorrect route used');


  global static String doPut() {

    Pattern updateTeamMemberPattern = Pattern.compile('/teams/(\\d+)/members/(\\d+)');

    Matcher match = updateTeamMemberPattern.matcher(RestContext.request.requestURI);
    if(match.matches()) {
        return JSON.serializePretty('PUT data on member ' + match.group(2) + ' in team ' + match.group(1));
        return JSON.serializePretty('ERROR - incorrect route used');

    return JSON.serializePretty('ERROR - incorrect route used');


As you can see, this will allow you to match what pattern is coming into the methods so you can then run the method you require. Obviously the code needs cleaning a little but this would allow you to do fully nested resources.


The reason Apex REST does not support nested resources/multiple wildcards is due to the matching rules. The rules in the documentation state

The rules for mapping URLs are:

  • An exact match always wins.
  • If no exact match is found, find all the patterns with wildcards that match, and then select the longest (by string length) of those.
  • If no wildcard match is found, an HTTP response status code 404 is returned.

In the case of the defined patterns above, when we add the final wildcard '/*' we redefine the pattern to be matched so that /teams/{teamid}/members does not match our defined pattern of /teams/*/members/*. Adding the extra slash /teams/{teamid}/members/ would possibly resolve this however is not a valid REST route and would still need the validation that GET /teams/123/members/456 was not being called (i.e. with a member number).

The system works as anticipated in the documentation, perhaps an idea should be promoted to make this easier to do though.


I placed some similar code in Episode 13 of the @forcedotcomcast video series which shows how you can use nested resources


I wrote a lightweight framework called Apex-Rest-Route to standardize building RESTful API's in RestResources.

It lets you define and respond to deeply nested routes from a single @RestResource.

The readme shows an example of how you could implement a similar URI structure.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .