After migrating the data, which was a complex task, and implementing various custom features, we went live. At the beginning of 2021, Zurich Tourism launched its new website. Based on a first version of an open data API allowing partners to find up-to-date data on their website.

Designing the API in Drupal 9

The API was based on Drupal 7, which has now been replaced. The customers’ requirements were clear: we had to replicate the API as closely as possible and implement it in Drupal 9. The data structure has to support, which is why the API in Drupal 7 was a custom implementation.

We wanted to use as many of the Drupal Community's code as possible when developing the new open data API. This helps to support maintainability and keep the quality high, and of course, to save money.

There are different approaches to building this type of API and, as is often the case, all of the approaches have pros and cons.

Approach 1: Using existing normalisation modules

Drupal has many existing modules that fulfil a similar requirement, such as the core module JSON:API. These modules are implemented very generically, meaning that, as far as possible, all of the entities’ fields are normalised. However, if you require a completely different structure or an additional logic for certain fields, you have to make adaptations. Furthermore, these modules often provide many more functions than will be used, which reduces the flexibility provided and makes the system less clear as there are so many excess functions.

Approach 2: Custom normalisation in combination with the RESTful Web Services module

The RESTful Web Services module is also a Drupal core module. This module can be used to integrate REST APIs into a Drupal project without much effort. Implementing the open data API with this module requires a lot of time because you have to take care of the entire normalisation process by yourself. However, it is a very flexible option as you also implement everything yourself. The extra flexibility it provides also makes it more likely to be implemented in a clear and sustainable way.


We achieve normalisation using a normaliser class, which transforms Drupal entities into model classes. The model classes represent types from The following diagram shows the process, using a node-type place entity as an example. In this case, the model type corresponds to LocalBusiness.

By using this model, the mapping and transformation processes are separated from one another. And a toArray function provides full control of how data is serialised.

The open data interface in practice

Partners can synchronise their data by using the open data REST endpoint.

The overview page at provides categories of places and accommodations. So, if you want to pull the data for all restaurants from, for example, you can simply enter the category ID using a query parameter.

This is how Hotel Schweizerhof Zurich gets its data for the page