SharePoint to Qdrant

Qdrant collections filled one way from SharePoint lists, one point per item with an indexed payload. SPSync writes no vectors here, so semantic search needs your own embedding step.

Book a call

Talk through your use case, see further walkthroughs or demos, and set up a trial in your own environment.

Last updated

One way: SharePoint stays the system of record, and SPSync keeps a read-only copy of your lists current in Qdrant.

Status: Shipped · product: SPSync for Search & Vector Stores

SPSync copies SharePoint list items one way into Qdrant, each item a point whose payload holds its columns, and never writes back to SharePoint. It sends no vectors: every collection is created without a vector configuration, so searching these points by meaning needs an embedding step you run yourself over the payload. Vectors on sync for Qdrant are under consideration, not planned or scheduled; today SPSync generates embeddings only for Postgres with pgvector and Azure AI Search.

What Qdrant does well without a vector is filter on an indexed payload, and that is what SPSync sets up. An application already on Qdrant gets the list content as points it can filter, current on the sync schedule.

Connecting

Give SPSync the instance URL, such as http://localhost:6333 for a local instance or the cluster URL Qdrant Cloud shows, and, if the instance needs one, an API key in an environment variable. Qdrant has a single authentication style, the API key. SPSync keeps a local state file between runs, which needs a stable path.

Collections, point IDs and payload indexes

Every SPSync table becomes a collection. A risk register, grc_risks, with a multi-choice Controls column gives grc_risks, grc_risks__controls and the shared sp_users. Qdrant accepts only an integer or a UUID as a point ID, so SPSync derives a stable UUID from each row’s key, the same ID on every run, which lets an upsert replace the right point.

Each column gets a payload index typed to match: IDs as keyword, text as text, whole numbers as integer, numbers and currency as float, Yes/No as bool and dates as datetime. Currency values are sent as numbers so a range filter matches them. Qdrant will not change an index’s type, so a SharePoint column that changes type sends writes to a new _v2 collection. New columns get a payload index in place.

How do I filter SharePoint data in Qdrant?

Use the condition that suits each index. IDs, including a person column’s {column}_user_id, take an exact match on value. Text, choice values and lookup display names carry a full-text index, so match them with a text condition, which Qdrant splits into words and compares without regard to case. Numbers and currency take a range, and so do dates, written as RFC 3339 timestamps. Because every replicated column has an index, these filters still run on a cluster where strict mode refuses filters on unindexed fields.

With no vector to rank by, the query is a scroll through the matching points. Open risks owned by one person, scored 15 or more and reviewed since January:

POST /collections/grc_risks/points/scroll
{
"filter": {
"must": [
{ "key": "status", "match": { "text": "open" } },
{ "key": "owner_user_id", "match": { "value": "11111111-1111-1111-1111-111111111111" } },
{ "key": "risk_score", "range": { "gte": 15 } },
{ "key": "last_reviewed", "range": { "gte": "2026-01-01T00:00:00Z" } }
]
},
"limit": 50,
"with_payload": true
}

Can Qdrant be your SharePoint vector database?

Yes, with an embedding job of your own, and it should keep its vectors out of SPSync’s collections. On an upsert to an existing point ID the whole point is replaced, keeping only the vectors in that request. SPSync’s upserts carry none, so a vector added to one of its points disappears the next time that row changes, and a reconcile, weekly by default, rewrites every point.

Create a collection of your own with the vector size and distance your model needs, and give each vector the point ID SPSync gave the row. A nearest-neighbour hit then leads straight back to SPSync’s point and its payload. The job can scroll for points whose sp_modified is later than its last run to find what needs embedding again, and remove vectors for points SPSync has deleted.

Deletes and what each run sends

A deleted SharePoint item’s point is removed from the item collection, along with its points in the child collections. Each run sends only rows that changed since the last successful push; a reconcile, weekly by default, sends them all, which repairs points edited or deleted by hand.

Where it fits

Applications already running Qdrant read the collections as a current, filterable copy of list content; see AI agents and tools over SharePoint. Retrieval where SPSync produces the vectors runs on pgvector or Azure AI Search; see RAG on SharePoint lists.

Steps

  1. Pick the SharePoint access model: delegated sign-in, or an app with Sites.Selected on specific sites for unattended runs.
  2. Set the Qdrant URL, and the API key variable if needed.
  3. Choose the lists and run; the first run creates the collections and payload indexes.
  4. Query the collections from your application, and point any embedding job at a collection of its own.

A local instance is fine for development; production use belongs on Qdrant Cloud or a cluster you run. Collection size drives memory and storage as lists grow, and SharePoint permissions are not carried across, so instance access is the boundary.

Desktop, Azure or command line

All three editions run the same engine, write the same tables and use the same licence key, so the choice comes down to who looks after the sync.

Desktop app

For macOS and Windows. Sign in with Microsoft, tick the lists, choose a database and sync from your own machine on the schedule you set. Delegated sign-in needs no admin unless your tenant requires admin consent for apps.

In your Azure

SPSync in your Azure, a managed application for your own subscription, is deployed with you on a call while the Marketplace listing is prepared. Once deployed it is always on, so the sync keeps running with every laptop closed.

Command line

Every replication is a YAML file you can review and commit. Run it from a server, a container or a CI pipeline, and re-run it safely any time.

Frequently asked questions

What does a SharePoint list become in Qdrant?

Collections: one for the list's items, one per multi-value column and one shared users collection. Each row is a point whose payload holds the row's columns.

Does SPSync write embeddings to Qdrant?

No. Collections are created with no vector configuration, so points carry payload only. To search them by meaning, run your own job that embeds the text you choose and keeps the vectors in a collection of yours, keyed on SPSync's point IDs. Embeddings on sync for Qdrant are under consideration, with no plan or date. SPSync generates vectors today for SharePoint to pgvector and SharePoint to Azure AI Search.

Can I filter on payload fields?

Yes. SPSync creates a payload index for every column with a type to match, so filters on a status, an owner ID, a date range or a number work straight away.

Does SPSync need an API key for Qdrant?

Only if the instance requires one, as Qdrant Cloud does. A local or self-hosted instance without an API key needs no credential.

Talk to us about Qdrant

SPSync is licensed per installation and per target family, with Standard Support included. Tell us which targets you need and how many machines, and we will size it with you. See how licensing works.

Set it up

Sign in to SharePoint with the SharePoint connection guide, then follow the Qdrant setup guide to create the database user and open the connection for Qdrant. If the connection test fails, the troubleshooting guide lists the errors people hit and what fixes them.

Script it

Everything you can click, you can script. The CLI, YAML config and automation below reproduce this scenario exactly. See the CLI reference.

spsync auth login --client-id 00000000-0000-0000-0000-000000000000
spsync export-config --output replication.yaml --pipeline-name qdrant --prefix qdrant --destination-kind qdrant --connection-string-env SPSYNC_DB_CONNECTION --dataset-name qdrant --client-id 00000000-0000-0000-0000-000000000000 --site-url https://contoso.sharepoint.com/sites/example --all-lists
spsync doctor replication.yaml
spsync run replication.yaml
pipeline_name: qdrant
prefix: qdrant
auth:
  mode: delegated
  client_id: 00000000-0000-0000-0000-000000000000
  tenant_id: common
destination:
  kind: qdrant
  connection_string_env: SPSYNC_DB_CONNECTION
  dataset_name: qdrant
scopes:
  - site_url: https://contoso.sharepoint.com/sites/example
    mode: entire_site
reconcile_interval_days: 7
create_reporting_views: false

Cron (Qdrant nightly):

# every night at 02:00
0 2 * * * cd /opt/spsync && SPSYNC_DB_CONNECTION="$(cat /etc/spsync/db.env)" uv run spsync run replication.yaml >> /var/log/spsync/run.log 2>&1

GitHub Actions:

# .github/workflows/spsync-run.yml
name: SPSync
on:
  schedule:
    - cron: "0 2 * * *"
  workflow_dispatch: {}
jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v3
      - run: uv sync
      - run: uv run spsync run replication.yaml
        env:
          SPSYNC_DB_CONNECTION: ${{ secrets.SPSYNC_DB_CONNECTION }}
          SPSYNC_LICENCE_KEY: ${{ secrets.SPSYNC_LICENCE_KEY }}

Azure DevOps:

# azure-pipelines.yml
schedules:
  - cron: "0 2 * * *"
    branches: { include: [main] }
    always: true
steps:
  - script: uv sync
  - script: uv run spsync run replication.yaml
    env:
      SPSYNC_DB_CONNECTION: $(SPSYNC_DB_CONNECTION)
      SPSYNC_LICENCE_KEY: $(SPSYNC_LICENCE_KEY)

Windows (PowerShell + Task Scheduler):

# Windows Task Scheduler action (see /docs/cli/automation/)
$env:SPSYNC_DB_CONNECTION = (Get-Content C:\spsync\db.env)
uv run spsync run C:\spsync\replication.yaml
schtasks /Create /SC DAILY /ST 02:00 /TN "SPSync" /TR "powershell -File C:\spsync\run.ps1"

macOS (launchd):

# ~/Library/LaunchAgents/io.spsync.run.plist, then: launchctl load ~/Library/LaunchAgents/io.spsync.run.plist

Secrets (licence key, connection strings) come from the environment, so never write them into the YAML. See scheduling and secrets.

Book a call

Tell us about your lists and where they need to go: we will talk through your use case, show further walkthroughs or demos, and set up a trial in your own environment.