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

# Syncing Contacts

> Syncing device contacts to the cloud

# Syncing Contacts

Once contacts access is granted, contacts are synced from the device to the cloud automatically without any action required from you.

## Automatic Sync

Contacts sync in small batches whenever the app is in the foreground. If [Background Sync](/services/background-sync) is enabled, contacts sync even when the app is not active. Even large contact books with 1000+ contacts sync in 60-90 seconds, depending on network conditions.

For subsequent app launches, only unsynced or modified contacts are synchronized, ensuring minimal network and battery usage.

The SDK automatically triggers sync when:

* The app becomes active
* Contact store changes are detected
* Contact access status changes from denied to granted

## Sync Metrics and Tracking

You can track the progress and results of contact syncing operations using platform-specific callbacks.

<CodeGroup>
  ```swift Swift theme={null}
  import ContactsManager

  // Set up a completion handler to receive sync metrics
  ContactsService.shared.onContactsSynced = { metrics in
      print("Sync completed with the following metrics:")
      print("Total device contacts: \(metrics.totalDeviceContacts)")
      print("New contacts added: \(metrics.newContacts)")
      print("Updated contacts: \(metrics.updatedContacts)")
      print("Unchanged contacts: \(metrics.unchangedContacts)")
      print("Deleted contacts: \(metrics.deletedContacts)")
      print("Total processed: \(metrics.totalProcessed)")
      
      // Update your UI or notify the user about sync completion
      DispatchQueue.main.async {
          // Update UI elements
          self.updateSyncStatusLabel(metrics: metrics)
      }
  }

  // Example function to update UI
  func updateSyncStatusLabel(metrics: SyncMetrics) {
      let totalChanged = metrics.newContacts + metrics.updatedContacts + metrics.deletedContacts
      if totalChanged > 0 {
          syncStatusLabel.text = "Synced \(totalChanged) contact changes"
      } else {
          syncStatusLabel.text = "Contacts up to date"
      }
  }
  ```

  ```kotlin Kotlin theme={null}
  import io.contactsmanager.api.ContactService
  import io.contactsmanager.api.models.CMSyncMetrics

  // Set up a completion handler to receive sync metrics
  ContactService.getInstance(context).onContactsSynced = { metrics ->
      println("Sync completed with the following metrics:")
      println("Total device contacts: ${metrics.totalDeviceContacts}")
      println("New contacts added: ${metrics.newContacts}")
      println("Updated contacts: ${metrics.updatedContacts}")
      println("Unchanged contacts: ${metrics.unchangedContacts}")
      println("Deleted contacts: ${metrics.deletedContacts}")
      println("Total processed: ${metrics.totalProcessed}")
      
      // Update your UI or notify the user about sync completion
      runOnUiThread {
          // Update UI elements
          updateSyncStatusLabel(metrics)
      }
  }

  // Example function to update UI
  fun updateSyncStatusLabel(metrics: CMSyncMetrics) {
      val totalChanged = metrics.newContacts + metrics.updatedContacts + metrics.deletedContacts
      if (totalChanged > 0) {
          syncStatusLabel.text = "Synced $totalChanged contact changes"
      } else {
          syncStatusLabel.text = "Contacts up to date"
      }
  }
  ```
</CodeGroup>

## SyncMetrics Structure

The SDK provides detailed metrics through the `SyncMetrics` structure:

<CodeGroup>
  ```swift Swift theme={null}
  public struct SyncMetrics {
      /// Total number of contacts found on device
      public let totalDeviceContacts: Int
      /// Number of new contacts added
      public let newContacts: Int
      /// Number of contacts that were updated
      public let updatedContacts: Int
      /// Number of contacts that were unchanged
      public let unchangedContacts: Int
      /// Number of contacts that were deleted
      public let deletedContacts: Int
      /// Total number of contacts processed
      public let totalProcessed: Int
  }
  ```

  ```kotlin Kotlin theme={null}
  data class SyncMetrics(
      /** Total number of contacts found on device */
      val totalDeviceContacts: Int,
      
      /** Number of new contacts added */
      val newContacts: Int,
      
      /** Number of contacts that were updated */
      val updatedContacts: Int,
      
      /** Number of contacts that were unchanged */
      val unchangedContacts: Int,
      
      /** Number of contacts that were deleted */
      val deletedContacts: Int,
      
      /** Total number of contacts processed */
      val totalProcessed: Int
  )
  ```
</CodeGroup>

These metrics help you understand the scope and impact of each sync operation.

## Force Sync

Sometimes you may need to force a complete resync of all contacts, regardless of their current sync status. This is useful when troubleshooting sync issues or ensuring data consistency after server-side changes.

### Implementation

<CodeGroup>
  ```swift Swift theme={null}
  import ContactsManager

  // Force resync all contacts
  do {
      let resyncedCount = try await ContactsService.shared.forceResyncAllContacts()
      print("Successfully resynced \(resyncedCount) contacts")
  } catch {
      print("Force resync failed: \(error.localizedDescription)")
  }

  // You can also use the completion handler to track progress
  ContactsService.shared.onContactsSynced = { metrics in
      print("Force resync completed:")
      print("Total contacts processed: \(metrics.totalProcessed)")
      // All contacts will appear as "updated" since sync timestamps were reset
  }
  ```

  ```kotlin Kotlin theme={null}
  // TODO: Coming Soon
  ```
</CodeGroup>

### Important Notes

* **Performance Impact**: Force sync processes ALL contacts, which may take longer than regular sync
* **Network Usage**: This operation will re-upload all contact data
* **Use Sparingly**: Only use when necessary, as regular incremental sync is more efficient

## User Logout

When users log out of your application, you should properly clean up the ContactsManager service to ensure user data privacy and prepare for the next user session.

### When to Use Reset

* **User Logout**: When the current user signs out of your application
* **Account Switching**: When switching between different user accounts

### Implementation

<CodeGroup>
  ```swift Swift theme={null}
  import ContactsManager

  // Logout: Clean up ContactsManager when user logs out
  do {
      // This clears all local contact data and user session
      try await ContactsService.shared.reset()
      print("User logged out, ContactsManager cleaned up successfully")
  } catch {
      print("Logout cleanup failed: \(error.localizedDescription)")
  }

  // When a new user logs in, reinitialize with their credentials
  do {
      try await ContactsService.shared.initialize(
          withToken: "new-user-token",
          options: ContactsManagerOptions(
              verboseLogging: false,
              autoSyncEnabled: true
          )
      )
      print("ContactsManager initialized for new user")
  } catch {
      print("Initialization failed: \(error.localizedDescription)")
  }
  ```

  ```kotlin Kotlin theme={null}
  // TODO: Coming Soon
  ```
</CodeGroup>

### What Logout Does

1. **Clears Local Database**: Removes all stored contact data for privacy
2. **Resets Sync State**: Clears all sync timestamps and metadata
3. **Unsubscribes Events**: Stops all background listeners and observers
4. **Clears User Session**: Removes stored user tokens and preferences
5. **Service State**: Returns the service to uninitialized state

## Best Practices

1. **Initial Sync**: After getting contacts authorization, let the automatic sync happen without interruption
2. **Completion Indication**: Use the sync metrics to show progress to users when syncing large contact lists
3. **Background Sync**: For the best user experience, enable [Background Sync](/services/background-sync) to keep contacts up-to-date even when the app is not active
