Import data to Google Chat

With the Google Chat API, you can import data from your other messaging platforms into Google Chat. You can import existing messages, attachments, reactions, memberships, and space entities from your other messaging platforms to corresponding Chat API resources. You can import this data by creating Chat spaces in import mode and importing data into those spaces. After the process successfully completes, these spaces become standard Chat spaces.

The following outlines the complete import process:

  1. Plan your import
  2. Configure authorization for the Chat app
  3. Create a space in import mode
  4. Import resources
  5. Validate imported resources
  6. Reconcile imported resource differences from source data
  7. Complete import mode
  8. Give access to the space after import mode
  9. Troubleshooting

Prerequisites

Apps Script

Python

Plan your import

Plan accordingly for the amount of data to be imported, understand how the usage limits and quotas can impact the import process, and be aware of the types of Chat spaces supported when importing to a new space.

Review API usage limits

The time required to import data into Chat can vary greatly depending on the quantity of Chat resources to import. Review your Chat app's usage limits and the amount of data scheduled for import from the source messaging platform to determine an estimated timeline.

When importing messages to a space, we recommend that you spread the calls to the messages.create() method across different message threads.

Identify the supported spaces to import

Import mode only supports the SpaceType of SPACE and GROUP_CHAT. It does not support DIRECT_MESSAGE. See the documentation for SpaceType for more information.

Create a space in import mode

To create a space in import mode, call the create method on the Space resource and set importMode to true.

When you create the space in import mode, make note of the following.

  • The date and time - Remember, import mode must be completed within 30 days. If the space is still in import mode after 30 days from the time the spaces.create() method was called, it's automatically deleted and becomes inaccessible and unrecoverable.
    • Don't use the value of the createTime field to track the expiration of the 30 day timeframe. This is not always the same as when you call the spaces.create() method. When using import mode, the createTime field can be set to the historical timestamp at which the space was created in the source in order to preserve the original creation time.
  • The space resource name (name) - The unique identifier that is used to retrieve information about the specific space and is referenced in later steps when importing content into the space.

To preserve the creation time of the equivalent space entity from the source messaging platform, you can set the createTime of the space. This createTime must be set to a value between January 1, 2000 and present time.

To create an external space in import mode, set externalUserAllowed to true. After import is successfully completed, you can add external users.

The following example shows how to create a space in import mode:

Apps Script

function createSpaceInImportMode() {
  const space = Chat.Spaces.create({
      spaceType: 'SPACE',
      displayName: 'DISPLAY_NAME',
      importMode: true,
      createTime: (new Date('January 1, 2000')).toJSON()
  });
  console.log(space.name);
}

Python

"""Create a space in import mode."""

import datetime

from google.oauth2 import service_account
from googleapiclient.discovery import build

# Specify required scopes.
SCOPES = [
    'https://www.googleapis.com/auth/chat.import',
]

CREDENTIALS = (
    service_account.Credentials.from_service_account_file('credentials.json')
    .with_scopes(SCOPES)
    .with_subject('EMAIL')
)

# Build a service endpoint for Chat API.
service = build('chat', 'v1', credentials=CREDENTIALS)

result = (
    service.spaces()
    .create(
        body={
            'spaceType': 'SPACE',
            'displayName': 'DISPLAY_NAME',
            'importMode': True,
            'createTime': f'{datetime.datetime(2000, 1, 1).isoformat()}Z',
        }
    )
    .execute()
)

print(result)

Replace the following:

  • EMAIL: the email address of the user account that you're impersonating with domain-wide authority.
  • DISPLAY_NAME: the name for the space created in import mode. This must be a unique name for the space that's displayed to Chat users. We recommend using the same display name as the space from which you're importing data.

Import resources

To import resources from other messaging platforms, you create Google Chat resources (such as messages, reactions, attachments) in the import mode space. When you create a resource in the space, you specify data from the related resource from the message platform that you're migrating from.

Messages

Your Chat apps can import messages using their own authority, or on behalf of a user through impersonation. The message author is set to the impersonated user account. For more information, see Authorize Chat apps. To import a message in an import mode space, call the create method on the Message resource. In order to preserve the creation time of the original message from the source messaging platform, you can set the createTime of the message. This createTime must be set to a value between the space creation time that you previously set and present time.

Messages in the same space cannot contain the same createTime, even if previous messages with that time are deleted.

Messages containing third-party URLs in import mode spaces can't render link previews within Google Chat.

When you create the messages in import mode, spaces don't notify or send email to any users, including messages which contain user mentions.

The following example shows how to create a message in an import mode space:

Python

"""Create a message in import mode space."""

import datetime

from google.oauth2 import service_account
from googleapiclient.discovery import build

# Specify required scopes.
SCOPES = [
    'https://www.googleapis.com/auth/chat.import',
]

CREDENTIALS = (
    service_account.Credentials.from_service_account_file('credentials.json')
    .with_scopes(SCOPES)
    .with_subject('EMAIL')
)

# Build a service endpoint for Chat API.
service = build('chat', 'v1', credentials=CREDENTIALS)

NAME = 'spaces/SPACE_NAME'
result = (
    service.spaces()
    .messages()
    .create(
        parent=NAME,
        body={
            'text': 'Hello, world!',
            'createTime': f'{datetime.datetime(2000, 1, 2).isoformat()}Z',
        },
    )
    .execute()
)

print(result)

Replace the following:

Reactions

Your Chat app can import reactions for messages by using the Chat API. For information about the resource methods and types of authentication support in import mode spaces, see Authorize Chat apps.

Attachments

Your Chat app can upload attachments using the Chat API. For information about the resource methods and types of authentication support in import mode spaces, see Authorize Chat apps. However, we highly recommended that you use Google Drive API to upload attachments as Google Drive files and link the file URIs to the respective messages in the import mode spaces to import attachments from other messaging platforms to avoid hitting Google Chat internal limit for attachment upload.

Historical memberships

Historical memberships are memberships created for users who had already left the original space entity from the source messaging platform, but you want to retain their data in Chat. For information about adding new members after the space is no longer in import mode, see Create membership resource.

In many cases, when those historical members are subject to a data retention policy in Google, you want to preserve the data (such as Messages and reactions) created by historical memberships in a space before importing them to Chat. While the space is in import mode, you can import those historical memberships into the space, using the create method on the Membership resource. In order to preserve the leave time of the historical membership, you must set the deleteTime of the membership. This leave time must be accurate because it impacts which data to retain for those memberships. Moreover, this deleteTime must be after the space creation timestamp and must not be a future timestamp.

In addition to deleteTime, you can also set createTime to preserve the original join time of the historical membership. Unlike deleteTime, the createTime is optional. If unset, createTime is automatically calculated by subtracting 1 microsecond from deleteTime. If set, createTime must be before deleteTime and must be on or after the space creation time. This createTime information isn't used to determine data retention and isn't visible in admin tools such as the Google Admin console and Google Vault.

While there might be multiple ways that a user can join and leave a space in the source messaging platform (through invites, joining by themselves, being added by another user), in Chat those actions are all represented by the historical membership createTime and deleteTime fields as being added or removed.

The following example shows how to create a historical membership in an import mode space:

Python

"""Create a historical membership in import mode space."""

import datetime

from google.oauth2 import service_account
from googleapiclient.discovery import build

# Specify required scopes.
SCOPES = [
    'https://www.googleapis.com/auth/chat.import',
]

CREDENTIALS = (
    service_account.Credentials.from_service_account_file('credentials.json')
    .with_scopes(SCOPES)
    .with_subject('EMAIL')
)

# Build a service endpoint for Chat API.
service = build('chat', 'v1', credentials=CREDENTIALS)

NAME = 'spaces/SPACE_NAME'
USER = 'users/USER_ID'
result = (
    service.spaces()
    .members()
    .create(
        parent=NAME,
        body={
            'createTime': f'{datetime.datetime(2000, 1, 3).isoformat()}Z',
            'deleteTime': f'{datetime.datetime(2000, 1, 4).isoformat()}Z',
            'member': {'name': USER, 'type': 'HUMAN'},
        },
    )
    .execute()
)

print(result)

Replace the following:

Import resources in an external space

You can only create an external space with import mode using credentials belonging to users inside your Workspace organization. This only applies while the space is in import mode. Once the space completes import mode, external users can be invited to join the imported spaces (see access section) and their credentials can be used to call Chat API.

Validate imported resources

Your Chat app can read back and validate the contents of an import mode space by calling the list method on the Message resource. You can read Reaction and Attachment resources from any returned message's emojiReactionSummaries and attachment fields. Chat apps can only call this method on behalf of a user through impersonation. For more information, see Authorize Chat apps.

Your Chat app can also read individual messages for validation by calling the get method on the Message resource. Chat apps can only call this method to read their own messages by using their own authority. For more information, see Authorize Chat apps.

Chat apps can also list historical memberships by calling the list method on the Membership resource. After the space exits import mode, the list method doesn't expose historical memberships anymore. Chat apps can only call this method on behalf of a user through impersonation. For more information, see Authorize Chat apps.

You can read an import mode space's properties by calling the get method on the Space resource. Chat apps can only call this method using their own authority. For more information, see Authorize Chat apps.

Reconcile imported resource differences from source data

If any imported resource no longer matches the original entity from the source messaging platform due to changes in the original entity during import, Chat apps can call the Chat API to modify the imported chat resource. For example, if a user edits a message in the source messaging platform after that message was created in Chat, Chat apps can update the imported message so that it reflects the current content of the original message.

Messages

To update supported fields on a message in an import mode space, call the update method on the Message resource. Chat apps can only call this method using the same authority that was used during the initial message creation. If you used user impersonation during the initial message creation, you must use the same impersonated user to update that message.

To delete a message in an import mode space, call the delete method on the Message resource. Messages in an import mode space don't need to be deleted by the original message creator and can be deleted by impersonating any user in the domain. Chat apps can only delete their own messages using their own authority. For more information, see Authorize Chat apps.

Reactions

To delete a reaction for a message in an import mode space, use the delete method on the reactions resource. For information about the resource methods and types of authentication support in import mode spaces, see Authorize Chat apps.

Attachments

To update attachments for a message in an import mode space, use the upload method on the media resource. For information about the resource methods and types of authentication support in import mode spaces, see Authorize Chat apps.

Historical memberships

To delete a historical membership in an import mode space, use the delete method on the Membership resource. After a space exits import mode, the delete method doesn't let you delete historical memberships anymore.

You can't update a historical membership in an import mode space. If you want to correct an incorrectly imported historical membership, you need to delete it first and then recreate it while the space is still in import mode.

Spaces

To update supported fields in an import mode space, use the patch method on the spaces resource.

To delete an import mode space, use the delete method on the spaces resource.

For information about the resource methods and types of authentication support in import mode spaces, and see Authorize Chat apps.

Complete import mode

Before calling the completeImport method, you should ensure that validation and reconciliation of resource differences are completed. Exiting a space out of import mode is an irreversible process and converts the import mode space into a regular space. There's no indicator in Chat that attributes these spaces to a data import.

Make note of the date and time you call completeImport, the resource name of the user who made the call, and the response returned. This can be helpful if you must encounter any issues and must investigate them.

To complete import mode and make the space accessible to users, the Chat app can call the completeImport method on the Space resource. Chat apps can only call this method on behalf of a user through impersonation. For more information, see Authorize Chat apps. The impersonated user is added to the space as a space manager once this method completes. This method must be called within 30 days of the initial create.space method call. If you attempt to call this method after the 30 day duration has elapsed, the call results in failures because the import mode space is deleted and is no longer accessible to the Chat app.

The impersonated user in the completeImport method doesn't need to be the space creator.

The following example shows how to complete the import mode:

Python

"""Complete import."""

from google.oauth2 import service_account
from googleapiclient.discovery import build

# Specify required scopes.
SCOPES = [
    'https://www.googleapis.com/auth/chat.import',
]

CREDENTIALS = (
    service_account.Credentials.from_service_account_file('credentials.json')
    .with_scopes(SCOPES)
    .with_subject('EMAIL')
)

# Build a service endpoint for Chat API.
service = build('chat', 'v1', credentials=CREDENTIALS)

NAME = 'spaces/SPACE_NAME'
result = service.spaces().completeImport(name=NAME).execute()

print(result)

Replace the following:

Give access to the space after import mode

To give Chat users access to the recently imported space, Chat apps can continue to use the chat.import scope and user impersonation within 30 days of the initial create.space() method call to do the following:

To use these methods with the chat.import scope, the impersonated user must be a space manager.

For external spaces, the membership create() method also allows to invite users outside of your Workspace organization. Make sure you understand all the known limitations for external users.

Troubleshooting

If you experience a problem when importing Chat spaces, review the following issues for assistance. If you encounter an error response, make note of it (copy/paste the text into a document or save a screenshot) for future reference and troubleshooting.

When a space is successfully imported, CompleteImportSpace completes with a status of OK.

Didn't complete import before the 30-day window expired

As previously described in Create a space in import mode, if the space is still in import mode after 30 days from the time the create method was called, it's automatically deleted and becomes inaccessible and unrecoverable.

Unfortunately, the deleted space is no longer available or recoverable and the import process must be initiated again.

Find missing spaces

If you're unable to find the new Chat space, review the following table for the response you received from CompleteImportSpace to see the explanation and how to resolve it.

Response received Investigation steps Explanation Resolution
CompleteImportSpace throws an exception and calling GetSpace returns PERMISSION_DENIED. Check your records for when the space was created and if it's older than 30 days, it was automatically deleted. Additionally, there is no record of the imported space in the space management tool or audit log. It's been longer than 30 days since the import process was started and the space failed to successfully exit migration. Create a new space and run the import process again.
CompleteImportSpace returns OK and calling GetSpace returns PERMISSION_DENIED. There's no record of the imported space in the space management tool, but the space is shown to be deleted in the audit log. The space was successfully imported, but subsequently deleted. Create a new space and run the import process again.