I am trying to get the Global Navigation links using a REST call.

https://sitename/sites/test/_api/navigation/menustate?mapprovidername='GlobalNavigationSwitchableProvider'&$filter=IsHidden eq 'false'" 

It seems that the filter is not working correctly, since I get all the items. Also once I call it, I would like to use Handlebars to be able to style it...but my main issue is that I am unable to filter properly.

  • Have you tried 0 or losing the single quotes? I know Yes/No fields are tricky to work with in REST. It may extend to all booleans.
    – wjervis
    Sep 25, 2014 at 14:55
  • Yup. I have tried 0, No, false, with and without quotes.
    – Diana
    Sep 25, 2014 at 15:15
  • What about neq true/1/yes?
    – wjervis
    Sep 25, 2014 at 15:22
  • Tried those as well -.- I'm wondering if it's the way the response is coming back? There are so many sub levels before you get to the actual item you want to display. msdn.microsoft.com/en-us/library/office/…
    – Diana
    Sep 25, 2014 at 15:25
  • Hmm, I tried setting odata to nometadata, which strips out some of the data returned, but the filter still does not work. Are you able to manipulate the returned data after the REST call? That may be the only approach
    – wjervis
    Sep 25, 2014 at 15:43

2 Answers 2


Since you are using jQuery I would suggest to utilize jQuery.grep() to easily filter elements in array.

The following example demonstrates how to request global navigation items and filter REST result:

function getJson(endpointUrl,success,failure)
      type: "GET", 
      headers: { 
            "accept": "application/json;odata=verbose",
            "content-type": "application/json;odata=verbose"
      url: endpointUrl, 
      success: success,
      failure: failure 

function getGlobalNavigation(webUrl,success,failure)
    var navEndpointUrl = webUrl + "/_api/navigation/menustate?mapprovidername='GlobalNavigationSwitchableProvider'";


function printNodes(data){
    var nodes = data.d.MenuState.Nodes.results;

    //exclude hidden nodes
    var filteredNodes = $.grep(nodes, function(node) {
       return !node.IsHidden;

    //print nodes
function logError(error){
  • It's giving only till 2 level, if there are more than 2 level then what about that? Mar 8, 2018 at 7:33
  • Thanks @VadimGremyachev. My requirement was to get all menu items that User is seeing on OOB Pages i.e., exclude hidden subsite links. I was facing issue with Navigation/Menustate REST call because I was using /_api/navigation/menustate?$filter=mapprovidername eq 'GlobalNavigationSwitchableProvider' Please make sure you use /_api/navigation/menustate?**mapprovidername='GlobalNavigationSwitchableProvider'**
    – Dipesh
    May 17, 2018 at 8:48

After chatting with wjervis, since the filter does not work on _api/navigation, we needed to use the javascript to pinpoint the items I wanted to extract:

function globalNav(){ 
                    contentType: "application/json;odata=verbose", 
                    headers: { "accept": "application/json;odata=verbose" }, 
                    success:function (data){ 
                        var newData = {}, 
                        d = {}, 
                        menuState = {}, 
                        nodes = {}, 
                        results = new Array(); 

                        for(var i = 0; i < data.d.MenuState.Nodes.results.length; i++) { 
                            var result = {}; 

                            if(data.d.MenuState.Nodes.results[i].IsHidden == false){ 
                                result.CustomProperties = data.d.MenuState.Nodes.results[i].CustomProperties; 
                                result.FriendlyUrlSegment = data.d.MenuState.Nodes.results[i].FriendlyUrlSegment; 
                                result.IsHidden = data.d.MenuState.Nodes.results[i].IsHidden; 
                                result.Nodes = data.d.MenuState.Nodes.results[i].Nodes; 
                                result.NodeType = data.d.MenuState.Nodes.results[i].NodeType; 
                                result.SimpleUrl = data.d.MenuState.Nodes.results[i].SimpleUrl; 
                                result.Title = data.d.MenuState.Nodes.results[i].Title; 


                        nodes["__metadata"] = data.d.MenuState.Nodes["__metadata"]; 
                        nodes.Results = results; 

                        menuState["__metadata"] = data.d.MenuState["__metadata"]; 
                        menuState.FriendlyUrlPrefix = data.d.MenuState.FriendlyUrlPrefix; 
                        menuState.Nodes = nodes; 
                        menuState.SimpleUrl = data.d.MenuState.SimpleUrl; 
                        menuState.SPSitePrefix = data.d.MenuState.SPSitePrefix; 
                        menuState.SPWebPrefix = data.d.MenuState.SPWebPrefix; 
                        menuState.StartingNodeKey = data.d.MenuState.StartingNodeKey; 
                        menuState.StartingNodeTitle = data.d.MenuState.StartingNodeTitle; 
                        menuState.Version = data.d.MenuState.Version; 

                        d.MenuState = menuState; 

                        newData.d = d; 

                        var source1 = $("#globalNavTemplate").html(); 
                        var template1 = Handlebars.compile(source1); 

  • 1
    A lot can be cut out if you want. I wasn't sure which bit you needed, so copied all the the metadata. I put it in the discussion if you're interested.
    – wjervis
    Sep 25, 2014 at 18:22
  • I used this solution as well but it does not return the custom properties which I defined on term set node. What needs to be done to get the custom properties as well?
    – Tolga
    Dec 10, 2015 at 15:56
  • I am also not able to get Custom Properties in the Rest Result. is there way to get it Oct 16, 2017 at 11:11

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.