---
title: SMB Connector
path: connectors/smb-connector
status: published
---

Keep a ScaiDrive share in step with an SMB (Windows / Samba) file share. The connector logs in with a service account, walks the SMB tree, mirrors the structure into ScaiDrive, and schedules recurring syncs. Changes on either side propagate.

**Base path:** `/api/v1/smb-connectors/`

## Why

Organizations with existing SMB shares want their content available through modern sync and sharing without migrating it. Install the connector, point it at an SMB share, and that content becomes accessible through the ScaiDrive web client, desktop client, and API.

The connector is not an SMB frontend for ScaiDrive — clients don't connect to ScaiDrive over SMB. The connector bridges SMB content *into* ScaiDrive's native sync model.

## Sync directions

| Mode | Behavior |
|------|----------|
| `bidirectional` | Changes on either side replicate. Conflicts resolved per configured strategy |
| `smb_to_scaidrive` | SMB is authoritative. Changes in ScaiDrive are overwritten on next sync |
| `scaidrive_to_smb` | ScaiDrive is authoritative. SMB changes are overwritten |

Use `bidirectional` for active collaboration. Use the unidirectional modes when one side is the system of record (e.g., a legacy scanner that writes to SMB) and the other is the view layer.

## Creating a connector

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/smb-connectors \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Finance Fileserver",
    "description": "Legacy Windows share — finance department",
    "server_host": "fs01.corp.example.com",
    "server_port": 445,
    "share_name": "Finance",
    "base_path": "2026",
    "domain": "CORP",
    "username": "scaidrive-svc",
    "password": "<secret>",
    "target_share_id": "shr_01J3H",
    "target_path": "/From Fileserver",
    "sync_direction": "bidirectional",
    "sync_permissions": true,
    "include_patterns": {"extensions": ["pdf", "docx", "xlsx"]},
    "exclude_patterns": {"patterns": ["~$*", ".DS_Store", "Thumbs.db"]},
    "conflict_resolution": "LAST_WRITER_WINS",
    "sync_interval_minutes": 15
  }'
```

```python
resp = httpx.post(
    f"{url}/api/v1/smb-connectors",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "name": "Finance Fileserver",
        "server_host": "fs01.corp.example.com",
        "server_port": 445,
        "share_name": "Finance",
        "base_path": "2026",
        "domain": "CORP",
        "username": "scaidrive-svc",
        "password": os.environ["SMB_PASS"],
        "target_share_id": "shr_01J3H",
        "target_path": "/From Fileserver",
        "sync_direction": "bidirectional",
        "sync_interval_minutes": 15,
    },
)
connector = resp.json()
```

```typescript
const resp = await fetch(`${url}/api/v1/smb-connectors`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Finance Fileserver",
    server_host: "fs01.corp.example.com",
    server_port: 445,
    share_name: "Finance",
    base_path: "2026",
    domain: "CORP",
    username: "scaidrive-svc",
    password: process.env.SMB_PASS,
    target_share_id: "shr_01J3H",
    target_path: "/From Fileserver",
    sync_direction: "bidirectional",
    sync_interval_minutes: 15,
  }),
});
const connector = await resp.json();
```

Credentials are encrypted at rest. The `password` field is write-only — reads never return it. Requires `MANAGE_PERMISSIONS` on the target share.

### All configuration fields

| Field | Notes |
|-------|-------|
| `name`, `description` | Display |
| `server_host`, `server_port` | SMB server, usually port 445 |
| `share_name` | SMB share root |
| `base_path` | Subpath inside the SMB share (optional) |
| `domain` | NT domain / workgroup |
| `username`, `password` | Service account |
| `target_share_id` | ScaiDrive share to mirror into |
| `target_path` | Path inside the target share (created if missing) |
| `sync_direction` | `bidirectional`, `smb_to_scaidrive`, `scaidrive_to_smb` |
| `sync_permissions` | Replicate SMB ACLs to ScaiDrive ACLs (requires identity mappings) |
| `sync_hidden_files` | Default false |
| `sync_system_files` | Default false |
| `include_patterns` | `{"extensions": [...], "patterns": [...]}` — whitelist |
| `exclude_patterns` | Same shape — blacklist |
| `conflict_resolution` | One of the sync strategies |
| `sync_interval_minutes` | Recurring sync schedule; 0 disables scheduled runs |

## Testing connectivity

Before your first sync, test the connection:

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/test \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

Response:

```json
{
  "success": true,
  "message": "Connected to fs01.corp.example.com\\Finance as CORP\\scaidrive-svc",
  "error": null
}
```

If `success: false`, `error` carries the SMB error (auth failure, DNS, firewall).

## Triggering a sync

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/sync \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

Returns `202 Accepted` with a job ID. List jobs:

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/jobs
```

```json
{
  "jobs": [
    {
      "id": "job_01J6A",
      "status": "completed",
      "started_at": "2026-04-23T10:00:00Z",
      "finished_at": "2026-04-23T10:07:33Z",
      "files_scanned": 8420,
      "files_synced": 42,
      "bytes_transferred": 98765432,
      "error_count": 0
    }
  ]
}
```

Scheduled syncs run on the `sync_interval_minutes` cadence. You can force a manual sync at any time.

## Identity mapping

By default, files synced from SMB are owned by the connector's service account in ScaiDrive. To preserve original ownership — so Alice who created a file in SMB is shown as the owner in ScaiDrive — configure identity mappings.

Map an SMB principal to a ScaiDrive user or group:

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/identity-mappings \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "identity_type": "user",
    "smb_principal": "CORP\\alice",
    "scaidrive_principal_id": "usr_01J4M"
  }'
```

With `sync_permissions: true` on the connector and identity mappings in place, SMB ACLs are translated to ScaiDrive ACEs automatically. Unmapped SMB principals generate a warning in the job log and fall back to the connector service account.

List mappings:

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/identity-mappings
```

Remove a mapping:

```bash
curl -X DELETE $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/identity-mappings/map_01J6B \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

## File-state inspection

To see which files the connector is tracking and their sync status:

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X/file-states
```

Useful for debugging — shows per-file last-sync time, last error, and current checksum on both sides.

## Conflict handling

In `bidirectional` mode, conflicts arise when both SMB and ScaiDrive change the same file between syncs. `conflict_resolution` controls:

- `LAST_WRITER_WINS` — newest modification time wins.
- `KEEP_BOTH` — server (ScaiDrive) side gets a `(conflict)` suffix; SMB side stays.
- `SCAIDRIVE_WINS` — ScaiDrive always wins.
- `SMB_WINS` — SMB always wins.

For safety during initial onboarding, consider starting in `smb_to_scaidrive` mode for a few cycles (SMB is authoritative, nothing in ScaiDrive can damage the original), then switch to `bidirectional` once you trust the flow.

## Updating a connector

```bash
curl -X PATCH $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sync_interval_minutes": 60}'
```

Any field except immutable ones (`target_share_id`) can be updated. Rotating credentials:

```bash
curl -X PATCH $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "new-svc", "password": "<new-secret>"}'
```

## Deleting a connector

```bash
curl -X DELETE $SCAIDRIVE_URL/api/v1/smb-connectors/cnn_01J5X \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

Deletes the connector and identity mappings. Content already synced into ScaiDrive stays. SMB content is untouched.

## Troubleshooting

**`CONNECTOR_AUTH_FAILED`** — SMB rejected credentials. Check domain, username, password. Check whether the account is locked or disabled.

**`CONNECTOR_UNREACHABLE`** — Network failure. Check DNS, firewall on port 445, SMB service on the server.

**Errors on individual files** — Show up in job `error_count`. Common causes: locked files (Office temp files `~$*` — exclude them), permission denied in SMB (service account needs read/write), symlinks (not followed).

**Partial syncs** — If a connector's job takes longer than the sync interval, the next scheduled run is skipped rather than overlapping. `GET /jobs` shows the schedule decisions.

## What's next

- [SharePoint Connector](/docs/scaidrive/connectors/sharepoint-connector) — the Microsoft 365 equivalent.
- [Connectors Reference](/docs/scaidrive/reference/connectors) — all endpoints.