Encoding and Field Formats

  • Character encoding must be in UTF-8
  • DateTime and Date fields will follow the ISO 8601 subset as per the W3c note except when specified otherwise. created and updated timestamps should provide seconds and a UTC offset. Other times, for example within schedules, should provide only hours and minutes.
  • When a time zone has to be specified explicitly (in a timezone field, rather than as part of an ISO timestamp), it must use a time zone name from the TZ Database
  • Geospatial data will follow existing standards, using the standard EPSG:4326 (latitude/longitude) spatial reference system:
  • Links will use the following rules
    • In XML, links will use the a link tag. The syntax is as in Atom, though the tag is not placed within an Atom namespace. The type of link is in the rel attribute, and the URL in the href attribute.
    • In JSON, as a rule, link attribute names have _url added to the end. There are some exceptions; see the JSON section below.
  • Open511 IDs are globally unique identifiers that take the form jurisdiction-id/resource-id. For example, my.city.gov/84738. The first segment of the event ID is the jurisdiction ID. The second segment is a string ID that must be unique within its jurisdiction. It can contain the characters a-zA-Z0-9_.-. The two segments are separated with a /.

REST

Like many open data APIs, Open511 will roughly follow the REST design. REST does not provide fixed constraints but best practices that will be used by the API:

  • Uniform interface: use of HTTP to provide uniform methods and content negotiation features
  • Stateless: each request is independent from the previous one which simplifies implementation for both server and client
  • Resource-based: each concept becomes a resource that can be accessed via an URL
  • Hypermedia: representations contain links to other resources

The Open511 specification does not provide a fixed URL layout for the resources it describes. Resources are linked together (starting from the discovery resource), and clients may follow these links to obtain the data they seek. For resources with an id field, it is a best practice to include this value in the resource URL, often as the final component of the path, so that the road event with ID mycity.gov/52 has a URL at (for example) /events/mycity.gov/52.

Format negotiation

Open511 supports two serialization formats (XML and JSON). Implementations that wish to provide data in other formats may also do so via this mechanism.

Clients indicate their format preference via one of two mechanisms:

  • The Accept HTTP header. HTTP allows clients to list several possible content types in order of preference (and so implementors are encouraged to use a library to parse the header) though the simplest use of the header is to specify a single preferred type: Accept: application/json. Implementations must support the application/json and application/xml types.
  • A URL parameter named format, which accepts ?format=json and ?format=xml. If provided, it takes precedence over the Accept header.

Implementations are free to determine their default serialization. Responses must include a Content-Type header set to the appropriate content type.

Versioning

Each major version of this specification is identified with a version string. The current version string is v1. When (and only when) a backwards-incompatible change is made to the specification, the version string will change.

Clients may request responses conforming to a specific Open511 version via one of two mechanisms:

  • An Open511-Version header, with the desired version string as a value, e.g. Open511-Version: v1
  • A URL parameter named version, e.g. ?version=v1. If provided, it takes precedence over the Open511-Version header.

When a client requests a version the server is unable to provide, the server may either respond using its default version, or may attempt to return the closest supported version to what the client is requesting; the specifics of this behaviour are left to implementors to decide.

Pagination

Endpoints returning lists of resources should be paginated. Page information is provided in a structure called pagination at the top level of the response:

FieldTypeDescription
offsetInteger

Mandatory

The index within the full list of results, counting from 0, of the first result on the current page.

On the first page, offset will always be 0. If 20 results are shown per page, offset will be 20 on the second page, 40 on the third page, etc.

nextLink

Optional

Link pointing to the next page of results. Must be omitted if there is no next page.

previousLink

Optional

Link pointing to the previous page of results. Must be omitted if there is no previous page, i.e. offset is 0.

Endpoints returning lists must also accept a limit URL parameter defining the maximum number of events to return in a single paginated response.

The default value for limit (how many items to include on a page if no parameter is provided) is up to individual implementors. Likewise, implementors may want to enforce a maximum value for this parameter in order to conserve server resources, so that a ?limit=10000 query would still return only e.g. 500 events per page. However, if such a maximum is implemented, it should not be lower than 500.

Serialization

Open511 supports XML and JSON serializations. The examples available on each resource page are usually the best way to understand the structure of the serializations; some non-exhaustive guidelines follow.

A web-based validator, commandline validation tool, and XML schema are available to test the validity of your documents. As well, the web validator and commandline tool can convert between the XML and JSON serializations. This conversion tool may be useful for implementors who choose to store data in one serialization and convert on-demand to the other.

XML

  • Documents are contained within an open511 tag, which includes a version attribute. If relative links are used within resources, an xml:base attribute is encouraged: <open511 version="v0" xml:base="http://mycity.gov/">.
  • Objects generally appear within a container tag with a plural name: event within events, area within areas, etc.
    <open511 ...>
      <events>
        <event>...</event>
        <event>...</event>
      </events>
      <pagination>...</pagination>
      <link ... />
      <link ... />
    </open511>
  • Links use a link tag, with the field name in the rel attribute and the URL in the href attribute: <link rel="self" href="/api/events/" />

XML geographies

Geospatial fields use GML version 3.2.1. This is a very complex format, and so we use only a small subset, such that there is only one way to express a given geography.

Tools may be able to generate output that fits within this subset. For example, in PostGIS 2.x, a recommended open-source geospatial database, use ST_AsGML(3, geom::geometry, 15, 23), where geom is the name of your geography or geometry column. But if the GML your preferred tool generates doesn’t fit within this subset, the geometries involved are simple enough that constructing the GML manually should still be fairly simple.

All GML geometries must include the srsName="urn:ogc:def:crs:EPSG::4326" attribute. Coordinates must be in latitude, longitude order. Note that this is the reverse of the axis order that GeoJSON uses.

Open511 supports the following geometry structures:

  • <gml:Point srsName="urn:ogc:def:crs:EPSG::4326">
      <gml:pos>45.5261 -73.5877</gml:pos>
    </gml:Point>
  • <gml:LineString srsName="urn:ogc:def:crs:EPSG::4326">
      <gml:posList>45.523 -73.592 45.524 -73.59 45.523 -73.592</gml:posList>
    </gml:LineString>
  • <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326">
      <gml:exterior>
        <gml:LinearRing>
          <gml:posList>40 -73 41 -73 41 -74 40 -74 40 -73</gml:posList>
        </gml:LinearRing>
      </gml:exterior>
      <gml:interior>
        <gml:LinearRing>
          <gml:posList>40.2 -73.2 40.8 -73.2 40.8 -73.8 40.2 -73.8 40.2 -73.2</gml:posList>
        </gml:LinearRing>
      </gml:interior>
    </gml:Polygon>
    <!-- note that most polygons will have only an exterior ring -->
  • <gml:MultiPoint srsName="urn:ogc:def:crs:EPSG::4326">
      <gml:pointMember>
        <gml:Point>
          <gml:pos>45.5261 -73.5877</gml:pos>
        </gml:Point>
      </gml:pointMember>
      <gml:pointMember>
        <gml:Point>
          <gml:pos>45.4 -73.6</gml:pos>
        </gml:Point>
      </gml:pointMember>
    </gml:MultiPoint>
  • MultiLineString and MultiPolygon geometries are similar, with gml:lineStringMember and gml:polygonMember tags

 

JSON

  • In XML, links use <link>. In JSON, links are generally normal attributes, but _url is appended to the field name (which is in the rel attribute in XML). For example
    <link rel="description" href="http://example.net/description.html"/>
    becomes
    "description_url": "http://example.net/description.html"
    But there are some exceptions:
    • Links with rel="self" are named simply url in JSON.
    • In the attachments section of events, where links are expected to include several attributes, links are serialized as JSON objects.
      <link rel="related" title="Detour map" type="application/pdf" length="200345" href="http://my.city.gov/trafic/advisory/39473/com.pdf" hreflang="en" />
      becomes
      {
        "type": "application/pdf",
        "length": 200345,
        "url": "http://my.city.gov/trafic/advisory/39473/com.pdf",
        "title": "Detour map",
        "hreflang": "en"
      }
    • The grouped_events section of events is simply an array: ["/events/mycity.gov/4877", "/events/mycity.gov/8897"]
  • A meta structure has to be contained in each response. This meta structure contains the format version number. It is contained directly in the first level structure.
    {
      ...
      "meta": {
          "version": "v0"
      }    
    }
  • Lists expressed in XML in a <things><thing /></things> kind of structure are expressed via JSON arrays:
    {
      ...
      "events": [
        { "headline": "Road closed", ...},
        { "headline": "Bridge closed", ...}
      ],
      ...
    }

Bandwidth Optimization and Conditional Requests

Since the API will likely be used by mobile applications, bandwidth optimization is important. Servers are encouraged to support the following features:

Field Selection

Another bandwidth-saving feature is allowing the clients to request only a subset of the fields on a resource. This feature is optional for server implementations: servers may choose to simply ignore all fields parameters and always return all fields.

A fields URL parameter contains a comma-separated list of field names, e.g. ?fields=id,current_speed,updated. Only fields matching the provided names will be returned.

Link fields can be specified using either the XML rel value (self, jurisdiction) or the JSON name (url, jurisdiction_url).

Field selection takes place at the resource level -- top-level fields like pagination can never be filtered out. Within a resource, every field name in a nested structure must be provided. For example, to get the name of an event's roads, you must be include roads,road,name in the fields parameter.

Authentication and Encryption Mechanisms

In the spirit of open data, we encourage implementors to make their API available for unauthenticated read access. For write access (e.g post reports) or implementors who need to enforce authentication on GET requests, this section provides guidelines.

For authentication, users must use API keys (tokens). That token must be accepted via an api_key querystring parameter, because that’s sometimes the only mechanism that works in-browser. However, because querystring authentication is awkward with hypermedia APIs like Open511 (links to other resources don’t actually work until the client appends authentication parameters to the URL), implementations should also accept HTTP Basic authentication, where the API key is provided as the username and the password is left blank.

Encryption should be managed by the regular HTTP layer. The only encryption accepted is HTTPS. Implementations using authentication are encouraged to require HTTPS for all requests in order to protect API keys.

Error Handling

When an error is encountered, the response must have a 4xx or 5xx HTTP error code. Specifically:

  • The client request is badly formed, e.g. incorrect filter syntax: 400
  • The request requires authentication, but no API key was provided: 401. The error message should explain how to obtain an API key.
  • The request was for an individual resource URL, and that resource could not be found: 404. Note that for an empty filtered list resource — e.g. all events with road_name Boardwalk, but no such events exist — the appropriate response is with status code 200 and an empty <events /> container within the standard response body.
  • The server rate-limits requests, and the client has exceeded the rate limit: 429
  • The server has an internal problem: 500

Errors may be returned in text/plain, application/xml, or application/json. The minimum valid JSON error response is {"error": "message here"}. In XML, it's <open511 version="whatever"><error>message here</error></open511>.

Implementors may choose to add additional fields on top of that minimum. For example, {"error": "something bad happened", "internal_code": "HF8837"}.

Response Language

Open511 has the ability to support multiple languages. However, unilingual server implementations don't need to worry about anything here beyond ensuring that XML responses contain an appropriate xml:lang attribute.

Clients may specify language preferences in one of two ways

  • The Accept-Language HTTP header
  • The accept-language URL parameter can also be used, using the same syntax as the header, e.g. ?accept-language=en,pt. If provided, it takes precedence over the header.

In order to use the Accept-Language selector (either HTTP or URL parameter), the client provides a list of supported languages in order of priority. For example pt, en to get Portuguese before English. The language values accepted are specified in RFC 1766. For simpliciy, we recommend using the two-letter language-tag as defined by ISO-639-1

XML serializations must always contain xml:lang attributes to indicate the language(s) of the response. In XML, if no Accept-Language header or parameter is provided, then the server should return all the free-text data it knows about, regardless of language. This means that a single road event might contain <headline xml:lang="en">Bridge Replacement</headline><headline xml:lang="fr">Remplacement du pont</headline>. If either an Accept-Language header or accept-language parameter are present, however, the server must select a single language for each object returned. Take the example of a client with a language preference of fr, en requesting a list of events, all of which are available in English and some of which are additionally available in French. The server should return French versions of the events where it can, and use English for the rest. However, within a single event, all the free-text fields returned should be in the same language.

When returning JSON data, the server must always select a single language for each object returned (as in the example above). In JSON, if no Accept-Language header or parameter is provided, the server must choose a single default language. Multilingual Open511 implementations should also add a lang attribute to each serialized object, with the ISO language tag as a value. Unilingual implementations do not need to include this attribute.

Aggregation and Multi-Jurisdiction Support

The Open511 API is designed to support multi-jurisdiction servers (a server that provides data for several jurisdictions) and aggregation of data (a server that gathers information from other Open511 servers). The last feature is meant to simplify the work of clients. For example, a region can setup an aggregator for all the jurisdictions of the region, or a third party can, assuming each jurisdiction's license allows it, build a service that serves a province or a country.

For the client, these features should be fairly transparent. Unless a jurisdiction filter is used, endpoints return data from all jurisdictions mixed together.

Aggregators must not modify the data they return. In particular, all resource URLs ("self" links) must be unmodified, and so continue to point to the original server. The exception is resources with an updated field: this should be set to the first time at which that version of the resource was accessible via the aggregator's API, which is likely to be slightly later than the original updated value.

Cross domain requests

Open511 APIs must support cross-domain requests, via CORS, by including an Access-Control-Allow-Origin: * header in all responses to GET queries.

Custom fields

Some implementors might have specific requirements that aren’t supported by the existing Open511 fields. While we encourage implementors to stay within the specification if possible, we also provide guidelines for adding custom fields to a specific implementation.

In XML serializations, custom tags may be placed anywhere, but must belong to a separate XML namespace, e.g. <bus_number xmlns="http://my.city.gov/open511-extensions">. In JSON serializations, custom attribute names must begin with +, e.g. +bus_number.

Static vs. dynamic ("simple version")

The documented API includes several query parameters which require application code on the server. But implementors may choose to publish Open511 data without supporting these query parameters, in such a way that the API could be implemented via a folder of static files hosted by a standard web server. This provides fewer features to users, but should be easier to implement, particularly for smaller jurisdictions.

Static services are indicated as such via the service_type on the discovery resource: http://open511.org/services/events/ is the dynamic service, http://open511.org/services/events-static/ is the static version.

After that, the requirements for the service are exactly the same, except that options in headers and query-string parameters are ignored. Some of the specific implications of this for events:

  • Format and language negotiation are ignored; all Open511 data is XML
  • Only events with a status of ACTIVE are available