Skip to main content

Command Palette

Search for a command to run...

SharePoint REST API - Working with Site Collections

Updated
18 min readView as Markdown
SharePoint REST API - Working with Site Collections
R

I'm a .NET/M365 developer, trainer, author, MVP & MCT Alumni

SP.Site represents a SharePoint site collection — the top-level container with its own security boundary, storage quota, and administration settings. It is accessible at /_api/site from any site within the collection. This post covers reading and updating site collection properties, managing activated features, and accessing the site recycle bin.


Introduction

SharePoint distinguishes between a site collection (SP.Site, accessible at /_api/site) and a site within that collection (SP.Web, accessible at /_api/web). Every site collection has a single SP.Site instance. Regardless of which URL you use as the prefix, /_api/site always resolves to the site collection containing that URL:

https://contoso.sharepoint.com/sites/marketing/_api/site
https://contoso.sharepoint.com/sites/marketing/team/_api/site

Both URLs above refer to the same SP.Site object — the marketing site collection. The second URL targets a subsite, but /_api/site still walks up to the site collection root. This contrasts with /_api/web, which resolves to the specific site at the URL prefix. See the Working with Sites post for SP.Web.

SP.Site exposes a narrower surface than SP.Web. Most of the entity's properties are read-only; write operations are limited to a small set of site-level settings, and they require Full Control-tier permissions — among the highest minimum permission requirements in this series.

Authentication note: The raw HTTP examples use a SharePoint Bearer token. With delegated authentication, the token represents a signed-in user and the operation must be permitted by both the delegated scope and that user's SharePoint permissions. With application (app-only) authentication, the token represents the Entra application and SharePoint evaluates its application permissions. For Entra app-only access to SharePoint REST, Microsoft documents certificate-based authentication; client-secret app-only tokens are not accepted by SharePoint REST. The legacy SharePoint ACS app-only model was retired on November 27, 2023 and stopped working on April 2, 2026. In SPFx, use SPHttpClient instead — it supplies the current user's SharePoint authentication context and manages request digests for write operations.


Before You Start: Headers and JSON Format

SharePoint's REST API defaults to OData v3 in most cases when the OData-Version header is not supplied. To use OData v4 — which is what SPFx's SPHttpClient uses by default — include the OData-Version: 4.0 header:

OData-Version: 4.0
Accept: application/json;odata.metadata=none
Content-Type: application/json;odata.metadata=none  (JSON-body requests only)

For a full explanation of OData versions, JSON format options, and how these headers interact, see Understanding SharePoint REST JSON Formats.


The SP.Site Entity

A plain GET /_api/site returns the core properties of the site collection. The properties you'll use most often:

Property Type Description
Id Guid The site collection's GUID. Stable across URL changes.
Url string The full absolute URL of the site collection, e.g. https://contoso.sharepoint.com/sites/marketing.
ServerRelativeUrl string The server-relative URL, e.g. /sites/marketing.
PrimaryUri string The canonical URL of the site collection. Typically the same as Url.
GeoLocation string The multi-geo data center code for the site collection, e.g. NAM, EUR.
ReadOnly bool Whether the site collection is in a read-only state.
WriteLocked bool Whether the site collection is write-locked.
LockIssue string The reason for the lock if the site collection is locked. null when unlocked.
CompatibilityLevel int Always 15 in SharePoint Online. A holdover from on-premises version tracking.
MaxItemsPerThrottledOperation int The list view threshold. Always 5000 in SharePoint Online.
CurrentChangeToken SP.ChangeToken The current change token for this site collection. Used with GetChanges for incremental change detection.
ShareByEmailEnabled bool Whether sharing by email invitation is enabled.
ShareByLinkEnabled bool Whether sharing by anonymous link is enabled.
DisableCompanyWideSharingLinks bool Whether company-wide sharing links are disabled.
DisableAppViews bool Whether app views are disabled.
DisableFlows bool Whether Power Automate flows are disabled for the site collection.
AllowDesigner bool Whether SharePoint Designer access is allowed.
AllowMasterPageEditing bool Whether master page editing is allowed.
GroupId Guid The GUID of the connected Microsoft 365 group. All zeros if the site collection is not group-connected. This is a preview property but is returned in the default response.
HubSiteId Guid The GUID of the hub site this site collection is associated with. All zeros if not a hub site member. Preview property.
IsHubSite bool Whether this site collection is registered as a hub site. Preview property.
Classification string The site's SharePoint classification value, if configured. Site classification is distinct from Microsoft Purview sensitivity labels. Preview property.
SensitivityLabelId string The GUID of the sensitivity label. Preview property.

Navigation properties (accessible via $expand or as sub-resource paths):

Property Type Description
Owner SP.User The site collection owner. In Microsoft 365 Group-connected sites this is the Owners group (PrincipalType=4), not an individual user.
RootWeb SP.Web The top-level web of the site collection. Equivalent to /_api/web when the request is made against the site collection's root URL.
Features SP.Feature collection Features activated at the site collection scope.
RecycleBin SP.RecycleBinItem collection Items in the site collection recycle bin. Requires Sites.FullControl.All / AllSites.FullControl.
SecondaryContact SP.User The secondary site collection administrator.

The Usage property (type SP.UsageInfo) is not returned in the default response — it requires an explicit $select. See Get Storage and Usage Statistics below.


API Operations

Get the Site Collection

Returns the SP.Site entity with all default properties:

GET https://contoso.sharepoint.com/sites/marketing/_api/site
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK (abridged)

{
  "CompatibilityLevel": 15,
  "CurrentChangeToken": {
    "StringValue": "1;1;a1b2c3d4-e5f6-7890-abcd-ef1234567890;639222683731500000;918667384"
  },
  "DisableAppViews": false,
  "DisableCompanyWideSharingLinks": false,
  "DisableFlows": false,
  "GeoLocation": "NAM",
  "GroupId": "a3b4c5d6-e7f8-9012-34ab-cdef12345678",
  "HubSiteId": "00000000-0000-0000-0000-000000000000",
  "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "IsHubSite": false,
  "LockIssue": null,
  "MaxItemsPerThrottledOperation": 5000,
  "PrimaryUri": "https://contoso.sharepoint.com/sites/marketing",
  "ReadOnly": false,
  "ServerRelativeUrl": "/sites/marketing",
  "ShareByEmailEnabled": true,
  "ShareByLinkEnabled": false,
  "Url": "https://contoso.sharepoint.com/sites/marketing",
  "WriteLocked": false
}

Several properties in the schema are legacy SharePoint on-premises fields with no practical meaning in SharePoint Online. CompatibilityLevel is always 15. UpgradeReminderDate and UpgradeScheduledDate return placeholder dates from 1899 and 1753 respectively. You can safely ignore these.

Preview properties — GroupId, HubSiteId, IsHubSite, Classification, SensitivityLabelId, and others — are returned in the default response even without an explicit $select. Their values reflect the current site configuration.

Delegated Permission: Requires AllSites.Read for a user with modern SharePoint Visitor Group permission or SharePoint's built-in Read permission or greater.

Application Permission: Requires the Sites.Read.All permission scope or higher.


Get Selected Properties

Use $select to return only specific properties:

GET https://contoso.sharepoint.com/sites/marketing/_api/site?$select=Id,Url,GroupId,IsHubSite,GeoLocation
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK

{
  "GeoLocation": "NAM",
  "GroupId": "a3b4c5d6-e7f8-9012-34ab-cdef12345678",
  "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "IsHubSite": false,
  "Url": "https://contoso.sharepoint.com/sites/marketing"
}

Delegated Permission: Requires AllSites.Read for a user with modern SharePoint Visitor Group permission or SharePoint's built-in Read permission or greater.

Application Permission: Requires the Sites.Read.All permission scope or higher.


Get Storage and Usage Statistics

The Usage property is not included in the default response. Request it explicitly with $select:

GET https://contoso.sharepoint.com/sites/marketing/_api/site?$select=Usage
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK

{
  "Usage": {
    "Bandwidth": 0,
    "DiscussionStorage": 0,
    "Hits": 0,
    "Storage": 1909785,
    "StoragePercentageUsed": 6.947757356101646e-8,
    "Visits": 0
  }
}

Storage is in bytes. StoragePercentageUsed is the fraction of the site collection's storage quota currently in use. The Bandwidth, Hits, and Visits values above are from a near-empty test site; active sites may return non-zero values for these fields.

Delegated Permission: Requires AllSites.Manage for a user with modern SharePoint Owner Group permission or SharePoint's built-in Full Control permission level. Member-level users return 403 regardless of delegated scope (validated against SharePoint Online).

Application Permission: Requires the Sites.Read.All permission scope or higher.


Expand Navigation Properties

Navigation properties are not included in the default response. Use $expand to include them inline. Combine with $select to control which properties of the expanded entity are returned:

GET https://contoso.sharepoint.com/sites/marketing/_api/site?$expand=Owner&$select=Id,Owner
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK

{
  "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "Owner": {
    "Email": "marketing@contoso.onmicrosoft.com",
    "Id": 6,
    "IsHiddenInUI": true,
    "LoginName": "c:0o.c|federateddirectoryclaimprovider|a3b4c5d6-e7f8-9012-34ab-cdef12345678_o",
    "PrincipalType": 4,
    "Title": "Marketing Owners",
    "UserPrincipalName": null,
    "UserId": null
  }
}

For Microsoft 365 Group-connected sites, Owner is the Owners security group (PrincipalType: 4), not an individual user. UserId and UserPrincipalName are null in this case. For non-group-connected sites, Owner is an individual SP.User with the usual user properties.

Expanding RootWeb returns the full SP.Web entity for the site collection's top-level web. When called from the site collection's root URL this is the same data as /_api/web, but if called from a subsite URL, RootWeb still refers to the site collection root while /_api/web refers to the subsite. This can be useful when you need both site collection and site properties in a single request, but it returns the complete web entity and may be more data than you need. Use $select on the expanded property to narrow it:

GET https://contoso.sharepoint.com/sites/marketing/_api/site?$expand=RootWeb&$select=Id,RootWeb/Id,RootWeb/Title,RootWeb/Url
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Delegated Permission: Requires AllSites.Read for a user with modern SharePoint Visitor Group permission or SharePoint's built-in Read permission or greater.

Application Permission: Requires the Sites.Read.All permission scope or higher.


Update Site Collection Properties

Send a MERGE request with only the properties to change. Omitted properties are unchanged:

POST https://contoso.sharepoint.com/sites/marketing/_api/site
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Content-Type: application/json;odata.metadata=none
Authorization: Bearer <token>
X-HTTP-Method: MERGE
If-Match: *

{
  "DisableFlows": true
}

Response — 204 No Content

Delegated Permission: Requires AllSites.FullControl for a user with modern SharePoint Owner Group permission or SharePoint's built-in Full Control permission level.

Application Permission: Requires the Sites.FullControl.All permission scope. Sites.ReadWrite.All and Sites.Manage.All both return 403 (validated against SharePoint Online).

If-Match: * is required. Omitting it returns 400 Bad Request.

Writable properties include DisableFlows, DisableAppViews, DisableCompanyWideSharingLinks, ShareByEmailEnabled, AllowDesigner, and AllowMasterPageEditing. Most other properties on SP.Site are read-only.


Working with Features

A SharePoint feature is a packaged unit of functionality that can be activated or deactivated on a site collection or site. Site collection-scoped features are managed through /_api/site/features; site-scoped features are managed through /_api/web/features (covered in the Working with Sites post).

The two operations — activate and deactivate — both require Sites.FullControl.All / AllSites.FullControl.

List Active Features

Returns the collection of currently activated site collection features:

GET https://contoso.sharepoint.com/sites/marketing/_api/site/features?$select=DefinitionId,DisplayName
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK

{
  "value": [
    {
      "DefinitionId": "00bfea71-1c5e-4a24-b310-ba51c3eb7a57",
      "DisplayName": "BasicWebParts"
    },
    {
      "DefinitionId": "ca7bd552-10b1-4563-85b9-5ed1d39c962a",
      "DisplayName": "Fields"
    }
  ]
}

Without $select, the default response returns only DefinitionIdDisplayName is not included. The DisplayName values are internal feature names, not the friendly names shown in the SharePoint administration UI. Each activated feature is identified by its GUID; you must know the GUID in advance to activate or deactivate a specific feature.

Delegated Permission: Requires AllSites.Read for a user with modern SharePoint Visitor Group permission or SharePoint's built-in Read permission or greater.

Application Permission: Requires the Sites.Read.All permission scope or higher.


Activate a Feature

Call add on the features collection, passing the feature GUID, a force flag, and a featdefScope value. Set force to false for a standard activation and pass featdefScope=0 (FeatureDefinitionScope.None, which was accepted by SharePoint Online in testing):

POST https://contoso.sharepoint.com/sites/marketing/_api/site/features/add(featureId=guid'a1b2c3d4-e5f6-7890-abcd-ef1234567890',force=false,featdefScope=0)
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>
Content-Length: 0

Response — 200 OK

{
  "DefinitionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

The response returns the DefinitionId of the activated feature. Feature activation in SharePoint Online can involve background provisioning — lists, content types, or event receivers may be created asynchronously after the API call returns. A GET confirming the feature appears in the active features collection establishes that SharePoint has registered the activation, but not necessarily that every asynchronous provisioning side effect has completed. If you intend to deactivate the feature immediately after activating it, wait for that GET confirmation before calling remove.

Note: featdefScope=0 corresponds to FeatureDefinitionScope.None and worked in SharePoint Online testing, allowing SharePoint to resolve the feature definition. Microsoft's FeatureCollection.Add documentation states that this parameter should be Site or Farm, although Microsoft examples elsewhere also use None. The behavior shown here is based on live validation.

Delegated Permission: Requires AllSites.FullControl for a user with modern SharePoint Owner Group permission or SharePoint's built-in Full Control permission level.

Application Permission: Requires the Sites.FullControl.All permission scope. Sites.ReadWrite.All and Sites.Manage.All both return 403 (validated against SharePoint Online).


Deactivate a Feature

Call remove on the features collection, passing the feature GUID and a force flag:

POST https://contoso.sharepoint.com/sites/marketing/_api/site/features/remove(featureId=guid'a1b2c3d4-e5f6-7890-abcd-ef1234567890',force=false)
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>
Content-Length: 0

Response — 204 No Content

Set force to true only if a standard deactivation returns an error — forcing it to proceed despite errors, which may leave orphaned content. Some features cannot be deactivated via REST regardless of permission level — for example, the Document ID Service returns 403 even with Sites.FullControl.All (validated). These features must be deactivated through the SharePoint administration UI or PowerShell. If remove returns 403 with FullControl scope, this may be the cause, though the status code alone does not establish it.

Delegated Permission: Requires AllSites.FullControl for a user with modern SharePoint Owner Group permission or SharePoint's built-in Full Control permission level.

Application Permission: Requires the Sites.FullControl.All permission scope (validated against SharePoint Online).


Check Whether a Feature Is Active

Use getbyid to retrieve a specific feature by GUID:

GET https://contoso.sharepoint.com/sites/marketing/_api/site/features/getbyid(guid'a1b2c3d4-e5f6-7890-abcd-ef1234567890')
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK (feature is active)

{
  "DefinitionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Response — 200 OK (feature is not active)

{
  "@odata.null": true
}

When the feature is not active, SharePoint returns 200 OK with {"@odata.null":true} — the OData v4 representation of a null single entity. It does not return 404 Not Found. Check for the presence of DefinitionId in the response (or the absence of @odata.null) rather than relying on HTTP status to determine whether a feature is active.

Delegated Permission: Requires AllSites.Read for a user with modern SharePoint Visitor Group permission or SharePoint's built-in Read permission or greater.

Application Permission: Requires the Sites.Read.All permission scope or higher.


Working with the Site Recycle Bin

/_api/site/recyclebin returns the items in the site collection recycle bin:

GET https://contoso.sharepoint.com/sites/marketing/_api/site/recyclebin
OData-Version: 4.0
Accept: application/json;odata.metadata=none
Authorization: Bearer <token>

Response — 200 OK (illustrative — the test site recycle bin was empty during live validation; the shape below reflects the entity schema)

{
  "value": [
    {
      "AuthorEmail": "alex@contoso.onmicrosoft.com",
      "AuthorName": "Alex Wilber",
      "DeletedByEmail": "alex@contoso.onmicrosoft.com",
      "DeletedByName": "Alex Wilber",
      "DeletedDate": "2026-08-12T14:00:00Z",
      "DirName": "sites/marketing/Documents",
      "Id": "b1c2d3e4-f5a6-7890-bcde-f12345678901",
      "ItemState": 1,
      "ItemType": 1,
      "LeafName": "report.docx",
      "Size": "24576",
      "Title": "report.docx"
    }
  ]
}

ItemState indicates which stage of the recycle bin the item is in: 1 = first-stage (end-user recycle bin), 2 = second-stage (site collection recycle bin). Size is returned as a JSON string, not a number (validated against SharePoint Online).

ItemType indicates what kind of object was recycled:

ItemType Meaning
0 None
1 File
2 File version
3 List item
4 List or library
5 Folder
6 Folder containing lists
7 Attachment
8 List item version
9 Cascade parent
10 Web (subsite)
11 App

Values 14 were validated against SharePoint Online; values 511 are from the CSOM RecycleBinItemType documentation.

Two additional properties — DirNamePath and LeafNamePath — are also present in the response as { "DecodedUrl": "..." } objects rather than plain strings. DirNamePath.DecodedUrl corresponds to DirName; LeafNamePath.DecodedUrl corresponds to LeafName.

Delegated Permission: Requires AllSites.FullControl for a user with modern SharePoint Owner Group permission or SharePoint's built-in Full Control permission level.

Application Permission: Requires the Sites.FullControl.All permission scope. Sites.Read.All, Sites.ReadWrite.All, and Sites.Manage.All all return 403 (validated against SharePoint Online).


Quick Reference

Headers

Header Value When required
OData-Version 4.0 All requests
Accept application/json;odata.metadata=none All requests
Content-Type application/json;odata.metadata=none JSON body requests
X-HTTP-Method MERGE Update requests
If-Match * Update requests
Content-Length 0 Feature activate/deactivate (bodyless POST)
Authorization Bearer <token> All requests

Status Codes

Code Meaning When returned
200 OK Success with response body GET requests; feature activate; getbyid (active or inactive — see body)
204 No Content Success with no response body MERGE (update); feature deactivate
400 Bad Request Missing required header MERGE without If-Match
403 Forbidden Insufficient permission MERGE or feature activate/deactivate with less than Sites.FullControl.All; recycle bin with less than Sites.FullControl.All; Usage with less than Owner-level user permission
411 Length Required Missing Content-Length Feature activate or deactivate without Content-Length: 0

Permission Requirements

The table below lists the minimum delegated and application permission scopes. Delegated scopes apply when calling with a Bearer token on behalf of a signed-in user; the minimum user permission level column shows what access the signed-in user needs when using classic SharePoint permissions and modern SharePoint group permissions. Application permissions apply when calling without a signed-in user context (app-only). The application permissions in this table are permissions on the Office 365 SharePoint Online API, not the same-named Microsoft Graph permissions. An SPFx solution using SPHttpClient does not require you to grant these delegated or application scopes to the solution; it calls SharePoint as the current user, whose SharePoint permissions govern the operation. Delegated and application scope requirements in this table were live-validated against SharePoint Online. Basic read operations were tested with a Member-level delegated user (AllSites.Read scope) and app-only (Sites.Read.All); elevated operations (Usage, recycle bin, write) were tested with an Owner-level delegated user and app-only FullControl tokens. The classic SharePoint permission-level minima in the table come from Microsoft's documentation.

Operation Minimum delegated permission Minimum user permission level Minimum tenant-wide application permission
Get site collection properties AllSites.Read Classic: Read; Group: Visitor Sites.Read.All
Get selected properties AllSites.Read Classic: Read; Group: Visitor Sites.Read.All
Get usage statistics AllSites.Manage Classic: Full Control; Group: Owner Sites.Read.All
Expand navigation properties AllSites.Read Classic: Read; Group: Visitor Sites.Read.All
Update site collection properties AllSites.FullControl Classic: Full Control; Group: Owner Sites.FullControl.All
List active features AllSites.Read Classic: Read; Group: Visitor Sites.Read.All
Check feature active AllSites.Read Classic: Read; Group: Visitor Sites.Read.All
Activate a feature AllSites.FullControl Classic: Full Control; Group: Owner Sites.FullControl.All
Deactivate a feature AllSites.FullControl Classic: Full Control; Group: Owner Sites.FullControl.All
Get recycle bin items AllSites.FullControl Classic: Full Control; Group: Owner Sites.FullControl.All

Note: The application permissions above are tenant-wide grants. For least-privilege access to specific site collections, the SharePoint Sites.Selected permission can be used for both application and delegated tokens. Sites.Selected consent alone does not grant access to any site — an explicit Read, Write, Manage, or FullControl role must be assigned on each target site collection via the Microsoft Graph /sites/{id}/permissions endpoint. For delegated tokens, access is the intersection of the signed-in user's own permissions and the role granted to the application for that site.


Wrapping Up

SP.Site exposes the site collection container and its administrative configuration. Key takeaways:

  • /_api/site always resolves to the site collection — whichever sub-URL you prefix it with, you get the same SP.Site object.

  • Most properties are read-only. Write operations on SP.Site require Sites.FullControl.All (app-only) or AllSites.FullControl (delegated) — the highest permission level in the series.

  • Preview properties — GroupId, IsHubSite, Classification, and others — are returned in the default response without needing $select.

  • Usage (storage/bandwidth statistics) is not in the default response; request it with $select=Usage.

  • DisplayName is not returned in the default features response; add $select=DefinitionId,DisplayName to get it.

  • Feature activation may involve asynchronous background provisioning. Confirm a feature is listed in the active features collection before attempting to deactivate it.

  • Some features cannot be deactivated via REST regardless of permission level and require the SharePoint administration UI or PowerShell instead.

  • The site recycle bin (/_api/site/recyclebin) requires Sites.FullControl.All — it returns 403 even with Sites.Manage.All.

Happy coding!