Manage Holds

Holds preserve data indefinitely to meet legal or preservation obligations. Usually holds are placed on one or more users to ensure that the data potentially relevant to a matter cannot be deleted until that matter is no longer active.

If a user who is subject to a hold deletes held data, that data is removed from the user's view, but it is preserved in Vault. As long as the hold is in place, a Vault admin can search and export that data.

Holds have the following components:

  • A service—the application responsible for the data to be held. The service can be set to mail, Drive, or Groups.
  • A scope—the entities covered by the hold. The scope can be set to one or more user accounts, or to an organizational unit (OU).
  • Additional options (optional)—the specific details (search queries or configuration options) used to narrow down the data to be held within the defined scope. Options include:
    • mail, Groups: search query to narrow down the hold
    • Drive: include Team Drives in the hold

Create a hold for mail on specific user accounts with a search query

The following example shows how a hold named "My First mail Accounts Hold" is created for:

  • Service: mail
  • Entity: user accounts "user1" and "user2"
  • Additional options: search query "to:ceo@company.com"

Retrieve user account IDs from AdminSdk.

Java

HeldMailQuery mailQuery = new HeldMailQuery().setTerms("to:ceo@company.com");
List accounts = Lists.newArrayList();
accounts.add(new HeldAccount().setAccountId(user1accountId));
accounts.add(new HeldAccount().setAccountId(user2accountId));
Hold hold = new Hold()
    .setName("My First mail Accounts Hold")
    .setCorpus("MAIL");
    .setQuery(new CorpusQuery().setMailQuery(mailQuery))
    .setAccounts(accounts);
Hold createdHold = client.matters().holds().create(matterId, hold).execute();

  }

Python

def create_hold_mail_accounts(service, matter_id, account_id):
    mail_query = {'terms': 'to:ceo@company.com'}
    accounts = [{'accountId': account_id}]
    wanted_hold = {
        'name': 'My First mail Accounts Hold',
        'corpus': 'MAIL',
        'query': {
            'mailQuery': mail_query
        },
        'accounts': accounts
    }
    return service.matters().holds().create(
        matterId=matter_id, body=wanted_hold).execute()

Create a hold for Drive on an OU and include Team Drive content

The following example shows how a hold named "My First Drive OU Hold" is created for:

  • Service: Drive
  • Entity: org unit "Finance" (OU ID is captured in orgUnitId)
  • Additional options: include Team Drives that users in this org unit are members of

Retrieve OU IDs from AdminSdk.

Java

HeldOrgUnit orgUnit = new HeldOrgUnit().setOrgUnitId(orgUnitId);
// Include team drives content.
HeldDriveQuery driveQuery = new HeldDriveQuery().setIncludeTeamDriveFiles(true);
// Create the hold.
Hold hold = new Hold()
    .setName("My First Drive OU Hold")
    .setCorpus("DRIVE")
    .setQuery(new CorpusQuery().setDriveQuery(driveQuery))
    .setOrgUnit(orgUnit);
Hold createdHold = client.matters().holds().create(matterId, hold).execute();
return createdHold;

Python

def create_hold_drive_org(service, matter_id, org_unit_id):
    drive_query = {'includeTeamDriveFiles': True}
    org_unit = {'orgUnitId': org_unit_id}
    wanted_hold = {
        'name': 'My First Drive OU Hold',
        'corpus': 'DRIVE',
        'orgUnit': org_unit,
        'query': {
            'driveQuery': drive_query
        }
    }
    return service.matters().holds().create(
        matterId=matter_id, body=wanted_hold).execute()

Create a hold for Groups on specific group accounts with a date range

The following example shows how a hold named "My First Group Hold" is created for:

  • Service: Groups
  • Entity: group accounts "group1" and "group2"
  • Additional options: hold only messages with sent dates between "startTime" and "endTime"

Retrieve group account IDs from AdminSdk.

Java

String APRIL_2_2017_GMT = "2017-04-02T00:00:00Z"; // See below for format*.

List accounts = Lists.newArrayList();
accounts.add(new HeldAccount().setAccountId(accountId));
accounts.add(new HeldAccount().setAccountId(accountId2));
HeldGroupsQuery groupQuery = new HeldGroupsQuery();
// Restrict by sent date.
groupQuery.setStartTime(APRIL_2_2017_GMT);
groupQuery.setEndTime(APRIL_2_2017_GMT);
// create the hold
Hold hold = new Hold()
    .setName("My First Group Hold")
    .setCorpus("GROUPS")
    .setQuery(new CorpusQuery().setGroupsQuery(groupQuery));
    hold.setAccounts(accounts);
Hold createdHold = client.matters().holds().create(matterId, hold).execute();
 

Python

def create_hold_groups_date_range(service, matter_id, group_account_id):
    groups_query = {
        'startTime': '2017-04-02T00:00:00Z', # See below for format*
        'endTime': '2017-04-02T00:00:00Z'
    }
    accounts = [{'accountId': group_account_id}]
    wanted_hold = {
        'name': 'My First Group Hold',
        'corpus': 'GROUPS',
        'query': {
            'groupsQuery': groups_query
        },
        'accounts': accounts
    }
    return service.matters().holds().create(
        matterId=matter_id, body=wanted_hold).execute()
 
  • Timestamp format. Additionally, start/endTimes are converted to GMT and rounded down to the start of the given date.

Query and modify existing holds

The following example shows how to list all of the accounts included in an existing hold:

Java

client.matters().holds().accounts().list(matterId, holdId).execute().getAccounts();

Python

# If no accounts are on hold, ['accounts'] will raise an error.
def list_held_accounts(service, matter_id, hold_id):
    return service.matters().holds().accounts().list(
        matterId=matter_id, holdId=hold_id).execute()['accounts'] 

The following example shows how to add an account to, and remove an account from, an existing hold:

Java

// Add an account by id.
client
        .matters()
        .holds()
        .accounts()
        .create(matterId, holdId, new HeldAccount().setAccountId(accountId))
        .execute();
// Remove an account by id.
client.matters().holds().accounts().delete(matterId, holdId, accountId).execute(); 

Python

 
def add_held_account(service, matter_id, hold_id, account_id):
    held_account = {'accountId': account_id}
    return service.matters().holds().accounts().create(
        matterId=matter_id, holdId=hold_id, body=held_account).execute()

def remove_held_account(service, matter_id, hold_id, account_id):
    return service.matters().holds().accounts().delete(
        matterId=matter_id, holdId=hold_id, accountId=account_id).execute()
 

The following example shows how to modify the OU on an existing OU hold:

Java

Hold hold = client.matters().holds().get(matterId, holdId).execute();
hold.getOrgUnit().setOrgUnitId(newOrgUnitId);
Hold modifiedHold = client.matters().holds().update(matterId, holdId, hold).execute();
return modifiedHold;
 

Python

def update_hold_ou(service, matter_id, hold_id, org_unit_id):
    current_hold = get_hold(matter_id, hold_id)
    current_hold['orgUnit'] = {'orgUnitId': org_unit_id}
    return service.matters().holds().update(
        matterId=matter_id, holdId=hold_id, body=current_hold).execute() 

The following example shows how to list all holds for a matter:

Java

 
String matterId = "Matter Id";

// List all holds. List holdsList = client.matters().holds().list(matterId).execute().getHolds();

// Paginate on holds. ListHoldsResponse response = client .matters() .holds() .list(matterId) .setPageSize(10) .execute();

String nextPageToken = response.getNextPageToken(); if (nextPageToken != null) { client .matters() .holds() .list(matterId) .setPageSize(10) .setPageToken(nextPageToken) .execute(); }

Python

# This can paginate in the same manner as with matters.
def list_holds(service, matter_id):
    return service.matters().holds().list(matterId=matter_id).execute()