GeoWebDNS is a service inspired by DNS and reverse-geocoding. Given a lat/long, what is the URI of the standardized API, protocol, or file for a given service namespace (eg 311 services). The GeoWebDNS servers would be decentralized and redundant, automatically mirroring one-another and propagating out changes much like DNS servers. All that the client would need to do would be to send the lat/long and request the URI for a given namespace. The server would then have to look at the polygon that contains that lat/long for that service namespace and return the URI associated with it.

This model is meant to work in concert with a Service Discovery spec such as that being used with Open311. A good deal of other work is also occurring in the service discovery space for data catalogs and APIs.

Reference Implementation


The service will use HTTP. It exists at one URL; in this document we will use the example as the API endpoint.

A query uses query string arguments:

lat: The latitude. (WGS84)

long: The longitude. (WGS84)

Note: should lat/long be one value? This makes it easier to add new query types. It might be like: point=100.1234%2035.1234 (i.e., space-separated), or just comma-separated (which doesn’t need to be quoted).

type: The type of object to be returned; this will be a string/URI. This argument may be present multiple times, returning jurisdictions with any of the given types.

A query then looks like:

GET /service?lat=100.1234&long=35.1234&type=

The only coordinate system supported is WGS 84 (latitude/longitude).

In this example might be the URI identifying 311 jurisdictions. URIs act similar to how an XML namespace works; it is an opaque string, but by convention maps to a URL describing the type.

Note: should we accept a level of confidence, using the same scale as presented in the Google geocode API? A low confidence might mean we do a more fuzzy search.

The response is a JSON object like:

Content-type: application/json

{"results": [
    {"type": "",
     "uri": "",
     "name": "San Francisco 311",
     "kml": ""

The return result JSON is an object with one key, "results" (other keys may be added later, for example to specifying caching semantics or paging). The "results" key has a value of a list of all results matching this location.

Each result is an object with several keys:

"type": The “type” of the jurisdiction. If you specify multiple type=... in your query, you can use this to determine which specific type this result is.

"uri": The destination URL.

Note: should there be a kind of “id URL” in addition to this more explicit URL? For instance, if there are multiple APIs, they might each have a different “type” but still represent the same basic entity. These could all have the same id URI (e.g., http://sfgov/311) but still different specific endpoints.

"name": The name of the entity, a readable string.

Note: should this be translated or translatable? E.g., {"en_US": "San Francisco 311 Information", "es": "San Fransisco 311 Informacion"} ?

"kml": This optional response value points to a KML document describing the entity.

Note: would it make sense to inline GeoJSON?

No results

If there are absolutely no results, it will return {"results": []} with a 404 status code.


If the request is malformed, a 400 Bad Request response is given. The text of this response will be a readable description of the problem.

The readable format is defined by the Content-Type header, but will probably be HTML. Clients that cannot or do not want to present HTML can strip all tags and will get a description that is still readable.

Note: are there any predictable errors? E.g., a lat/long that is impossible?


Source code for the reference implementation is at

To get started, run:

    $ wget     $ chmod +x     $ ./ geowebdns-app

This product uses SilverLining for deployment. The stack consists of PostGIS, GeoAlchemy, WebOb.

To bootstrap a database, you can run these scripts:

   $ cd src/geowebdns/imports    $ mkdir data    $ ./    $ export CONFIG_PG_SQLALCHEMY=postgres://postgres:password@localhost/geowebdns  # use your postgres password here    $ ./ --commit