OneDrive Indexing API

Captain indexes OneDrive for Business through Microsoft’s Graph API. There is no per-user OAuth flow and no user passwords involved: your Microsoft 365 admin registers an app once, and Captain uses that app’s credentials to read a single file, a folder (recursively), or a user’s whole drive. You name the user on each request.

To index SharePoint sites instead, see the SharePoint Indexing API guide. The endpoints and permissions are separate by design: OneDrive access requires the broader Files.Read.All permission, so a tenant that only wants to expose one SharePoint site never has to grant it.

What your IT admin provides

Three values, all from a one-time App Registration in Microsoft Entra ID:

ValueWhat it is
tenant_idYour Microsoft 365 directory (tenant) ID: a GUID, or the domain like yourco.onmicrosoft.com.
client_idThe Application (client) ID of the App Registration created for Captain.
client_secretA secret generated for that app. Captain uses it per job to mint short-lived tokens; it is never stored.

Plus the email (user principal name) of the OneDrive user to index, e.g. analyst@yourco.com.

One-time setup

Every step below is done by someone with admin rights in your Microsoft 365 tenant. It takes about 10 minutes and is done once. After that, indexing is a plain API call. If you already created an App Registration for SharePoint indexing, reuse it and just add the permission in Step 2.

Step 1: Create an App Registration and client secret

  1. Sign in at entra.microsoft.com (or the Azure portal) and go to Identity → Applications → App registrations.
  2. Click New registration. Name the app (for example captain-indexing), leave every default as is, and click Register.
  3. On the app’s Overview page, copy two values: the Application (client) ID and the Directory (tenant) ID.
  4. Go to Certificates & secrets and click New client secret. Pick an expiry and click Add.
  5. Copy the secret’s Value right away; it is shown only once. This is the client_secret you’ll send to Captain. Keep it secret.
  1. On the app’s API permissions page, click Add a permission and choose Microsoft Graph.
  2. Choose Application permissions, not Delegated. Application permissions are what let Captain run headlessly, with no signed-in user.
  3. Add Files.Read.All. OneDrive requires it; the site-scoped Sites.Selected permission does not cover user OneDrives.
  4. Click Grant admin consent for <your org> on the same page.

Indexing

All three endpoints take the same auth fields plus the user’s email, and differ only in scope.

A user’s whole OneDrive

$curl -X POST "https://api.runcaptain.com/v2/collections/{collection_name}/index/onedrive" \
> -H "Authorization: Bearer $CAPTAIN_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "tenant_id": "00000000-1111-2222-3333-444444444444",
> "client_id": "<application (client) id>",
> "client_secret": "<client secret value>",
> "user_email": "analyst@yourco.com",
> "processing_type": "advanced"
> }'

A folder (recursively)

$curl -X POST "https://api.runcaptain.com/v2/collections/{collection_name}/index/onedrive/directory" \
> -H "Authorization: Bearer $CAPTAIN_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "tenant_id": "00000000-1111-2222-3333-444444444444",
> "client_id": "<application (client) id>",
> "client_secret": "<client secret value>",
> "user_email": "analyst@yourco.com",
> "folder_id": "01ABCDEF...",
> "processing_type": "advanced"
> }'

folder_id is the folder’s Graph driveItem ID. Subfolders are indexed too.

A single file

$curl -X POST "https://api.runcaptain.com/v2/collections/{collection_name}/index/onedrive/file" \
> -H "Authorization: Bearer $CAPTAIN_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "tenant_id": "00000000-1111-2222-3333-444444444444",
> "client_id": "<application (client) id>",
> "client_secret": "<client secret value>",
> "user_email": "analyst@yourco.com",
> "item_id": "01GHIJKL...",
> "processing_type": "advanced"
> }'

item_id is the file’s Graph driveItem ID.

Every response is { "job_id": "...", "status": "pending" }. Poll GET /v2/collections/{name}/jobs/{job_id} for progress, then query the collection with POST /v2/collections/{name}/query.

What gets indexed

  • Documents (PDF, DOCX, XLSX, PPTX, CSV, TXT, images, etc.): OneDrive stores files in their native formats, so everything downloads and processes directly. No export step.
  • Skipped: OneNote notebooks and any file the app can’t access (logged and skipped; the job continues).

Troubleshooting

SymptomCause & fix
AADSTS7000215: Invalid client secretThe secret is wrong or expired. Generate a new one under Certificates & secrets (copy the Value, not the Secret ID).
Consent errors (AADSTS500011, “insufficient privileges”)Admin consent wasn’t granted. On the app’s API permissions page, click Grant admin consent.
403 resolving the user’s driveThe app is missing the Files.Read.All application permission (site-scoped Sites.Selected is not enough for OneDrive).
A folder job finishes with some files failedThose items are restricted beyond the app’s grant. Captain skips them and indexes the rest.

Security notes

  • Grants are read-only. Captain never writes to or deletes from OneDrive.
  • Files.Read.All covers files tenant-wide, so treat the app’s credentials accordingly. If you only need SharePoint content, use the SharePoint guide with Sites.Selected instead and skip this permission entirely.
  • The client secret is a credential: treat it like a password. Revoke it any time under Certificates & secrets, or kill all access by deleting the App Registration.
  • Captain uses the secret only to mint short-lived tokens per job; nothing durable is stored beyond the request.
  • Every read appears in your Microsoft 365 audit logs, attributed to the app.