Sources

SharePoint

Connect a Microsoft 365 account and feed a document base from a site's document library. Read-only permissions, incremental syncs, and your folder structure preserved.

Connect a Microsoft 365 account and feed a document base from a SharePoint site's document library, or from one folder inside it. Access runs through Microsoft Graph with read-only permissions, so nothing Engram holds can change anything in your tenant.

What you need

Someone who can consent for the Microsoft 365 tenant, and the site or folder you want to read. The permissions requested are read-only:

PermissionWhy it is asked for
Sites.Read.AllFind the sites and their document libraries
Files.Read.AllList folders and read the files inside them
User.ReadIdentify the account that connected
offline_accessKeep syncing after the browser session ends

There is no write permission anywhere in that list. Tokens are encrypted at rest, and disconnecting in the app deletes them.

1. Connect and pick a library

Connecting is a browser flow, so it happens in the app: on the Documents step of a document base's setup, choose Connect SharePoint. Consent once and the connection belongs to your workspace.

SharePoint has no picker of its own, so you browse inside the app instead and the ids it hands back are opaque values you pass straight through:

Id shapeWhat it points at
no idThe tenant's sites, so you can choose one
site:<siteId>That site's default document library, at its root
item:<driveId>:<itemId>One folder inside a library

Treat them as blobs. Pass back exactly what you received rather than building one by hand.

2. Import once, or register a source

A one-off import pulls a folder now and stops:

curl -X POST https://api.engramdynamics.org/v1/corpora/c_7a1f.../import \
  -H "Authorization: Bearer <your key>" \
  -H "Content-Type: application/json" \
  -d '{
        "connection_id": "cc_71f4...",
        "folder_id": "item:b!Ab3...:01ABCXYZ",
        "folder_name": "Policies"
      }' 

A source keeps it current:

curl -X POST https://api.engramdynamics.org/v1/corpora/c_7a1f.../sources \
  -H "Authorization: Bearer <your key>" \
  -H "Content-Type: application/json" \
  -d '{
        "kind": "sharepoint",
        "connection_id": "cc_71f4...",
        "site_id": "contoso.sharepoint.com,8f3c...,2d91...",
        "folder_id": "item:b!Ab3...:01ABCXYZ",
        "mode": "additive",
        "schedule_minutes": 360
      }' 

site_id is only needed when you are pointing at a site's default library; folder_id alone is enough for a folder inside one. As with Drive there is no template to apply: the connection is the credential, so the source comes back ready and the first sync is what proves the folder is readable.

source = requests.post(
    f"{BASE}/corpora/{base_id}/sources",
    headers=HEADERS,
    json={
        "kind": "sharepoint",
        "connection_id": connection_id,
        "folder_id": folder_id,
        "mode": "mirror",
        "schedule_minutes": 360,
    },
    timeout=30,
).json()

run = requests.post(
    f"{BASE}/corpora/{base_id}/sources/{source['id']}/sync", headers=HEADERS, timeout=30
).json()
print(run["id"], run["state"])

How updates are picked up

After the first sync we hold Microsoft Graph's delta cursor for that library or folder and ask only for what changed, so a large library with a handful of edits fetches a handful of files. has_delta_token on the source says the cursor is held. Removals come back as removals, so a source in mirror mode takes the document out of the base and one in additive mode leaves it.

Folder structure is preserved as document paths, so a file at Policies/EU/refunds.docx in the library is at the same path in the base.

Limits and troubleshooting

Next

Turning a library or folder into a standing source from the Sources section of the Documents tab, on a schedule you pick: Keeping a folder in sync. What we can read out of each file, and how a file becomes a document: What counts as a document.