> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trusset.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Database Sync

> Bulk-import and export customer records between your systems and Trusset

The `sync` sub-module handles bulk migration of customer data between your existing systems and Trusset. It is designed for institutions with established customer databases that need to onboard thousands of records without manual entry.

Records are mapped by `externalId` - your system's unique customer identifier. This key is used for deduplication and conflict resolution across syncs.

## Import records

```typescript theme={null}
import { SyncRecord } from '@trusset/sdk'

const records: SyncRecord[] = existingCustomers.map(row => ({
  externalId: row.customerId,       // required - your unique ID
  name: row.fullName,
  walletAddress: row.ethAddress,    // optional
  country: row.countryCode,
  investorType: 'RETAIL',
  kycHash: row.kycRootHash,         // root hash from the KYC proof tool
  metadata: { source: 'core-banking', migrationBatch: '2025-Q1' },
}))

const result = await trusset.customers.sync.importRecords(records, {
  batchSize: 50,
  onConflict: 'update',
  onProgress: (done, total) => {
    console.log(`${done}/${total} processed`)
  },
})

result.total    // total records submitted
result.created  // new customers created
result.updated  // existing customers updated
result.skipped  // skipped due to onConflict: 'skip'
result.errors   // array of { externalId, code, message }
```

The SDK processes records in configurable batches to avoid overloading the API. Each record is matched against existing customers by `externalId`. If a match is found, the `onConflict` strategy determines the outcome.

### Conflict strategies

| Strategy | Behavior                                                                                             |
| -------- | ---------------------------------------------------------------------------------------------------- |
| `update` | Overwrites name, country, investorType, walletAddress, and metadata on the existing record. Default. |
| `skip`   | Leaves the existing record untouched. Counted in `result.skipped`.                                   |

### With on-chain verification

Set `verifyOnChain: true` to automatically batch-verify imported records that have both a `walletAddress` and a `country`. This runs after the database import completes and requires a verified [registered wallet](/protocol/infrastructure/custody) on the instance. Each record's `kycHash` (the root hash from the [KYC proof tool](/sdk/customers/kyc-proofs)) is passed through to the on-chain verification, so proof-backed claims can be added later.

```typescript theme={null}
const result = await trusset.customers.sync.importRecords(records, {
  onConflict: 'update',
  verifyOnChain: true,
  verificationDefaults: {
    softExpiryDays: 365,
    hardExpiryDays: 730,
  },
})
```

On-chain verification failures do not roll back the database import. Failed verifications appear in `result.errors` with code `VERIFY_FAILED`.

<Expandable title="SyncOptions reference">
  <ParamField body="batchSize" type="number" default={50}>
    Records per API call. Range: 1-200. Higher values reduce HTTP overhead but increase per-request latency.
  </ParamField>

  <ParamField body="onConflict" type="string" default="update">
    `update` or `skip`. Determines behavior when a customer with the same `externalId` already exists.
  </ParamField>

  <ParamField body="verifyOnChain" type="boolean" default={false}>
    If `true`, batch-verifies addresses on the IdentityRegistry after import. Only applies to records with both `walletAddress` and `country`.
  </ParamField>

  <ParamField body="verificationDefaults" type="object">
    Default `softExpiryDays` and `hardExpiryDays` for on-chain verification.
  </ParamField>

  <ParamField body="onProgress" type="function">
    Callback invoked after each batch: `(processed: number, total: number) => void`.
  </ParamField>
</Expandable>

## Export records

Pull all customer data back out as flat `SyncRecord` objects. Useful for syncing Trusset state back into your core systems or for audit purposes.

```typescript theme={null}
const records = await trusset.customers.sync.exportRecords({
  includeArchived: false,
})

// records: SyncRecord[]
// Each record: { externalId, walletAddress?, name?, country?, investorType?, metadata? }
```

The method paginates internally - it fetches all records regardless of total count. For very large datasets (50k+ customers), consider using the [list endpoint](/endpoints/customers/list) directly with pagination for more control.

## SyncRecord schema

Every record requires `externalId`. All other fields are optional.

```typescript theme={null}
interface SyncRecord {
  externalId: string          // your system's unique customer ID
  walletAddress?: string      // Ethereum address
  name?: string               // display name
  country?: string            // ISO country code
  investorType?: string       // preset or custom verification profile key
  kycHash?: string            // root hash from the KYC proof tool
  metadata?: Record<string, unknown>
}
```

## Error handling

Import errors are collected per-record rather than failing the entire batch. The `errors` array in the result contains one entry per failed record:

```typescript theme={null}
const result = await trusset.customers.sync.importRecords(records)

for (const err of result.errors) {
  console.error(`Failed: ${err.externalId} - ${err.code}: ${err.message}`)
}
```

Common error codes:

| Code              | Cause                                                 |
| ----------------- | ----------------------------------------------------- |
| `INVALID_ADDRESS` | Wallet address failed checksum validation             |
| `CUSTOMER_EXISTS` | Duplicate wallet address (different externalId)       |
| `VERIFY_FAILED`   | On-chain batch verification failed for this entry     |
| `UNKNOWN`         | Unexpected server error - check `message` for details |
