An easy-to-use Python wrapper for the Open311 API.
Pull request Compare This branch is 105 commits behind codeforamerica:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


An updated Open311 API Python wrapper that was built to be as absolute user-friendly and easy-to-use as possible. Many of the design decisions made will reflect these qualities.


This is still a work in progress, but you can git clone this repo and run python install to check out the current progress.

The wrapper is also available through PyPi -- but installing through pip is currently not advised until it is in a production-ready state.

pip install three



If you have an Open311 API key that you always intend to use, rather than initializing the Three class with it each time, you can set an OPEN311_API_KEY environment variable on the command line.


Otherwise, you can initialize the class with your API key and endpoint.

>>> from three import Three
>>> t = Three('', api_key='my_api_key')


By default, Three will configure a URL without a specified schema to use HTTPS.

>>> t = Three('')
>>> t.endpoint == ''


The default format for the Three wrapper is JSON -- although not all Open311 implementations support it. This is done mainly for easy-of-use (remember, that's the over-arching goal of the Three wrapper). You can, however, specifically request to use XML as your format of choice.

>>> t = Three('', format='xml')
>>> t.format == 'xml'



After you've initialized your Three class, you can readjust its settings with the configure method. You can also switch back to the orgininal settings with the reset method.

>>> from three import Three
>>> t = Three('', api_key='SECRET_KEY')
{'service': 'data'}

>>> t.configure('', format='xml'
...             api_key='SF_OPEN311_API_KEY')
{'SF': {'service': 'data'}}

>>> t.configure(api_key='ANOTHER_API_KEY')
>>> # Switch back to original settings.
... t.reset()


In order to use the Open311 service discovery, simply invoke the discovery method.

>>> t = Three('')
>>> t.discovery()
{'service': {'discovery': 'data'}}

Sometimes, however, service discovery paths differ from service and request URL paths -- in which case you can pass the specified URL to the discovery method as an argument.

>>> t.discovery('')


To see the available services provided by an Open311 implementation, use the services method.

>>> t = Three('')
{'all': {'service_code': 'info'}}

You can also specify a specific service code to get information about.

{'033': {'service_code': 'info'}}


To see available request data, use the requests method.

>>> t = Three('')
>>> t.requests()
{'all': {'requests': 'data'}}

Most Open311 implementations support page and page_size parameters.

>>> t.requests(page_size=50)
{'total': {'of': {'50': 'requests'}}}

>>> t.requests(page=2, page_size=50)
{'next': {'50': 'results'}}

You can also specify a specific service code.

>>> t.requests('123')
{'123': {'requests': 'data'}}

Other parameters can also be passed as keyword arguments.

>>> t.requests('456', status='open')
{'456': {'open': {'requests': 'data'}}}


If you're looking for information on a specific Open311 request (and you have it's service code ID), you can use the request method.

>>> t = Three('')
>>> t.request('12345')
{'request': {'service_code_id': {'12345': 'data'}}}


Sometimes you might need to programmatically create a new request, which is what the post method can be used for. NOTE: the Open311 spec states that all POST service requests require a valid API key.

>>> t = Three('', api_key='SECRET_KEY')
>>>'123', name='Zach Williams', address='85 2nd St',
...        description='New service code 123 request.')
{'new': {'request': 'created'}}


Each service request ID can be tracked with a temporary token. If you need to find the service request ID and have the request's token, you can use the token method.

>>> t = Three('')
>>> t.token('12345')
{'service_request_id': {'for': {'token': '12345'}}}