7

If I go to SharePoint 2013 site, click on Admin -> SharePoint, you will see a list of site collections (the link is https://somename-admin.sharepoint.com/_layouts/15/online/SiteCollections.aspx)

What is the REST endpoint URL to get this list of site collections ?

I was trying _api/search/query?querytext='contentclass:sts_site' or _api/search/query?querytext='contentclass:sts_web', but it doesn't give the whole list...

  • However, as I said, "querytext='contentclass:sts_site" doesn't give the whole list of site collections. It returns only those accessible for current user. This is the problem. – user33021 Sep 2 '14 at 13:07
  • how were you able to solve the problem? the answers to this question don't work for me. I only get a subset of Sites. Interestingly, i don't get some of the Site collections for which I am the owner! – Syed Mauze Rehan Aug 1 '15 at 10:54
11

Unfortunately it doesn't seem possible to achieve using neither REST nor JSOM.

So, the workaround, as you correctly mentioned in the question would be to utilize SharePoint Search REST/JSOM and specify contentclass:sts_site to return sites results.

The following REST example demonstrates that:

function searchSites(webUrl,success, failure) {
    var url = webUrl + "/_api/search/query?querytext='contentclass:sts_site'";
    $.ajax({
        url: url,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: function (data) {
            success(data.d.query);
        },
        error: function (data) {
            failure(data);
        }
    });
}


//print sites info
searchSites(_spPageContextInfo.webAbsoluteUrl,
  function(query){
      var resultsCount = query.PrimaryQueryResult.RelevantResults.RowCount;
      for(var i = 0; i < resultsCount;i++) {
          var row = query.PrimaryQueryResult.RelevantResults.Table.Rows.results[i];
          var siteUrl = row.Cells.results[6].Value;
          console.log(JSON.stringify(siteUrl));
      }   
  },
  function(error){
    console.log(JSON.stringify(error));
  }
);

EDIT:

Note this is using the search query to get the list of site collections. as such, newly added site collections will not appear until the search index is recrawled.

Also this is very unfortunate that this requires being an administrator to do this. I created a new feature request Sharepoint user voice idea for not requiring admin rights to list site collections to handle this.

  • This doesn't work for me. I am using Client Credentials Flow to get access token. Is that the issue? URL i hit >>> https://{tenantName}-admin.sharepoint.com/_api/search/query?querytext='.... – Syed Mauze Rehan Jul 24 '15 at 5:14
  • How will this work for Anonymous access? (APP only auth token) – Syed Mauze Rehan Jul 31 '15 at 7:06
  • @Vadim doesn't work for me either. This just returns a bunch of stuff values, but it does not have the 2 site collections i created in the admin UI. Is there literally no way to list site collections in the entire API? that's really unfortunate – Nicholas DiPiazza May 3 '18 at 5:29
  • 1
    To anyone not seeing newly created site collections from this query, it's because the search index hasn't added the site collections yet! you need to either wait or trigger the indexing before this will work! – Nicholas DiPiazza May 4 '18 at 13:54
  • Another problem is many sharepoint on-prem installations don't have the search service enabled: The search request was unable to connect to the Search Service. – Nicholas DiPiazza Aug 1 '18 at 17:40
2

There are no REST endpoints at the farm level in SharePoint, so there is no REST endpoint for all the site collections in your farm/tenancy.

You could get all the subwebs for a specific site (/_api/web?$select=Webs&$expand=Webs), but not all the sites in a tenant/farm.

1

The query that you have used will only return the sites that the user running the code has access to. Looks like you are trying to get the site collections list from O365 tenant. Here is something that you can try using CSOM.

  • 2
    If there is a way to do it not using C# ? I wanted to make a Java application running on a local client machine (not web server) that will be able to get list of site collections. – Alex Aug 29 '14 at 14:14
  • 2
    How do I do that through REST API? Is there a way? – Syed Mauze Rehan Aug 1 '15 at 8:23
1

I know this is an old post but I compare current address to ('https://yourURL/_api/Web/FirstUniqueAncestorSecurableObject').d.Url. If they are equal, I assume I'm talking to the site collection. Please correct me if that is off base but I hope this may help someone in the future.

  • Yes this is off base. the question was how do you obtain a list of site collections in the entire sharepoint tenant. not "is this site a site collection" – Nicholas DiPiazza May 3 '18 at 5:28
1

For SharePoint on-prem

If the search API is enabled for you, use this answer above: https://sharepoint.stackexchange.com/a/113625/60157

Otherwise...

Soap call - sites.asmx - GetContent

One sure-fire way to get the site collections on your system with REST calls is to make call Soap with your REST client.

You have to make 2+ soap calls to get the result.

C# Code Example:

    public XmlDocument getContent(string siteUrl, String contentType, string contentId) {
      List<string> allSites = new List<string>();
      var _url = string.Format("{0}/_vti_bin/SiteData.asmx", siteUrl);
      var _action = "http://schemas.microsoft.com/sharepoint/soap/GetContent";

      XmlDocument soapEnvelopeXml = CreateSoapEnvelope(contentType, contentId);
      HttpWebRequest webRequest = CreateWebRequest(_url, _action);
      InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);

      // begin async call to web request.
      IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);

      // suspend this thread until call is complete. You might want to
      // do something usefull here like update your UI.
      asyncResult.AsyncWaitHandle.WaitOne();

      // get the response from the completed web request.
      XmlDocument contentDatabaseResult = new XmlDocument();
      using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult)) {
        using (StreamReader rd = new StreamReader(webResponse.GetResponseStream())) {
          contentDatabaseResult.Load(rd);
        }
      }
      return contentDatabaseResult;
    }

    public List<string> GetAllSiteCollections() {
      List<String> allSites = new List<string>();
      XmlDocument virtualServerGetContentResult = getContent(rootSite, "VirtualServer", null);
      XmlNode contentResultNode = virtualServerGetContentResult.SelectSingleNode("//*[local-name() = 'GetContentResult']");
      if (contentResultNode == null || contentResultNode.InnerText == null) {
        throw new Exception(string.Format("Cannot list top level sites from {0}", rootSite));
      }
      XmlDocument innerXmlDoc = new XmlDocument();
      innerXmlDoc.LoadXml(contentResultNode.InnerText);
      string contentDatabaseId = innerXmlDoc.SelectSingleNode("//*[local-name() = 'ContentDatabase']").Attributes["ID"].Value;
      if (contentDatabaseId == null) {
        throw new Exception(string.Format("Cannot list top level sites from {0}", rootSite));
      }
      XmlDocument contentDatabaseGetContentResult = getContent(rootSite, "ContentDatabase", contentDatabaseId);
      XmlNode contentDatabaseResultNode = contentDatabaseGetContentResult.SelectSingleNode("//*[local-name() = 'GetContentResult']");
      if (contentDatabaseResultNode == null || contentDatabaseResultNode.InnerText == null) {
        throw new Exception(string.Format("Cannot list top level sites from {0}", rootSite));
      }
      innerXmlDoc = new XmlDocument();
      innerXmlDoc.LoadXml(contentDatabaseResultNode.InnerText);
      XmlNodeList sites = innerXmlDoc.SelectNodes("//*[local-name() = 'Site']");
      foreach (XmlNode siteNode in sites) {
        allSites.Add(siteNode.Attributes["URL"].Value);
      }
      return allSites;
    }

    HttpWebRequest CreateWebRequest(string url, string action) {
      HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
      webRequest.Headers.Add("SOAPAction", action);
      webRequest.ContentType = "text/xml;charset=\"utf-8\"";
      webRequest.Accept = "text/xml";
      webRequest.Method = "POST";
      webRequest.Credentials = credentialCache;
      return webRequest;
    }

    XmlDocument CreateSoapEnvelope(string objectType, string objectId) {
      XmlDocument soapEnvelopeDocument = new XmlDocument();
      string soapEnv = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:soap=""http://schemas.microsoft.com/sharepoint/soap/"">
   <soapenv:Header/>
   <soapenv:Body>
      <soap:GetContent>
         <soap:objectType>{0}</soap:objectType>
{1}
         <soap:retrieveChildItems>true</soap:retrieveChildItems>
         <soap:securityOnly>false</soap:securityOnly>
      </soap:GetContent>
   </soapenv:Body>
</soapenv:Envelope>";
      soapEnvelopeDocument.LoadXml(string.Format(soapEnv, objectType,
                                                 objectId == null ? "" : "<soap:objectId>" + objectId + "</soap:objectId>"));
      return soapEnvelopeDocument;
    }

    void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest) {
      using (Stream stream = webRequest.GetRequestStream()) {
        soapEnvelopeXml.Save(stream);
      }
    }
  }

For SharePoint Online

Rest call - WCF ProcessQuery

First see https://pholpar.wordpress.com/2011/05/25/interpreting-network-traffic-generated-by-the-sharepoint-client-object-model/ for how to make rest calls to the WCF client.svc endpoint. I will not include the process of creating SPOIDCRL cookie and getting the X-Digest value. But you will need these.

curl -X POST \
  https://xxxxxxxxx-admin.sharepoint.com/_vti_bin/client.svc/ProcessQuery \
  -H 'Content-Type: text/xml' \
  -H 'Cookie: SPOIDCRL=77u/PD94b.....TwvU1A+' \
  -H 'X-ClientService-ClientTag: TAPS (16.0.7813.0)' \
  -H 'X-FORMS_BASED_AUTH_ACCEPTED: f' \
  -H 'X-RequestDigest: 0x089E7....905ED2601,03 Aug 2018 05:12:10 -0000' \
  -H 'X-RequestForceAuthentication: true' \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.7918.1217" ApplicationName="Lucidworks Fusion">
   <Actions>
      <ObjectPath Id="4" ObjectPathId="3" />
      <ObjectPath Id="6" ObjectPathId="5" />
      <Query Id="7" ObjectPathId="5">
         <Query SelectAllProperties="true">
            <Properties>
               <Property Name="NextStartIndexFromSharePoint" ScalarProperty="true" />
            </Properties>
         </Query>
         <ChildItemQuery SelectAllProperties="true">
            <Properties />
         </ChildItemQuery>
      </Query>
   </Actions>
   <ObjectPaths>
      <Constructor Id="3" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" />
      <Method Id="5" ParentId="3" Name="GetSitePropertiesFromSharePoint">
         <Parameters>
            <Parameter Type="Null" />
            <Parameter Type="Boolean">false</Parameter>
         </Parameters>
      </Method>
   </ObjectPaths>
</Request>'

The result will contain your site collections.

If you happen to have 1000's site collections in your SharePoint online, you may need to figure out how to change this query to support paging.

0

To get all Site Collection using rest Api when you try to use _api/search/query?querytext='contentclass:sts_site' or _api/search/query?querytext='contentclass:sts_web', but it doesn't give the whole list.

You have to create one Search Result Source and in that give this --

  • Name - Get all Site Collection.
  • Protocol - Local Sharepoint.
  • Type - Sharepoint Search Result.
  • Credentials - Default Authentication.
  • Query - contentclass:sts_site.

And call this result source using rest call-

function searchSiteCollection() {
var url = webUrl + "/_api/search/query?querytext='*'&sourceid='[SOURCEID OF YOUR RESULT SOURCE]'&rowlimit=500";
    $.ajax({
        url: url,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: function (data) {
             var resultsCount = data.d.query.PrimaryQueryResult.RelevantResults.TotalRows;
      for(var i = 0; i < resultsCount;i++) {
          var row = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results[i];
          siteUrl[i] = row.Cells.results[6].Value;

               }
}

User will get all site collections where he is site collection admin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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