Webservice API

Overview

Normally the web pages of Enhydris are good if you are a human; but if you are a computer (a script that creates stations, for example), then you need a different interface. For that purpose, Enydris offers an API through HTTP, through which applications can communicate. For example, http://openmeteo.org/db/stations/d/1334/ shows you a weather station in human-readable format; http://openmeteo.org/db/api/Station/1334/ provides you data on the same station in machine-readable format.

Note

The Webservice API has been implemented using django-piston, but in the future we may change that to tastypie or to django-rest-framework.

The Webservice API is a work in progress: it was originally designed in order to provide the ability to replicate the data from one instance to another over the network. It was later extended to provide the possibility to create timeseries through a script. New functions are added to it as needed.

Client authentication

Some of the API functions are provided freely, while others require authentication. An example of the latter are functions which alter data; another example is data which are protected and need, for example, a subscription in order to be accessed. In such cases of restricted access, HTTP BASIC authentication is performed.

Note

Using piston.authentication.HttpBasicAuthentication with apache and mod_wsgi requires you to add the WSGIPassAuthorization On directive to the server or vhost config, otherwise django-piston cannot read the authentication data from HTTP_AUTHORIZATION in request.META. See: WSGI+BASIC_AUTH.

Generic API calls

Similarly to Django’s dumpdata management command, the Webservice API usually returns a JSON file with the requested objects, including all the fields that the dumpdata command exports. This means that the files produced by the Enhydris API can be used with Django’s loaddata management command to load data to an empty instance.

All of these API calls are accessible under the /api/ url after which you just fill in the model name of the model you want to request. For example, to request a JSON file containing all the stations you must provide the following url http://base-address/api/Station/. The same goes for the rest of the enhydris models (e.g. /api/Garea/, /api/Gentity/ etc). There is also the ability to request only one object of a specific type by appending its id in the url like this: http://base-address/api/Station/1000/.

See the data model reference for information on the models.

Station information and lists

There are also some more calls which provide station details in a more human readable format, including a station’s geodata which may be used by 3rd party application to incorporate the displaying of enhydris stations in their maps. These API calls reside under the /api/Station/info/ url and are similar to the ones above. If you do not specify any additional parameters, you get information for all Stations hosted in Enhydris and if you want the details for a specific station, you just need to append its id to the end of the url like above (eg /api/Station/info/1000). See models.Gentity and models.Station for a description of the meaning of the fields.

There is also another feature which enables users to request a sublist of stations by providing the station ids in a comma separated list by using the /api/Station/info/list url. This call supports only the POST method and the comma separated list must be given under the varible name station_list. For example:

curl -X POST -d "station_list=10001,10002,10003" http://openmeteo.org/db/api/Station/info/list/

Creating new time series

At the time of this writing the only writeable service is the creation of new time series. To do this, you POST /api/Timeseries/; you must pass an appropriate csrf_token and a session id (you must be logged on as a user who has permission to do this), and pass the data in an appropriate format, such as JSON. This is an example:

from urllib2 import build_opener, HTTPCookieProcessor, Request
import cookielib
import json

BASE_URL = 'http://openmeteo.org/db/'
USERNAME = 'my_username'
PASSWORD = 'my_password'
EXISTING_TIMESERIES_ID = 42

# Get a csrf token and login
cookiejar = cookielib.CookieJar()
opener = build_opener(HTTPCookieProcessor(cookiejar))
s = opener.open(BASE_URL + 'accounts/login/').read()
opener.addheaders = [('X-CSRFToken', cookie.value)
                    for cookie in cookiejar if cookie.name == 'csrftoken']
data = 'username=%s&password=%s' % (USERNAME, PASSWORD)
opener.open(BASE_URL + 'accounts/login/', data)

# Read an existing time series, and create a new one that has
# different remarks.
fp = opener.open('%sapi/Timeseries/%d/'
                                    % (BASE_URL, EXISTING_TIMESERIES_ID))
j = json.load(fp)
j[0]['fields']['remarks'] += "This time series rocks!"
fp = opener.open(Request('%sapi/Timeseries/' % (BASE_URL),
    data = json.dumps(j), headers = { 'Content-type': 'application/json' }))
response_text = fp.read()
new_id = int(response_text)

print "The time series was created; its id is %d" % (new_id,)

Timeseries data and GentityFile

At http://base-address/api/tsdata/id/ (where id is the actual id of the timeseries object) you can get the timeseries data in text format.

At http://base-address/api/gfdata/id (where id is the actual id of the GentityFile object) you can get a GentityFile.