The webstore provides an API that aims to make tabular data available as
hypermedia resources following the REST paradigm. This means having a
trade-off between the perfect way to represent tables and adhering to a
resource-centric view of web media.

Core Resource:

/{user-name}/{db-name}/{table-name}

Table is the central exposed resource (databases are created on-the-fly
and may in fact not actually be separate databases, depending on the
backend vendor (e.g. we can use PostgreSQL Schemas to partition the
table space and don’t actually need to create distinct databases).

For JSON, a special query parameter _callback=function can be added
to specify a JSONP padding. Be aware that webstore also supports Cross-Origin
Resource Sharing (CORS) by allowing access to all HTTP methods from any host.
This can make accessing resources very easy, as simple XMLHTTPRequest calls can
be used. CORS is not supported by all browsers, though, and thus JSONP still
has a use case.

Since JSON dictionaries don’t have any order associated with them, webstore
offers a secondary JSON encoding, called JSONtuples. This format can both be
written and read and provoked by setting the application/json+tuples content
type or by appending the .jsontuples suffix to a path.

The generated output will contain a dictionary with two entries: keys for an
ordered listing of the column names and data, which contains a list of
tuples, each a row of data ordered in the same order as given by the keys.

Sometimes it is useful to know the number, names and types of columns in
the database. To get such schema information, access the ‘schema’
subresource:

GET/{user-name}/{db-name}/{table-name}/schema

For reference, one can also address each row of a given table at the
following location (with {line-number} set to the auto-increment __id__
column):

GET/{user-name}/{db-name}/{table-name}/row/{line-number}

Another useful function is the distinct subcollection: for any column in
a table, this will return all values of the column exactly once with a
count of its occurences (ie. this is actually a GROUP BY query):

If a user name is known, a listing of all their databases is available
at:

GET/{user-name}

This listing is based on a directory listing for the SQLite backend and
prone have errors if the directory structure is modified outside of the
application. Further, generating this listing may be non-trivial for
cases in which another backend is used.

The request must have an appropriate Content-type set. The entire
request body is treated as payload. The desired table name is either
given as a query parameter (see above) or by posting to a non-existent
table:

POST/{user-name}/{db-name}/{table-name}

If application/json is specified as the content type, webstore will
expect a list of single-level hashes:

If the submitted data is in format that supports types (e.g. JSON),
database columns are created according to the type of the first row
in the data (e.g. a float JSON field will generate a FLOAT column in
SQL). If the value of a column is null in the first row, a VARCHAR
column is created. When new data is added, types are enforced on the
incoming data. Values that can not be converted to the designated
type will result in an HTTP 400 (Bad Request) error.

Webstore can execute raw SQL statements coming from a request. Such
statements have to be submitted in the body of a PUT request to the
database with a content type of ‘text/sql’:

PUT/{user-name}/{db-name}

If the user has ‘delete’ authorization, any SQL statement can be
executed, including potentially destructive operations such as
INSERT, UPDATE and DELETE. Otherwise, only read operations - i.e. the
SELECT statement - can be run.

If you need to rely on SQL parameter binding or database attachment
(see below), you can submit a JSON envelope instead of sending raw
SQL strings. This expects the same type of put request with a content
type of application/json and a body in the following format:

params can be either a list or dictionary of values to be bound in
the query, depending on whether you’re using positional or named parameters.

Database attachment is a special feature of SQLite that will allow
queries across several SQLite files. If you attach a database with a
given alias, its tables will be available with the alias prefix. If
no alias is specified, the database name will be used. If you don’t specify
a user, the same user as for the main database will be assumed.

Note. All SQL queries are somewhae´t database-specific, so you need to know
whether you are speaking to a PostgreSQL or SQLite-backed webstore.

When SQLite is used as a backend to webstore, the whole database file
(not a dump!) can be retrieved by calling the database endpoint either
with the ‘.db’ suffix or the ‘Accept:’ header set to ‘application/x-sqlite3’:

The webstore itself does not maintain information about registered users,
although users are a necessary, first-class element of the system. To still
support users, authentication is delegated to another system or performed
based on rules. The preferred authentication backend is CKAN, which is used by
directly interacting with the platform’s database. This means CKAN credentials
can be used as long as they include a valid CKAN api key (when authenticating
against CKAN replace the “user:password” string with your api key).

Authentication can be used via a basic auth header. In the future, support for
API keys and OAuth is planned.

Authorization is based on simple rules and can be configured via the config
file (AUTHORIZATION). A few common policies are this: