Skip to main content
Browse all guides
All guides

Integrating with SharePoint

Connect Action Flows to SharePoint Online document libraries through an OpenAPI app that calls Microsoft Graph. With this setup, Actions can read files from SharePoint folders into a run, let an Agent browse and search folders, and write result files back to SharePoint.

What You Will Build

  1. A Microsoft Entra app registration with application permissions for SharePoint, so Studio can call Microsoft Graph without a signed-in user.
  2. An OpenAPI app in Studio with Service Principal credentials pointing at that registration.
  3. An input that downloads a SharePoint file into the run, where OCR, LLM, Agent, and other steps can use it.
  4. Tools that list folders, search for files, resolve site IDs, and upload generated files back to SharePoint.

All SharePoint calls go through Microsoft Graph (https://graph.microsoft.com), so the same pattern works for any Graph drive endpoint. Every input and tool definition below is ready-to-import JSON: open the app's Inputs or Tools tab, select Import JSON, and paste the snippet — Studio creates the resource with its name, description, configuration, and parameter schema in one go. Importing a name that already exists prompts you to overwrite or rename.

Step 1 — Register a Microsoft Entra Application

Studio authenticates to Microsoft Graph with app-only (client credentials) authentication. Create the app registration in the Microsoft Entra admin center of the Microsoft 365 tenant that hosts the SharePoint sites:

  1. Go to Microsoft Entra ID > App registrations > New registration.
  2. Enter a name, for example Dooap Studio - SharePoint. No redirect URI is needed.
  3. Register the application and note the Application (client) ID and Directory (tenant) ID from the Overview page.
  4. Go to Certificates & secrets > New client secret, create a secret, and copy the secret value immediately — it is shown only once.

Choose the Permission Model

Under API permissions > Add a permission > Microsoft Graph > Application permissions, add one of:

  • Sites.Selected (recommended) — the app has no access to any site until an administrator grants it access to specific site collections. Use this to limit the integration to only the sites your Actions need.
  • Sites.Read.All — read files in all site collections in the tenant.
  • Sites.ReadWrite.All — read and write files in all site collections in the tenant.

Then select Grant admin consent for the tenant. A Global Administrator or Privileged Role Administrator must perform this step.

Grant Site Access for Sites.Selected

With Sites.Selected, consent alone grants nothing — an administrator must grant the app a role on each target site. Grant the role with a Microsoft Graph call (the caller needs Sites.FullControl.All or an equivalent admin context):

POST https://graph.microsoft.com/v1.0/sites/{siteId}/permissions
Content-Type: application/json

{
  "roles": ["write"],
  "grantedToIdentities": [
    {
      "application": {
        "id": "<application-client-id>",
        "displayName": "Dooap Studio - SharePoint"
      }
    }
  ]
}

Use the role read for read-only integrations and write when Actions should also upload files. The same grant can be made with PnP PowerShell:

Grant-PnPEntraIDAppSitePermission `
  -AppId "<application-client-id>" `
  -DisplayName "Dooap Studio - SharePoint" `
  -Site "https://contoso.sharepoint.com/sites/Finance" `
  -Permissions Write

If different Actions need different access levels, register two Entra applications — one granted read, one granted write — and create a separate OpenAPI app in Studio for each. Assign the read-only app's resources to Actions that only consume files.

Step 2 — Create the OpenAPI App in Studio

  1. Go to Tenant Admin > Apps.
  2. Select New, choose OpenAPI, and continue.
  3. Enter a clear name, such as SharePoint - Finance, and save the app.
  4. Open the app and select Configure Credentials.
  5. Set Authentication Type to Service Principal and enter:
    • Client ID — the Application (client) ID from Step 1.
    • Client Secret — the secret value from Step 1.
    • Azure Tenant ID — the Directory (tenant) ID from Step 1.
    • Scopehttps://graph.microsoft.com/.default. The dialog labels the field optional, but Microsoft Graph rejects tokens requested without it, so always set it for this integration. Studio appends /.default automatically if you enter only https://graph.microsoft.com.
  6. Use Test Connection to verify token acquisition, then save.

Studio now acquires and caches Microsoft Graph tokens for this app. In the definitions below, the token is injected with the {{APP_BEARER_TOKEN}} placeholder and masked in run logs.

Step 3 — Resolve the Site ID

Microsoft Graph identifies a SharePoint site by a composite ID in the form hostname,siteCollectionId,webId, for example:

contoso.sharepoint.com,00000000-0000-0000-0000-000000000000,11111111-1111-1111-1111-111111111111

Add a small helper tool to the app so you can resolve site IDs from inside Studio. On the Tools tab, select Import JSON and paste:

{
  "name": "Get_SharePoint_Site",
  "description": "Resolves a SharePoint site by hostname and site name. Returns the site id needed by the other SharePoint tools.",
  "configTemplate": {
    "BaseUrl": "https://graph.microsoft.com",
    "Method": "GET",
    "Path": "/v1.0/sites/{hostname}:/sites/{siteName}",
    "Headers": {
      "Authorization": "Bearer {{APP_BEARER_TOKEN}}"
    },
    "DefaultParameterValues": {
      "hostname": "contoso.sharepoint.com"
    }
  },
  "toolCallSchema": {
    "type": "object",
    "properties": {
      "hostname": { "type": "string", "description": "SharePoint hostname, e.g. contoso.sharepoint.com. Leave empty to use the default." },
      "siteName": { "type": "string", "description": "Site name as it appears in the site URL after /sites/, e.g. Finance" }
    },
    "required": ["siteName"],
    "additionalProperties": false,
    "x-parameter-locations": {
      "hostname": "path",
      "siteName": "path"
    }
  },
  "type": "OpenAPI",
  "appName": null,
  "tags": null,
  "responseSamples": null
}

After importing, edit the tool and replace the default hostname with your own SharePoint hostname. Run the tool once from a Tool Call Step (or ask an Agent step to call it) and copy the id field from the response. Paste that site ID into the DefaultParameterValues of the inputs and tools below so Action builders never have to type it.

Step 4 — Read Files from SharePoint

Define the file download as an input. OpenAPI inputs turn binary responses (PDFs, images, Office documents) into run files automatically, so the downloaded file becomes available to OCR steps, Agent steps, and file-accepting tools in the same run. On the Inputs tab, select Import JSON and paste (inputs carry no toolCallSchema — their parameter schema lives inside the configuration template as ParametersSchema):

{
  "name": "Read_SharePoint_File",
  "description": "Downloads a file from the site's default document library into the run.",
  "configTemplate": {
    "BaseUrl": "https://graph.microsoft.com",
    "Method": "GET",
    "Path": "/v1.0/sites/{siteId}/drive/root:/{filePath}:/content",
    "Headers": {
      "Authorization": "Bearer {{APP_BEARER_TOKEN}}"
    },
    "ParametersSchema": {
      "type": "object",
      "properties": {
        "siteId": { "type": "string", "description": "Microsoft Graph site id. Leave empty to use the configured default." },
        "filePath": { "type": "string", "description": "File path relative to the default document library root, e.g. Invoices/2026/inv-001.pdf" }
      },
      "required": ["filePath"],
      "additionalProperties": false,
      "x-parameter-locations": {
        "siteId": "path",
        "filePath": "path"
      }
    },
    "DefaultParameterValues": {
      "siteId": "<paste the site id from Step 3>"
    }
  },
  "type": "OpenAPI",
  "appName": null,
  "tags": null,
  "responseSamples": null
}

The path targets the site's default document library (Documents). filePath is relative to the library root, so Invoices/2026/inv-001.pdf reads .../Documents/Invoices/2026/inv-001.pdf.

To use it, open a step, add the Read_SharePoint_File input, and fill in filePath — as a fixed value, or as a reference such as {{input.triggerPayload.filePath}} when the path arrives with the trigger. At runtime the file is downloaded before the step body runs and joins the run's files, where later steps can reference it — for example with "latest" or a file selector in a tool parameter.

Step 5 — List and Search Folders

Define browsing operations as tools so an Agent can decide which folders to inspect. On the Tools tab, select Import JSON and paste:

{
  "name": "List_SharePoint_Folder",
  "description": "Lists the files and subfolders in a SharePoint folder. Use before reading files to discover exact file paths.",
  "configTemplate": {
    "BaseUrl": "https://graph.microsoft.com",
    "Method": "GET",
    "Path": "/v1.0/sites/{siteId}/drive/root:/{folderPath}:/children",
    "Headers": {
      "Authorization": "Bearer {{APP_BEARER_TOKEN}}"
    },
    "Query": {
      "$select": "id,name,size,folder,file,lastModifiedDateTime,webUrl",
      "$top": "200"
    },
    "DefaultParameterValues": {
      "siteId": "<paste the site id from Step 3>"
    }
  },
  "toolCallSchema": {
    "type": "object",
    "properties": {
      "siteId": { "type": "string", "description": "Microsoft Graph site id. Leave empty to use the configured default." },
      "folderPath": { "type": "string", "description": "Folder path relative to the document library root, e.g. Invoices/2026" }
    },
    "required": ["folderPath"],
    "additionalProperties": false,
    "x-parameter-locations": {
      "siteId": "path",
      "folderPath": "path"
    }
  },
  "type": "OpenAPI",
  "appName": null,
  "tags": null,
  "responseSamples": null
}

Optionally add a Search_SharePoint_Files tool for name and content search across the library. Note that Microsoft Graph's drive search endpoint does not work with app-only Sites.Selected permission — every search call fails with a generalException error even though listing and reading work. Add this tool only when the app registration has Sites.Read.All or broader; with Sites.Selected, rely on List_SharePoint_Folder instead:

{
  "name": "Search_SharePoint_Files",
  "description": "Searches the site's document library by file name and content. Returns matching files with their paths. Use List_SharePoint_Folder when you already know the folder.",
  "configTemplate": {
    "BaseUrl": "https://graph.microsoft.com",
    "Method": "GET",
    "Path": "/v1.0/sites/{siteId}/drive/root/search(q='{query}')",
    "Headers": {
      "Authorization": "Bearer {{APP_BEARER_TOKEN}}"
    },
    "DefaultParameterValues": {
      "siteId": "<paste the site id from Step 3>"
    }
  },
  "toolCallSchema": {
    "type": "object",
    "properties": {
      "siteId": { "type": "string", "description": "Microsoft Graph site id. Leave empty to use the configured default." },
      "query": { "type": "string", "description": "Search text matched against file names and content" }
    },
    "required": ["query"],
    "additionalProperties": false,
    "x-parameter-locations": {
      "siteId": "path",
      "query": "path"
    }
  },
  "type": "OpenAPI",
  "appName": null,
  "tags": null,
  "responseSamples": null
}

Step 6 — Write Files to SharePoint

Create an upload tool that writes generated text content — reports, CSV exports, JSON results, Markdown summaries — into a SharePoint folder. On the Tools tab, select Import JSON and paste:

{
  "name": "Upload_SharePoint_Text_File",
  "description": "Creates or overwrites a file in a SharePoint folder from text content. The file type is determined by the fileName extension (e.g. .csv, .json, .md, .txt, .html).",
  "configTemplate": {
    "BaseUrl": "https://graph.microsoft.com",
    "Method": "PUT",
    "Path": "/v1.0/sites/{siteId}/drive/root:/{folderPath}/{fileName}:/content",
    "Headers": {
      "Authorization": "Bearer {{APP_BEARER_TOKEN}}"
    },
    "RequestContentType": "text/plain",
    "BodyMode": "raw",
    "DefaultParameterValues": {
      "siteId": "<paste the site id from Step 3>"
    }
  },
  "toolCallSchema": {
    "type": "object",
    "properties": {
      "siteId": { "type": "string", "description": "Microsoft Graph site id. Leave empty to use the configured default." },
      "folderPath": { "type": "string", "description": "Target folder path relative to the document library root, e.g. Reports/2026" },
      "fileName": { "type": "string", "description": "File name including extension, e.g. summary.md" },
      "body": { "type": "string", "description": "The full text content of the file" }
    },
    "required": ["folderPath", "fileName", "body"],
    "additionalProperties": false,
    "x-parameter-locations": {
      "siteId": "path",
      "folderPath": "path",
      "fileName": "path",
      "body": "body"
    }
  },
  "type": "OpenAPI",
  "appName": null,
  "tags": null,
  "responseSamples": null
}

Because BodyMode is raw and the single body parameter is named body, its value is sent as the request body unchanged. A PUT to :/content creates the file, or overwrites it when a file with the same name already exists. The target folder must exist — create folders with the Create_SharePoint_Folder variation below if needed.

Using SharePoint in an Action Flow

Process a known file. Add the Read_SharePoint_File input to an OCR or LLM step and set filePath. The file is in the run before the step executes; an OCR step can read it directly, and downstream tools can reference it with "latest".

Let an Agent work a folder. Assign List_SharePoint_Folder, Search_SharePoint_Files, and Upload_SharePoint_Text_File to an Agent step with instructions such as:

List the folder Invoices/Incoming. For each PDF found, summarize its name, size, and last modified date. Write the summary as a Markdown table to Reports/incoming-summary.md.

The Agent calls the tools as needed, using the parameter descriptions to fill in values, and the configured siteId default fills in automatically.

Deterministic upload from a Tool Call step. When the write is fixed, use a Tool Call Step instead of an Agent. Example parameters that store a CSV produced by an earlier Code Step:

{
  "folderPath": "Exports/2026",
  "fileName": "approved-invoices.csv",
  "body": "{{Generate_CSV.csvContent}}"
}

More Graph Operations

The same app can host any other Microsoft Graph drive operation as an additional tool. Useful variations, all with the same Authorization header and siteId default:

  • Delete a fileDELETE /v1.0/sites/{siteId}/drive/root:/{filePath}
  • Create a folderPOST /v1.0/sites/{siteId}/drive/root:/{parentPath}:/children with a JSON body parameter such as {"name": "2026", "folder": {}, "@microsoft.graph.conflictBehavior": "fail"}
  • File metadata without contentGET /v1.0/sites/{siteId}/drive/root:/{filePath} returns name, size, timestamps, and webUrl for linking.
  • Other document libraries — the .../drive/... paths above target the site's default library. List all libraries with GET /v1.0/sites/{siteId}/drives, then address a specific library with /v1.0/drives/{driveId}/root:/{path} in place of /v1.0/sites/{siteId}/drive/root:/{path}.

Common Patterns

  • Invoice archive: an email- or webhook-triggered Action processes a document, then uploads the extraction result as JSON to a SharePoint archive folder with Upload_SharePoint_Text_File.
  • Scheduled folder digest: a scheduled Action lets an Agent list a folder, compare against a Data Table of already-processed names, process new files through Read_SharePoint_File, and record them.
  • Report drop: any Action Flow that produces text output (CSV, Markdown, HTML) publishes it to a SharePoint folder the business team already uses — no new UI needed.
  • Read-only + write split: separate read and write Entra applications and Studio apps, so most Actions carry read-only SharePoint access and only publishing Actions can write.

Things to Know

  • Downloads belong on inputs, not tools. OpenAPI inputs store binary responses as run files; OpenAPI tools read responses as text, so a tool calling the :/content download endpoint returns unusable text for binary files. If an Agent must pick the file dynamically, let it choose the path with list/search tools in one step and feed the chosen path into a Read_SharePoint_File input reference on the next step.
  • Uploads are text-only. The raw body mode sends the body parameter as UTF-8 text. Binary run files (PDFs, images) cannot be uploaded to SharePoint through an OpenAPI raw body. Graph's simple upload also caps at 250 MB; large-file upload sessions are not supported through OpenAPI apps.
  • Path values are inserted into the URL as-is. Spaces in file and folder names are handled, but names containing # or % must be percent-encoded in the parameter value (%23, %25).
  • Client secrets expire. Track the secret's expiry date in Entra and update it in the app's Configure Credentials dialog before it lapses.
  • Site IDs are stable. The composite hostname,guid,guid ID never changes for a site, so baking it into DefaultParameterValues is safe. Use separate OpenAPI apps (or explicit siteId values) when one tenant works against several sites.
  • Store the client secret only in the app credentials dialog, never in Action prompts, step parameters, or configuration templates.

Troubleshooting

  • Every Graph call fails with generalException / spException (a nested error object with "code": "generalException" and inner code spException) — the app registration authenticates, but its token carries no application permissions: either no Microsoft Graph application permission was ever added, or Grant admin consent was never given (Step 1). Note that Test Connection can still succeed in this state — it verifies token acquisition, not permissions. Fix it in the Entra admin center: add Sites.Selected (or Sites.Read.All / Sites.ReadWrite.All) under API permissions > Microsoft Graph > Application permissions and select Grant admin consent. With Sites.Selected, also complete the per-site grant.
  • Only Search_SharePoint_Files fails with generalException while list/read/upload work — Graph's drive search endpoint does not support app-only Sites.Selected. Use List_SharePoint_Folder instead, or grant the app Sites.Read.All if search is required (Step 5).
  • 403 Forbidden or Access denied from an otherwise working appSites.Selected grants nothing by itself; the target site collection is missing its explicit permission grant (Step 1).
  • 401 invalid_client when acquiring a token — the client secret is expired or wrong. Create a new secret in Entra and update it in Configure Credentials.
  • itemNotFound — the site name, file path, or folder path does not exist under the addressed document library. Remember paths are relative to the site's default Documents library; use List_SharePoint_Folder to discover exact paths.