> For the complete documentation index, see [llms.txt](https://docs.sudoplatform.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sudoplatform.com/guides/digital-account-protection/manage-data-holders.md).

# Manage Data Holders

A data holder is an organization discovered to hold data associated with a user's virtual presence. Data holders are automatically identified when a virtual presence is scanned.

Data holders are unique to the virtual presence and represent relationships with entities such as online retailers, social media platforms, or SaaS services that have interacted with the user's email account or other online presence.

### Retrieving a Data Holder <a href="#retrieving-a-data-holder" id="retrieving-a-data-holder"></a>

To retrieve a single data holder by its unique identifier, use the `getDataHolder` method. This will return the data holder if it exists.

{% tabs %}
{% tab title="Typescript" %}

```typescript
try {
  const dataHolder = await privacyInteractionClient.getDataHolder(dataHolderId)
  if (dataHolder) {
    // Data holder found.
    console.log(dataHolder.name, dataHolder.domainName)
  } else {
    // No data holder with this ID exists.
  }
} catch (error) {
  // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
do {
    if let dataHolder = try await privacyInteractionClient.getDataHolder(withId: dataHolderId) {
        // Data holder found.
        print(dataHolder.name, dataHolder.domainName)
    } else {
        // No data holder with this ID exists.
    }
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kt
launch {
    try {
        val dataHolder = withContext(Dispatchers.IO) {
            privacyInteractionClient.getDataHolder(dataHolderId)
        }
        if (dataHolder != null) {
            // Data holder found.
            println("${dataHolder.name} ${dataHolder.domainName}")
        } else {
            // No data holder with this ID exists.
        }
    } catch (e: DataHolderException) {
        // Handle/notify user of exception
    }
 }
```

{% endtab %}
{% endtabs %}

### Listing Data Holders <a href="#listing-data-holders" id="listing-data-holders"></a>

To retrieve all data holders associated with a specific virtual presence, use the `listDataHolders` method. Results are paginated.

A call to `listDataHolders` returns a `ListOutput` object containing a list of matching `items` and a `nextToken` to support pagination. If no results are found, the result will contain empty items. Always check the value of the returned `nextToken` since there are more results to retrieve when `nextToken` is defined.

{% tabs %}
{% tab title="Typescript" %}

```typescript
try {
  let nextToken: string | undefined = undefined
  do {
    const listOutput = await privacyInteractionClient.listDataHolders({
      virtualPresenceId: 'virtual-presence-id',
      limit: 20,
      nextToken,
    })

    for (const dataHolder of listOutput.items) {
      console.log(dataHolder.name, dataHolder.protectionState)
    }

    nextToken = listOutput.nextToken
  } while (nextToken !== undefined)
} catch (error) {
  // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
do {
    var nextToken: String?
    repeat {
        let listOutput = try await privacyInteractionClient.listDataHolders(
            withInput: ListDataHoldersInput(
                virtualPresenceId: "virtual-presence-id",
                limit: 20,
                nextToken: nextToken
            )
        )

        for dataHolder in listOutput.items {
            print(dataHolder.name, dataHolder.protectionState)
        }

        nextToken = listOutput.nextToken
    } while nextToken != nil
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kt
launch {
    try {
        var nextToken: String? = null
        do {
            val listOutput = withContext(Dispatchers.IO) {
                privacyInteractionClient.listDataHolders(
                    ListDataHoldersInput(
                        virtualPresenceId = "virtual-presence-id",
                        limit = 20,
                        nextToken = nextToken,
                    ),
                )
            }
            for (dataHolder in listOutput.items) {
                println("${dataHolder.name} ${dataHolder.protectionState}")
            }
            nextToken = listOutput.nextToken
        } while (nextToken != null)
    } catch (e: DataHolderException) {
        // Handle/notify user of errors
    }
}
```

{% endtab %}
{% endtabs %}

**Input Parameters:**

| Parameter           | Type   | Required | Description                                                      |
| ------------------- | ------ | -------- | ---------------------------------------------------------------- |
| `virtualPresenceId` | string | Yes      | The identifier of the virtual presence to list data holders for. |
| `limit`             | number | No       | Maximum number of items to return. Will be defaulted if omitted. |
| `nextToken`         | string | No       | A pagination token from a previous call.                         |

### Data Holder Protection States <a href="#data-holder-protection-states" id="data-holder-protection-states"></a>

Each data holder has a protection state indicating its current status in the monitoring lifecycle:

| State              | Description                                                                     |
| ------------------ | ------------------------------------------------------------------------------- |
| `MONITORED`        | The data holder is being actively monitored for privacy changes.                |
| `ACTION_REQUESTED` | An action (e.g., deletion request) has been initiated against this data holder. |
| `RESOLVED`         | The data holder interaction has been resolved.                                  |

### Listing Data Holder Scan Summaries <a href="#subscribing-to-data-holder-updates" id="subscribing-to-data-holder-updates"></a>

Each time a data holder is created or update as the result of a scan, a scan summary will be generated for that data holder. The latest scan summary is returned as an attribute when `getDataHolder` is invoked, or the full list of scan summaries for a given data holder can be retrieved using the `listDataHolderScanSummaries` endpoint.

{% tabs %}
{% tab title="Typescript" %}

```typescript
try {
  let nextToken: string | undefined = undefined
  do {
    const listOutput = await privacyInteractionClient.listDataHolderScanSummaries({
      dataHolderId: 'data-holder-id',
      limit: 20,
      nextToken,
    })

    for (const summary of listOutput.items) {
      console.log(summary.scannedAt, summary.emailCount)
    }

    nextToken = listOutput.nextToken
  } while (nextToken !== undefined)
} catch (error) {
  // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
do {
    var nextToken: String?
    repeat {
        let listOutput = try await privacyInteractionClient.listDataHolderScanSummaries(
            withInput: ListDataHolderScanSummariesInput(
                dataHolderId: "data-holder-id",
                limit: 20,
                nextToken: nextToken
            )
        )

        for summary in listOutput.items {
            print(summary.scannedAt, summary.emailCount)
        }

        nextToken = listOutput.nextToken
    } while nextToken != nil
} catch {
    // Handle/notify user of errors
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kt
launch {
    try {
        var nextToken: String? = null
        do {
            val listOutput = withContext(Dispatchers.IO) {
                privacyInteractionClient.listDataHolderScanSummaries(
                    ListDataHolderScanSummariesInput(
                        dataHolderId = "data-holder-id",
                        limit = 20,
                        nextToken = nextToken,
                    ),
                )
            }
            for (summary in listOutput.items) {
                println("${summary.scannedAt} ${summary.emailCount}")
            }
            nextToken = listOutput.nextToken
        } while (nextToken != null)
    } catch (e: DataHolderException) {
        // Handle/notify user of errors
    }
}
```

{% endtab %}
{% endtabs %}

### Subscribing to Data Holder Updates <a href="#subscribing-to-data-holder-updates" id="subscribing-to-data-holder-updates"></a>

To receive real-time notifications when data holders are discovered or updated during scanning, see [Subscriptions](https://docs.sudoplatform.com/~/revisions/U8P5YQbTWlABRqHUlUfP/guides/privacy-interaction/subscriptions).
