Skip to content

Set up SPSync: sign in, connect a site, run the first sync

This walks through the CLI, which is the base every other surface (desktop, the Azure managed application) is built on. If someone else has already set up authentication for your tenant, skip to Connect a site.

The desktop app and web UI cover the same ground with a guided first-run permissions wizard instead (Connect screen, once a connection is named): sign in, a check of what is already in place, then one of three ways to finish: grant it yourself, send a short pack to your tenant admin, or continue delegated for now. It re-probes and shows a tick per step so setup never ends on an unclear state; “Check permissions” on that screen re-runs the same check later. See Admin permissions for what each option grants.

Book a call and we set up a trial in your own environment: we talk through your use case, then get you running the desktop app, the CLI, or both, against your own tenant. That session is also where you settle which surface fits your team, so the rest of this page can point straight at commands rather than a generic checklist.

The steps below show the CLI, since its commands are the most direct way to see each stage of the sync explained; the desktop app’s permissions wizard, described above, walks through the same sign-in, connect and destination steps with a visual flow instead of a terminal. The CLI is installed with you on that call, and every command below assumes an installed spsync is on your PATH.

SPSync needs an Entra ID app registration to talk to Microsoft Graph on your behalf. Use the SPSync multi-tenant app (default, fastest to start) or your own app registration (“bring your own app”, useful if your organisation requires it).

Terminal window
spsync auth login --client-id <client-id>

--client-id is required. Use the SPSync multi-tenant app’s client id, which we give you at onboarding, or your own app registration’s (see below). This is a device-code sign-in: the CLI prints a code and a URL, you open the URL in any browser (including on another device) and enter the code. You are asked to consent to Sites.Read.All and your own profile (see Admin permissions for what each scope is used for and when you need a tenant admin instead of your own consent).

To sign in to a specific tenant, or with your own app registration:

Terminal window
spsync auth login --client-id <your-client-id> --tenant <your-tenant-id>

If you sign in with more than one account for the same app and tenant, spsync auth login lists them, and spsync auth status --client-id <client-id> --tenant <tenant-id> shows them again later. Copy the long home_account_id of the account you want into the auth: block of your config as account:, so SPSync never has to guess which one to use. Signing in to a different tenant keeps its own separate sign-in.

Terminal window
spsync discover sites --client-id <client-id>

This lists every site the signed-in identity can see and prints their ids; add --search yoursite to narrow a long list. If the signed-in identity cannot enumerate at all (a Sites.Selected grant, for example), this exits with a clear message pointing you at --site-url <full SharePoint site URL> instead, which looks up one known site directly without needing enumeration permission. Then list what is on it:

Terminal window
spsync discover lists <site-id> --client-id <client-id>

discover lists shows every list and library on the site so you can see what you are about to replicate before committing to it. Run it against more than one site if your replication should merge several sites into one destination schema (each gets its own table prefix, see the schema reference).

Put the destination connection string in an environment variable. SPSync only ever reads the DSN from the environment, never stores it in the config file:

Terminal window
export SPSYNC_DEST_DSN=postgres://user:pass@host:5432/spsync
spsync export-config \
--output replication.yaml \
--site-id <site-id> \
--list-id <list-id> \
--pipeline-name my-replication \
--prefix sp \
--destination-kind postgres \
--connection-string-env SPSYNC_DEST_DSN \
--dataset-name spsync \
--client-id <client-id>

Repeat --list-id for each list to include. Edit replication.yaml afterwards to add or remove lists (lists:), or to change the reconcile cadence (reconcile_interval_days:, default 7, see ADR-005). By default the sync interval (how often your own scheduler (cron, Task Scheduler, launchd, CI; spsync run itself never loops, see CLI automation) should call spsync run) is computed automatically from your Graph permission mode and the tenant’s request budget (5 minutes delegated, 1 minute app-only, 30 seconds absolute floor, see Admin permissions); doctor’s adaptive-interval check reports the current value and why. Pass --sync-interval-seconds <n> to export-config (or set sync_interval_seconds: directly in replication.yaml, a sibling of reconcile_interval_days:) to pin an explicit cadence instead, never below the 30 second floor. Leave it unset to keep the automatic default. Deletes are soft by default (adds sp_deleted_at rather than removing the row). To make a deleted SharePoint item’s row disappear from the destination entirely instead, add a hand-edited deletes: hard key to replication.yaml (a sibling of reconcile_interval_days:); leaving the key out, or setting deletes: soft, keeps today’s default behaviour. deletes: hard is refused at config-load time for destinations that rely on the soft-deleted row still being present to know what to remove from their own index (elasticsearch, opensearch, lancedb, qdrant, weaviate, dataverse, azure-ai-search) and for pgvector configured with pgvector_embedding_target: side_table.

Add --create-reporting-views to the export-config command above (or create_reporting_views: true directly in replication.yaml) to also get a v_{prefix}_{list} view per list after each run, for querying with a BI tool. See Reporting views for which destinations support this and what the view contains. In the desktop app the same setting is the “Create reporting views” toggle on this same Destination step, and it can be turned on or off later from an existing replication’s Runs screen.

Terminal window
spsync run replication.yaml

The first run does a full load; every run after that pulls only what changed (delta). To force a full re-check against SharePoint on demand (as a QA check that the two sides match, or to catch back up after your own server or a Microsoft 365 outage), without waiting for the reconcile schedule (weekly by default):

Terminal window
spsync reconcile replication.yaml

Reconcile also runs automatically on that schedule, weekly by default (see reconcile_interval_days above). The interval is configurable per replication, so you can run it more often as a QA check against silent drift or to catch back up quickly after an outage or a missed run.

Terminal window
spsync doctor replication.yaml

doctor checks the things that usually go wrong first, in order: the ODBC driver (SQL Server destinations only), Graph token validity, site permission grants, the current adaptive sync interval, and destination connectivity. Start here if anything looks off. See Troubleshooting for what each doctor finding means and how to fix it.

Book a call at any point during or after the trial (see What the trial does to your data) and we issue the licence key below. A licence is activated on the machine that runs SPSync (D21): each activated machine is a seat, and a seat can be deactivated and moved to another machine.

Terminal window
spsync licence activate SPSYNC1....

This stores the resulting activation token in this OS’s keychain (or a 0600 file when no keychain is available), prints a one-line confirmation naming this machine, and a summary of what the licence entitles: which destinations, how many machine seats it covers, the support tier, and when the term ends. --json returns the same fields structurally. If activation does not succeed (an invalid key, or every seat on it already taken), the command exits non-zero and prints why; fix that and run it again. spsync licence status shows this machine’s own activation alongside the trial/ licence state: hostname, when it was last activated, and how many days until the next background refresh. spsync licence fingerprint prints the SHA-256 fingerprint this machine activates with (never the raw hardware identifiers it is built from), useful for support or an offline, machine-locked key. Moving to a new machine: run spsync licence deactivate on the old one first to free the seat, or activate straight away if support already freed it for you.

  • Admin permissions if auth login or discover failed with a permission error.
  • Schema reference to know what tables and columns to expect at the destination before you point a report at them.