Retrieve Changes

For Google Drive apps that need to keep track of changes to files, the Changes collection provides an efficient way to detect changes to all files, including those that have been shared with a user. The collection works by providing the current state of each file, if and only if the file has changed since a given point in time.

Retrieve the start page token for the first time

To request the page token for the current state of the account, call changes.getStartPageToken. Store and use this token in the initial call to changes.list.

To retrieve the current page token:

Java

StartPageToken response = driveService.changes()
    .getStartPageToken().execute();
System.out.println("Start token: " + response.getStartPageToken());

Python

drive/snippets/drive-v3/change_snippet/fetch_start_page_token.py
from __future__ import print_function

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def fetch_start_page_token():
    """Retrieve page token for the current state of the account.
    Returns & prints : start page token

    Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity
    for guides on implementing OAuth2 for the application.
    """
    creds, _ = google.auth.default()

    try:
        # create gmail api client
        service = build('drive', 'v3', credentials=creds)

        # pylint: disable=maybe-no-member
        response = service.changes().getStartPageToken().execute()
        print(F'Start token: {response.get("startPageToken")}')

    except HttpError as error:
        print(F'An error occurred: {error}')
        response = None

    return response.get('startPageToken')


if __name__ == '__main__':
    fetch_start_page_token()
# [End drive_fetch_start_page_token]

PHP

$response = $driveService->changes->getStartPageToken();
printf("Start token: %s\n", $response->startPageToken);

.NET

drive/snippets/drive_v3/DriveV3Snippets/FetchStartPageToken.cs
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Services;

namespace DriveV3Snippets
{
    // Class to demonstrate use-case of Drive's fetch start page token
    public class FetchStartPageToken
    {
        /// <summary>
        /// Retrieve the starting page token.
        /// </summary>
        /// <returns>start page token as String, null otherwise.</returns>
        public static string DriveFetchStartPageToken()
        {
            try
            {
                /* Load pre-authorized user credentials from the environment.
                 TODO(developer) - See https://developers.google.com/identity for
                 guides on implementing OAuth2 for your application. */
                GoogleCredential credential = GoogleCredential.GetApplicationDefault()
                    .CreateScoped(DriveService.Scope.Drive);

                // Create Drive API service.
                var service = new DriveService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive API Snippets"
                });

                var response = service.Changes.GetStartPageToken().Execute();
                // Prints the token value.
                Console.WriteLine("Start token: " + response.StartPageTokenValue);
                return response.StartPageTokenValue;
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else
                {
                    throw;
                }
            }
            return null;
        }
    }
}

Ruby

response = drive_service.get_changes_start_page_token
puts "Start token: #{response.start_page_token}"

Node.js

drive/snippets/drive_v3/change_snippets/fetch_start_page_token.js
/**
 * Retrieve page token for the current state of the account.
 **/
async function fetchStartPageToken() {
  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app

  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  const auth = new GoogleAuth({scopes: 'https://www.googleapis.com/auth/drive.appdata'});
  const service = google.drive({version: 'v3', auth});
  try {
    const res = await service.changes.getStartPageToken({});
    const token = res.data.startPageToken;
    console.log('start token: ', token);
    return token;
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}

Retrieve changes

To retrieve the list of changes for the currently authenticated user, send a GET request to the changes collection, as detailed in the List reference.

Entries in the changes collection are ordered in chronological order. That is, the oldest changes show up first. The includeRemoved and restrictToMyDrive query parameters of the changes collection decide whether the response should include removed or shared items, respectively.

Java

// Begin with our last saved start token for this user or the
// current token from getStartPageToken()
String pageToken = savedStartPageToken;
while (pageToken != null) {
  ChangeList changes = driveService.changes().list(pageToken)
      .execute();
  for (Change change : changes.getChanges()) {
    // Process change
    System.out.println("Change found for file: " + change.getFileId());
  }
  if (changes.getNewStartPageToken() != null) {
    // Last page, save this token for the next polling interval
    savedStartPageToken = changes.getNewStartPageToken();
  }
  pageToken = changes.getNextPageToken();
}

Python

drive/snippets/drive-v3/change_snippet/fetch_changes.py
from __future__ import print_function

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def fetch_changes(saved_start_page_token):
    """Retrieve the list of changes for the currently authenticated user.
        prints changed file's ID
    Args:
        saved_start_page_token : StartPageToken for the current state of the
        account.
    Returns: saved start page token.

    Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity
    for guides on implementing OAuth2 for the application.
    """
    creds, _ = google.auth.default()
    try:
        # create gmail api client
        service = build('drive', 'v3', credentials=creds)

        # Begin with our last saved start token for this user or the
        # current token from getStartPageToken()
        page_token = saved_start_page_token
        # pylint: disable=maybe-no-member

        while page_token is not None:
            response = service.changes().list(pageToken=page_token,
                                              spaces='drive').execute()
            for change in response.get('changes'):
                # Process change
                print(F'Change found for file: {change.get("fileId")}')
            if 'newStartPageToken' in response:
                # Last page, save this token for the next polling interval
                saved_start_page_token = response.get('newStartPageToken')
            page_token = response.get('nextPageToken')

    except HttpError as error:
        print(F'An error occurred: {error}')
        saved_start_page_token = None

    return saved_start_page_token


if __name__ == '__main__':
    # saved_start_page_token is the token number
    fetch_changes(saved_start_page_token=209)

PHP

# Begin with our last saved start token for this user or the
# current token from getStartPageToken()
$pageToken = $savedStartPageToken;
while ($pageToken != null) {
    $response = $driveService->changes->listChanges($pageToken, array(
        'spaces' => 'drive'
    ));
    foreach ($response->changes as $change) {
        // Process change
        printf("Change found for file: %s", $change->fileId);
    }
    if ($response->newStartPageToken != null) {
        // Last page, save this token for the next polling interval
        $savedStartPageToken = $response->newStartPageToken;
    }
    $pageToken = $response->nextPageToken;
}

.NET

drive/snippets/drive_v3/DriveV3Snippets/FetchChanges.cs
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Services;

namespace DriveV3Snippets
{
    // Class to demonstrate use-case of Drive's fetch changes in file.
    public class FetchChanges
    {
        /// <summary>
        /// Retrieve the list of changes for the currently authenticated user.
        /// prints changed file's ID
        /// </summary>
        /// <param name="savedStartPageToken">last saved start token for this user.</param>
        /// <returns>saved token for the current state of the account, null otherwise.</returns>
        public static string DriveFetchChanges(string savedStartPageToken)
        {
            try
            {
                /* Load pre-authorized user credentials from the environment.
                 TODO(developer) - See https://developers.google.com/identity for
                 guides on implementing OAuth2 for your application. */
                GoogleCredential credential = GoogleCredential.GetApplicationDefault()
                    .CreateScoped(DriveService.Scope.Drive);

                // Create Drive API service.
                var service = new DriveService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive API Snippets"
                });

                // Begin with our last saved start token for this user or the
                // current token from GetStartPageToken()
                string pageToken = savedStartPageToken;
                while (pageToken != null)
                {
                    var request = service.Changes.List(pageToken);
                    request.Spaces = "drive";
                    var changes = request.Execute();
                    foreach (var change in changes.Changes)
                    {
                        // Process change
                        Console.WriteLine("Change found for file: " + change.FileId);
                    }

                    if (changes.NewStartPageToken != null)
                    {
                        // Last page, save this token for the next polling interval
                        savedStartPageToken = changes.NewStartPageToken;
                    }
                    pageToken = changes.NextPageToken;
                }
                return savedStartPageToken;
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else
                {
                    throw;
                }
            }
            return null;
        }
    }
}

Ruby

# Begin with our last saved start token for this user or the
# current token from get_changes_start_page_token()
page_token = saved_start_page_token;
while page_token do
  response = drive_service.list_changes(page_token,
                                        spaces: 'drive')
  for change in response.changes
    # Process change
    puts "Change found for file: #{change.file_id}"
  end
  if response.new_start_page_token
    # Last page, save this token for the next polling interval
    saved_start_page_token = response.new_start_page_token
  end
  page_token = response.next_page_token
end

Node.js

drive/snippets/drive_v3/change_snippets/fetch_changes.js
/**
 * Retrieve the list of changes for the currently authenticated user.
 * @param {string} savedStartPageToken page token got after executing fetch_start_page_token.js file
 **/
async function fetchChanges(savedStartPageToken) {
  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app

  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  const auth = new GoogleAuth({scopes: 'https://www.googleapis.com/auth/drive.readonly'});
  const service = google.drive({version: 'v3', auth});
  try {
    let pageToken = savedStartPageToken;
    do {
      const res = await service.changes.list({
        pageToken: savedStartPageToken,
        fields: '*',
      });
      res.data.changes.forEach((change) => {
        console.log('change found for file: ', change.fileId);
      });
      pageToken = res.data.newStartPageToken;
      return pageToken;
    } while (pageToken);
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}

The retrieved changes collection may or may not contain a nextPageToken. If the nextPageToken is present, it may be used to gather the next set of changes. If the nextPageToken is not present, the client application should store the nextStartPageToken in the collection for future use. With the page token stored, the client application is prepared to query again for changes in the future.

Using push notifications

Use the changes.watch method to subscribe for updates to the change log. Notifications do not contain details about the changes. Instead, they indicate that new changes are available. To retrieve the actual changes, poll the change feed as described in Retrieve changes.