Google provides a Google Health extension to the Google Data Python client library that helps connect to and use the Health Data API. In addition to providing some background on the capabilities of the Health Data API, this guide provides examples for interacting with the API using the Python client library. If you're interested in understanding more about the underlying protocol used by the Python client library to interact with the Health API, please see the protocol guide. For help setting up the client library, see the article on Getting Started with the Google Data Python Client Library.
This document is intended for programmers who want to write Python applications that interact with Google Health. The following instructions assume some knowledge of building, deploying, and running Python console/web applications.
The Google Data Python Client Library includes extensions to most Google Health-specific objects to make the service easier to use.
The Atom XML in a feed or entry is mapped to corresponding class in the Python library. For example, the
<atom:feed> element and <atom:entry> element correspond to the
gdata.health.ProfileFeed and gdata.health.ProfileEntry classes, respectively.
This client library is by no means the only way of connecting to and using the Google Health API. If you're interested in reading more about the underlying protocol that this library uses, see the Developer's Guide which discusses the raw protocol.
Google Health extends the Google Data feeds with elements from the ccr namespace. A user's entire Google Health
profile is stored in the Continuity of Care Record. This CCR data corresponds to an
instance of the class gdata.health.Ccr.
The Google Health APIs utilizes Google Accounts for authentication, so if you have a Google account you are all set. Otherwise, you can create a new account.
To use the Python client library, you'll need Python 2.0+ and the modules listed on the DependencyModules wiki page. After downloading the client library, a general introduction to the Python Client Library is available in the article Getting Started with the Google Data Python Library.
To include the examples in this guide into your own code, you'll need the following import statement:
import gdata.health import gdata.health.service
You will also need to setup a HealthService object, which represents a client connection (with authentication) to the
Health API.
client = gdata.health.service.HealthService(source='yourCo-yourAppName-v1')
To setup your HealthService to work with /h9, use:
client = gdata.health.service.HealthService(source='yourCo-yourAppName-v1', use_h9_sandbox=True)
The source argument is optional and should follow the format: company-applicationname-version.
It's recommended to include this parameter for logging purposes.
Note: The rest of the guide assumes you've created a HealthService in the variable client.
Use ClientLogin authentication if your client is a standalone, single-user "installed" client
(such as a desktop/console application). Once you have created a HealthService for either /h9 or
/health, call the gdata.service.ClientLogin() method with the user's credentials to authenticate your client.
client.ClientLogin('user@gmail.com, 'pa$$word')
For more information about ClientLogin authentication, including sample requests and responses, see the Authentication for Installed Applications documentation.
Note: As described in the ClientLogin documentation, the authentication request may fail
and issue a CAPTCHA challenge. If you want Google to display and handle the CAPTCHA challenge, then send the user to
https://www.google.com/accounts/DisplayUnlockCaptcha?service=health (rather than to the CAPTCHA-handling
URL given in the Authentication for Installed Applications documentation).
Using AuthSub, users can grant your web application access to their Google Health profile. Both AuthSub and
OAuth are the recommend means to connect with Google Health
because each token is directly linked to a specific profile in the user's account. Unlike other Google Data APIs, it is required that all requests from your application be digitally signed.
This means that you must either use OAuth, or request initial AuthSub tokens with the secure=1 parameter. Using AuthSub with secure=0 tokens is
limited to the H9 Developer's Sandbox during development.
Both Google Health (/health) and the H9 Developer's Sandbox (/h9)
use their own AuthSub handlers. When generating the link to the AuthSub approval page, you can specify a handler
by passing its URL as the keyword argument request_url to gdata.service.GenerateAuthSubRequestUrl().
Tip: When beginning development, it's recommended to
request an AuthSub token with next=http://localhost and secure=0. If you're ready to test
with your own domains, follow the steps in the
Domain Registration & Signing Requests of the Getting Started Guide.
The following code generates the correct URL to the H9 AuthSub approval page using secure=0 tokens:
import gdata.service
def GetH9AuthSubUrl():
next = 'http://localhost'
scopes = ['https://www.google.com/h9/feeds/']
session = True
secure = False
auth_sub_url = gdata.service.GenerateAuthSubRequestUrl(
next, scopes, hd='default', secure=secure, session=session,
request_url='https://www.google.com/h9/authsub')
# permission=0 allows for sending notices.
# permission=1 allows for sending notices and reading a users profile.
permission = '1'
auth_sub_url += '&permission=' + permission
return auth_sub_url
print GetH9AuthSubUrl()
Important: If your application will read data from a user's profile, be sure to include the
permission=1 query parameter. See Requesting a single-use token in the protocol guide
for details on supported query parameters.
Google Health requires that all API requests be digitally signed, and as a result, the process for generating the AuthSub URL
changes slighly if you're requesting secure=1 tokens for either /h9 or /health . You can no longer
use http://localhost as the next URL.
The following code generates the correct URL to the Google Health AuthSub approval page using secure=1 tokens:
import gdata.service
def GetHealthAuthSubUrl():
next = 'http://www.example.com/health.pyc'
scopes = ['https://www.google.com/health/feeds/']
session = True
secure = True
auth_sub_url = gdata.service.GenerateAuthSubRequestUrl(
next, scopes, hd='default', secure=secure, session=session,
request_url='https://www.google.com/health/authsub')
# permission=0 allows for sending notices.
# permission=1 allows for sending notices and reading a users profile.
permission = '1'
auth_sub_url += '&permission=' + permission
return auth_sub_url
print GetHealthAuthSubUrl()
Note: Before you can interact with Google Health, you must register your application with Google and Google Health. Please see Domain Registration & Signing Requests in the Getting Started Guide.
After a successful authorization from AuthSub, the user returns to your next URL with a single-use token
appended to the end. For example, http://www.example.com/health.pyc?token=singleUseToken.
The following code demonstrates how to instantiate a service object to use the H9 Sandbox, extract a single-use token from the URL, and upgrade the token to a long-lived session token:
import cgi parameters = cgi.FieldStorage() single_use_token = parameters['token'] client = gdata.health.service.HealthService(source='yourCo-yourAppName-v1', use_h9_sandbox=True) client.auth_token = single_use_token client.UpgradeToSessionToken()
For /health, the process is slightly different because of the requirement of signed requests.
import gdata.auth
f = open('/path/to/yourRSAPrivateKey.pem')
rsa_key = f.read()
f.close()
current_url = 'http://' + req.hostname + req.unparsed_uri
single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url, rsa_key=rsa_key)
client = gdata.health.service.HealthService(source='yourCo-yourAppName-v1')
client.UpgradeToSessionToken(token=single_use_token)
It's important to pass in your RSA private key before upgrading the single-use token. After you have a session token, use the
UpgradeToSessionToken() method to set the token in the HealthService object. Subsequent API requests will
use your private key and session token to sign requests.
For help creating a private key and public certificate, see Creating a self-signing X.509 public certificate in the Getting Started Guide.
It's suggested that your application provide users a way to revoke access to their linked profile. The Python client library
contains the gdata.service.RevokeAuthSubToken() method for revoking an AuthSub/OAuth token.
The following code revokes the user's session token:
client.RevokeAuthSubToken()
For detailed information on authenticating to the Google Health service, see these additional resources:
Note: This feature is only available (and necessary) when using ClientLogin.
Since ClientLogin requires a profile ID with each of its feeds, applications will want to query the profile/list first in order
to select the appropriate profile. The profile list feed returns Atom entries corresponding to each profile in the user's
Google Health account. The profile ID is returned in the <atom:content> and the profile name in the
<atom:title> element.
To execute a query against the profile/list feed, use the gdata.health.service.GetProfileListFeed() method
or construct a gdata.health.service.HealthProfileListQuery():
profile_list_feed = client.GetProfileListFeed() for entry in profile_list_feed: profile_id = entry.GetProfileId() profile_name = entry.GetProfileName() print '%s, %s' % (profile_name, profile_id)
The profile feed allows you to retrieve a CCR document describing a user's health information. Each profile is encapsulated inside of an
Atom <atom:entry>.
The process of extracting data from the profile requires two steps, sending a query and iterating through the resulting feed.
The following example shows how to query the profile feed and print the CCR for
each Atom entry. It assumes the user has authenticated and you have instantiated a HealthService object as client.
profile_feed = client.GetProfileFeed() for entry in profile_feed.entry: print entry.ccr
The gdata.health.HealthProfileQuery class helps simplify constructing a query URL based on the parameters you set.
This example queries the user's profile:
query = gdata.health.service.HealthProfileQuery(params={'digest': 'true'})
profile_feed = client.GetProfileFeed(query=query)
entry = profile_feed.entry[0] # we only have one entry with digest=true
Using the digest=true parameter, the user's entire CCR will be consolidated and returned in a single Atom entry.
When using ClientLogin, you'll need to provide a profile id to query:
profile_feed = client.GetProfileFeed(profile_id='12345')
The gdata.health.Ccr class has helpers to extract particular sections of the CCR.
You can take advantage of this method by invoking Get<CATEGORY>s, where CATEGORY
is one of the supported categories found in the reference guide.
The following snippet builds on the previous examples.
# entry.ccr.GetMedications()
# entry.ccr.GetImmunizations()
# entry.ccr.GetAlerts()
# entry.ccr.GetResults()
# entry.ccr.GetProblems()
# entry.ccr.GetProcedures()
# Example of extracting and printing the names of a user's medications
medications = entry.ccr.GetMedications()
for med in medications:
name = med.FindChildren('Product')[0].FindChildren('ProductName')[0].FindChildren('Text')[0]
print name.text
See the CCR reference for more information on elements.
You can also use the HealthProfileQuery to construct queries that return a subset of the user's CCR data, instead of their entire profile.
For example, you can construct a query that only returns condition data. See categories
in the reference guide for more examples of possible queries.
Only medication data in a single Atom entry:
query = gdata.health.service.HealthProfileQuery(params={'digest': 'true'}, categories=['medication'])
profile_feed = client.GetProfileFeed(query=query)
Medication or condition data in multiple Atom entries:
query = gdata.health.service.HealthProfileQuery(categories=['medication|condition']) profile_feed = client.GetProfileFeed(query=query)
A more complex query that returns the top 10 medications with 2 items each:
params = {'digest': 'true',
'grouped': 'true',
'max-results-group': '10',
'max-results-in-group': '2'}
query = gdata.health.service.HealthProfileQuery(params=params)
query.categories.append('medication')
profile_feed = client.GetProfileFeed(query=query)
A full list of supported query parameters is available in the query parameters section of the Health API Reference Guide.
Individual posts to the register feed are known as notices. Notices are sent from third-party applications to inform the user of a new event. With AuthSub/OAuth, notices are the single means by which your application can add new CCR information into a user's profile. Notices can contain plain text (including certain XHTML elements), a CCR document, or both. As an example, notices might be sent to remind users to pick up a prescription, or they might contain lab results in the CCR format.
Notices can be sent by calling the gdata.health.service.SendNotice() method.
This example sends a notice to the user's profile using AuthSub:
ccr = '''<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">
<Body>
<Problems>
<Problem>
<DateTime>
<Type><Text>Start date</Text></Type>
<ExactDateTime>2007-04-04T07:00:00Z</ExactDateTime>
</DateTime>
<Description>
<Text>Aortic valve disorders</Text>
<Code>
<Value>410.10</Value>
<CodingSystem>ICD9</CodingSystem>
<Version>2004</Version>
</Code>
</Description>
<Status><Text>Active</Text></Status>
</Problem>
</Problems>
</Body>
</ContinuityOfCareRecord>'''
created_entry = client.SendNotice('Subject line of your notice', body='Notice <b>body</b>.',
content_type='html', ccr=ccr)
problem = created_entry.ccr.GetProblems()[0].FindChildren('Description')[0].FindChildren('Text')[0]
print "Added the problem '%s' to the user's profile." % (name.text,)
Note: A simple message that does not contain CCR data can be sent using
client.SendNotice('Subject line', body='Notice body').
If you're using ClientLogin, be sure to include a profile id:
created_entry = client.SendNotice('Subject line of your notice', body='Notice <b>body</b>.',
content_type='html', ccr=ccr, profile_id='yourProfileID')
Please see the list of supported notice body html elements.