Overview
This skill helps AI agents integrate with SharePoint Online for document management, list operations, site automation, and custom development. It covers Microsoft Graph API for sites/lists/files, SharePoint REST API for advanced operations, search, permissions management, and SharePoint Framework (SPFx) for custom web parts.
Instructions
Step 1: Authentication
import { ClientSecretCredential } from '@azure/identity';
import { Client } from '@microsoft/microsoft-graph-client';
import { TokenCredentialAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials';
// Permissions: Sites.ReadWrite.All, Files.ReadWrite.All, Lists.ReadWrite.All
const credential = new ClientSecretCredential(
process.env.AZURE_TENANT_ID, process.env.AZURE_CLIENT_ID, process.env.AZURE_CLIENT_SECRET
);
const authProvider = new TokenCredentialAuthenticationProvider(credential, {
scopes: ['https://graph.microsoft.com/.default'],
});
const graphClient = Client.initWithMiddleware({ authProvider });
Step 2: Sites & Document Libraries
// Get site by URL
const site = await graphClient.api('/sites/contoso.sharepoint.com:/sites/engineering').get();
// Get document libraries (drives)
const drives = await graphClient.api(`/sites/${site.id}/drives`).get();
const driveId = drives.value[0].id;
// List folder contents
const items = await graphClient.api(`/drives/${driveId}/root/children`)
.select('id,name,size,lastModifiedDateTime,webUrl').get();
// Create folder
await graphClient.api(`/drives/${driveId}/root/children`).post({
name: 'New Project', folder: {}, '@microsoft.graph.conflictBehavior': 'rename',
});
Step 3: File Operations
// Upload small file (< 4MB)
await graphClient.api(`/drives/${driveId}/root:/Reports/monthly-report.pdf:/content`).putStream(fileContent);
// Upload large file (> 4MB) — resumable upload session
const session = await graphClient
.api(`/drives/${driveId}/root:/LargeFiles/dataset.csv:/createUploadSession`)
.post({ item: { '@microsoft.graph.conflictBehavior': 'replace', name: 'dataset.csv' } });
// Upload in 10MB chunks with Content-Range headers to session.uploadUrl
// Download, copy, move, delete
await graphClient.api(`/drives/${driveId}/items/${itemId}/content`).getStream();
await graphClient.api(`/drives/${driveId}/items/${itemId}/copy`).post({ parentReference: { driveId, path: '/root:/Archive' }, name: 'backup.pdf' });
await graphClient.api(`/drives/${driveId}/items/${itemId}`).patch({ parentReference: { id: targetFolderId } });
await graphClient.api(`/drives/${driveId}/items/${itemId}`).delete();
// Create sharing link
await graphClient.api(`/drives/${driveId}/items/${itemId}/createLink`).post({
type: 'view', scope: 'organization',
});
Step 4: SharePoint Lists
// Create a list
await graphClient.api(`/sites/${siteId}/lists`).post({
displayName: 'Project Tracker',
columns: [
{ name: 'ProjectName', text: {} },
{ name: 'Status', choice: { choices: ['Not Started', 'In Progress', 'Complete'] } },
{ name: 'DueDate', dateTime: {} },
{ name: 'Budget', currency: {} },
],
list: { template: 'genericList' },
});
// Get items with filter
const items = await graphClient.api(`/sites/${siteId}/lists/${listId}/items`)
.expand('fields($select=ProjectName,Status,DueDate)')
.filter("fields/Status eq 'In Progress'")
.orderby('fields/DueDate').get();
// Create / Update / Delete items
await graphClient.api(`/sites/${siteId}/lists/${listId}/items`).post({
fields: { ProjectName: 'Website Redesign', Status: 'In Progress', DueDate: '2026-04-01', Budget: 25000 },
});
await graphClient.api(`/sites/${siteId}/lists/${listId}/items/${itemId}/fields`).patch({ Status: 'Complete' });
await graphClient.api(`/sites/${siteId}/lists/${listId}/items/${itemId}`).delete();
// Bulk create (batch request)
const batchBody = {
requests: items.map((item, i) => ({
id: `${i}`, method: 'POST', url: `/sites/${siteId}/lists/${listId}/items`,
body: { fields: item }, headers: { 'Content-Type': 'application/json' },
})),
};
await graphClient.api('/$batch').post(batchBody);
Step 5: Search
// Search across all SharePoint content
const results = await graphClient.api('/search/query').post({
requests: [{
entityTypes: ['driveItem', 'listItem', 'site'],
query: { queryString: 'quarterly report 2026' },
from: 0, size: 25,
}],
});
// Search with filters (file type, author, site)
await graphClient.api('/search/query').post({
requests: [{ entityTypes: ['driveItem'], query: { queryString: 'filetype:pdf AND author:"John Smith"' } }],
});
Step 6: Webhooks
// Subscribe to document library changes
const subscription = await graphClient.api('/subscriptions').post({
changeType: 'created,updated,deleted',
notificationUrl: 'https://your-app.com/api/sharepoint-webhook',
resource: `/drives/${driveId}/root`,
expirationDateTime: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000).toISOString(),
clientState: 'your-secret-token',
});
// Renew before expiry (max 3 days for SharePoint)
await graphClient.api(`/subscriptions/${subscription.id}`).patch({
expirationDateTime: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000).toISOString(),
});
Examples
Example 1: Automate monthly report uploads to a SharePoint document library
User prompt: "Write a script that uploads a generated PDF report to our SharePoint Engineering site's Reports folder each month, creating the folder if it doesn't exist."
The agent will:
- Authenticate with Microsoft Graph using the Azure AD app credentials
- Resolve the site ID via
/sites/contoso.sharepoint.com:/sites/engineering - Get the default drive ID from
/sites/{siteId}/drives - Check if the monthly folder exists under Reports; if not, create it with
POST /drives/{driveId}/root/children - Upload the PDF using the small-file API (
PUT /drives/{driveId}/root:/Reports/2026-02/monthly-report.pdf:/content) or a resumable upload session if the file exceeds 4MB
Example 2: Build a project tracker with SharePoint lists
User prompt: "Create a SharePoint list called 'Project Tracker' with columns for project name, status, due date, and budget. Then add three sample projects and filter for in-progress items."
The agent will:
- Create the list via
POST /sites/{siteId}/listswith text, choice, dateTime, and currency columns - Add three items using
POST /sites/{siteId}/lists/{listId}/itemswith realistic data (e.g., "Website Redesign" at $25,000 In Progress) - Query filtered results with
.filter("fields/Status eq 'In Progress'")and.orderby('fields/DueDate') - Return the filtered items showing only in-progress projects sorted by due date
Guidelines
- Use Graph API over SharePoint REST API when possible — cleaner, better documented, same auth as Teams
- Batch requests for bulk operations (
/$batch) — max 20 requests per batch - Large file uploads (> 4MB) must use upload sessions — direct PUT has size limits
- SharePoint webhooks expire after 3 days max — set up a renewal job
- Use
$selectand$expandto reduce payload size — don't fetch everything - Delta queries (
/drives/{id}/root/delta) for syncing — tracks changes since last check - Document libraries are just "drives" in Graph API — same endpoints as OneDrive
- Column names in list APIs are internal names (no spaces) — use
fieldsobject for values - Rate limits: 10,000 API calls per minute per tenant — use batching for high-volume operations
- Search API indexes content inside documents (Word, PDF, etc.) — not just filenames