SharePoint REST API - Working with Site Collections

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
SPHttpClientinstead — 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.AllandSites.Manage.Allboth 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 DefinitionId — DisplayName 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=0corresponds toFeatureDefinitionScope.Noneand worked in SharePoint Online testing, allowing SharePoint to resolve the feature definition. Microsoft'sFeatureCollection.Adddocumentation states that this parameter should beSiteorFarm, although Microsoft examples elsewhere also useNone. 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.AllandSites.Manage.Allboth 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 1–4 were validated against SharePoint Online; values 5–11 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, andSites.Manage.Allall 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}/permissionsendpoint. 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/sitealways resolves to the site collection — whichever sub-URL you prefix it with, you get the sameSP.Siteobject.Most properties are read-only. Write operations on
SP.SiterequireSites.FullControl.All(app-only) orAllSites.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.DisplayNameis not returned in the default features response; add$select=DefinitionId,DisplayNameto 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) requiresSites.FullControl.All— it returns 403 even withSites.Manage.All.
Happy coding!


