The SharePoint REST API is organized entirely around one root path — {site-url}/_api/ — with everything else (lists, files, users, search) hanging off web, site, or a dedicated service beneath it. Here’s a reference list of the endpoints you’ll actually reach for, plus a working example calling one from plain JavaScript.
In this post: Site and web endpoints · List and item endpoints · File and folder endpoints · User and group endpoints · Search endpoints · Term store and workflow endpoints · Shaping responses with OData query options · The $batch endpoint · A working example · When would you actually use this? · Related reading
Site and web endpoints
- Current site collection:
_api/site - Current web:
_api/web - Subsites of the current web:
_api/web/webs
Worth flagging: a bare /sites/{site-id} path (no _api) is a Microsoft Graph convention, not SharePoint’s own REST API — the two are easy to conflate since they cover overlapping data, but they’re different APIs with different root paths and different auth scopes.
List and item endpoints
- Get all lists:
_api/web/lists - Get list items:
_api/web/lists/getByTitle('{list-title}')/items - Add a list item: POST to the same items endpoint above
- Update a list item: MERGE/PATCH to
_api/web/lists/getByTitle('{list-title}')/items({item-id}) - Delete a list item: DELETE to the same item endpoint
File and folder endpoints
- Files in a library:
_api/web/getFolderByServerRelativeUrl('{library-relative-url}')/files - Folders in a library:
_api/web/getFolderByServerRelativeUrl('{library-relative-url}')/folders - Get a file by path:
_api/web/getFileByServerRelativeUrl('{file-relative-url}') - Upload a file: POST to
_api/web/getFolderByServerRelativeUrl('{library-relative-url}')/files/add(overwrite=true,url='{filename}')
User and group endpoints
- Current signed-in user:
_api/web/currentuser - A specific user by ID:
_api/web/getUserById({user-id}) - All site users:
_api/web/siteusers - All site groups:
_api/web/sitegroups
Search endpoints
- Basic search query (GET, simpler queries):
_api/search/query?querytext='{query}' - Content search (POST, more complex queries — refiners, sorting):
_api/search/postquery - Scoped people/department search:
_api/search/query?querytext='Department:{department-name}'
Term store and workflow endpoints
- Taxonomy session (term store access):
_api/SP.Taxonomy.TaxonomySession/getTaxonomySession(termStoreId) - Term sets by name:
_api/SP.Taxonomy.TermStore/getTermSetsByName('{term-store-name}') - Workflows on a list:
_api/web/lists/getByTitle('{list-title}')/workflows - Start a workflow instance:
_api/SP.WorkflowServices.WorkflowInstanceService/StartWorkflowOnListItemBySubscriptionId
Worth noting on this last group: SharePoint 2010 workflows were retired in 2020, and SharePoint 2013 workflows were fully retired on April 2, 2026 — these workflow endpoints are effectively legacy at this point, not something to build a new integration against. Power Automate is the actual current answer for workflow orchestration.
Shaping responses with OData query options
The endpoints above return every field on every item by default — for a list with 40 columns and thousands of rows, that’s a lot of payload nobody asked for. These query string options apply on top of nearly any list/item endpoint above and are worth knowing before reaching for client-side filtering instead:
$select=Title,Status,DueDate— return only the named fields instead of the full item.$filter=Status eq 'Active'— server-side filtering. Supportseq,ne,gt,lt,ge,le, andand/orcombinations.$orderby=DueDate desc— server-side sort.$top=50— caps the page size (max 5,000 per SharePoint’s list view threshold regardless of what’s requested).$expand=Author,AssignedTo— inlines a lookup or person field’s full object instead of just its ID. Needed because$selectalone can’t pull a lookup field’s display value, only its ID.
The gotcha that actually bites people: $filter on a lookup or person column doesn’t work against the field name directly — filtering on AssignedTo needs AssignedTo/Id (or AssignedToId eq {id}), or, for a text comparison, the item’s FieldValuesAsText representation instead. And on a list that’s grown past the 5,000-item list view threshold, an unindexed $filter or $orderby gets throttled outright rather than just running slowly — if a query that worked fine in testing starts failing in production, check whether the list quietly crossed that threshold and whether the filtered column actually has an index.
A bare /sites/{site-id} path is a Microsoft Graph convention, not SharePoint’s own REST API — the two are easy to conflate but have different root paths and auth scopes.
The $batch endpoint
Worth knowing this exists before firing off dozens of individual calls in a loop: _api/$batch accepts a single `multipart/mixed` request bundling multiple operations — GETs, POSTs, MERGEs — into one HTTP round trip, which is a real, significant reduction in overhead compared to individual requests when updating or reading more than a handful of items at once. The trade-off is a genuinely more complex request format (a hand-built multipart body with its own boundary syntax) and a response that isn’t plain JSON — it needs to be split on the response boundary and parsed part by part, not passed straight to `response.json()`.
Worth reaching for a library rather than hand-rolling the multipart format for anything beyond a one-off script — PnPjs’s batching support handles the request construction and response parsing for you, covered in depth in the Related Reading link below.
A working example
Retrieving every item from a list named “Tasks” and rendering the titles into a div:
document.addEventListener("DOMContentLoaded", function() {
var siteUrl = "https://your-sharepoint-site-url";
var listName = "Tasks";
var endpointUrl = siteUrl + "/_api/web/lists/getByTitle('" + listName + "')/items";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
displayListItems(response.value);
} else {
console.error("Failed to retrieve list items. Error: " + xhr.status);
}
}
};
xhr.open("GET", endpointUrl, true);
xhr.setRequestHeader("Accept", "application/json;odata=nometadata");
xhr.send();
});
function displayListItems(items) {
var outputDiv = document.getElementById("output");
outputDiv.innerHTML = "List Items:
";
items.forEach(function(item) {
outputDiv.innerHTML += "" + item.Title + "
";
});
}
Replace the site URL and list name with your own. This example is read-only (a GET), so it doesn’t need the X-RequestDigest header — add it if you extend this to create, update, or delete items.
When would you actually use this?
- You’re integrating SharePoint data into an external application and need to know which endpoint actually covers what you’re after.
- You’re building a script editor web part or classic-page customization where pulling in PnPjs isn’t worth it for a single call.
- You need to know whether something’s a SharePoint REST concept or a Graph API concept before debugging why a URL pattern from one doesn’t work against the other.
Related reading
- How to Send an HTTP Request in SharePoint via JavaScript — the digest/header mechanics behind the GET example shown here, plus the POST case.
- CSOM, JSOM and REST API in SharePoint: Quick Overview — how REST compares to the other two client-side development models.
- SharePoint Data Handling with PnP Batching Queries — the full batching pattern via PnPjs, instead of hand-building the raw multipart request.
That’s the reference list plus a working example. Missing an endpoint you need? Ask in the comments.
App Catalog Authentication Automation Backup Compliance Content Type CSS Flows Google Javascript Limitations List Metadata MFA Microsoft Node NodeJs O365 OneDrive Permissions PnP PnPJS Policy PowerApps Power Automate PowerAutomate PowerPlatform PowerShell React ReactJs Rest API Rest Endpoint Security Send an HTTP Request to SharePoint SharePoint SharePoint List SharePoint Modern SharePoint Online SPFX SPO Sync Tags Teams Termstore Versioning


