Low-latency notification of Dropbox file changes

Posted by Steve Marx on November 04, 2013

Today we're introducing a new endpoint to the Core HTTP API called longpoll_delta. This new endpoint uses HTTP long polling to notify the caller when files have changed within a Dropbox user's account. This endpoint is already used by the Sync API on iOS and Android to notice changes as soon as they happen.

The new endpoint works in conjunction with the existing delta endpoint. When you call delta, you get back a set of changes as well as a cursor, which you pass with your next call to delta to indicate that you only need changes that occurred after that cursor. Typically, delta is used by polling periodically (generally every five minutes or so) for changes.

The new longpoll_delta call lets you avoid periodic polling and achieve low-latency change notification. longpoll_delta accepts a delta cursor and blocks until there are new changes (or a timeout is reached). When the call returns, you can call immediately delta to retrieve those changes.

The following sample code uses the new longpoll_delta endpoint together with delta to print updates to the console every time a file is created, modified, or deleted in Dropbox. Note that longpoll_delta isn't yet available in the Python SDK, so I'm calling it "by hand" using Kenneth Reitz's excellent Requests library. Hopefully this code gives you a feel for how the new endpoint is used:

import dropbox
import time
import requests

app_key = '<YOUR APP KEY>'
app_secret = '<YOUR APP SECRET>'

flow = dropbox.client.DropboxOAuth2FlowNoRedirect(app_key, app_secret)

print 'Go here and "allow": %s' % flow.start()
code = raw_input('Paste in your authorization code: ').strip()

access_token, _ = flow.finish(code)

client = dropbox.client.DropboxClient(access_token)

cursor = None
while True:
    result = client.delta(cursor)
    cursor = result['cursor']
    if result['reset']:
        print 'RESET'

    for path, metadata in result['entries']:
        if metadata is not None:
            print '%s was created/updated' % path
        else:
            print '%s was deleted' % path

    # if has_more is true, call delta again immediately
    if not result['has_more']:

        changes = False
        # poll until there are changes
        while not changes:
            response = requests.get('https://api-notify.dropbox.com/1/longpoll_delta',
                params={
                    'cursor': cursor,  # latest cursor from delta call
                    'timeout': 120     # default is 30 seconds
                })
            data = response.json()

            changes = data['changes']
            if not changes:
                print 'Timeout, polling again...'

            backoff = data.get('backoff', None)
            if backoff is not None:
                print 'Backoff requested. Sleeping for %d seconds...' % backoff
                time.sleep(backoff)
                print 'Resuming polling...'

For more information, read the full documentation for longpoll_delta, and let us know on the developer forum if you have any feedback!