Skip to content

How to get access to the API

Overview

To be able to use the discover.swiss API you must register as a developer and we must onboard you as a partner. We will give you access to the test environment without the need to become a partner, but once you get productive we must talk to each other.

  1. Go to Get the Developer Portal and sign up for an account
    developer.discover.swiss
  2. The Team will get a notification and assign you a subscription for the test environment.
    Although there are several API's you can choose from, with a test subscription you can access all of them
  3. Once you get feedback from us you can access your subscription keys in your profile in the developer portal.

Info

If you have any questions get in contact with us and mail to support@discover.swiss.

Access control

It is important to know who's calling on our API and since we do not provide a UI the application provider (you) must provide the correct identification tokens to get access to the API and the data. All these tokens are sent in Request Headers.

Identification levels

identification levels

Based on the subcription-key we can identify the partner and the application which is calling. The Partner information we need to filter data especially in the profile service.
-> Ocp-Apim-Subscription-Key header

We do provide a (technically) sessionless REST API. But to support the requirement of "as-a-guest" orders and profiles without log-in (authentication) we use profile-tokens which work similar to OAuth2 token but are available without authentication. To identify 1 profile and can be used as a session token on the web or stored in a client app to persist the connection to the current profile.
-> ProfileToken header

When a client application offers authentication to a user using our Azure Active Directory B2C, the guest can log in with different social media providers or user/password. In this case, you can use standard OAuth2 or openID connect flows to log the user in and provide the Authorization Bearer token to access the API.
-> Authorization header

In the future, we will distinguish between users who logged in with a social account where only the E-Mail is verified or for example with SwissPass or swissID where we can rely on the identity of the user. This identification level is stored and retrievable in the person response.

The following identification levels exist:

  • Guest
  • EmailNotVerified
  • EmailVerified

Request Headers

Language

Accept-Language: {iso-2 language code}

All APIs accept Accept-Language header with two letter ISO (en, de, fr, it) code to request content in different languages. If a language is not available or the header is missing it will serve the default language which is German.

Subscription

Ocp-Apim-Subscription-Key: {subscription key}

You will need to include the appropriate subscription key you can get in the developer portal in EVERY request to API.

Profile Header

ProfileToken: {jwt}

Without a valid ProfileToken or an Authorization header it is not possible to access the profile or marketplace services.

  1. Make a request to /token endpoint to get a profile token token and store it locally similar to a session cookie.
  2. In the token response you will get a refresh token as well. This token can be used to refresh the profileToken after (or better just before) it expires.

Info

In the MVP it was necessary to always add a ProfileToken. But for easier handling in Apps which use the profile service only with authenticated users we changed the behavior so that an Authorization header only is sufficient too. If both are present they need to fit the same profile.

Note

The desired maximal lifetime of the refresh token can be set in the token-request as well. Not in all scenarios the same lifetime of the refresh token makes sense. For client apps a longer lifetime is better so the user is still "logged in" even after several months of not using the App. But on a web application this is a more serious security issue and the refresh token should only be valid for the duration of an expected user "session".

Authorization

Authorization: Bearer {jwt-token}

We use Azure Active Directory B2C as an identity management service and standard OAuth2 which means you need to include the Authorization Header sending the Bearer {accessToken} in every request. This token identifies the user and is used to select the profile to work with (not query parameters). For more details see Quickstart: Call Azure Active Directory B2C

Best practices

Where to store the API-Subscription Key

Generally, subscription keys used on the client can be "stolen" easily.

On the topic of how and where the API Key is stored in the app, there are different opinions. Our key must be handled in the same way as any API key from Google or DropBox or somebody.

Here are a few ideas: https://stackoverflow.com/questions/14570989/best-practice-for-storing-and-protecting-private-api-keys-in-applications

And here a discussion by Google: https://cloud.google.com/endpoints/docs/openapi/when-why-api-key

If you compile the subscription key in the app it is very hard to change it in case it gets stolen and misused. If you get the key from your server (your own API). It can be changed easily and without a new release. In the end, however, it also requires an access authorization to your API and the problem will only be postponed. If you communicate only through a proxy on your server with the discover.swiss api, the key can't get stolen, but you need to maintain a "proxy", request get slower and we (discover.swiss) do not get useful tracking information from the client directly which can be used for monitoring and DOS detection.

The subscription key is only enough to use the API. But that does not give you any external data, you can only use the services and reload the data you save yourself.

At some point in the future discove.swiss may charged on the traffic and then you would pay the traffic of the key thief as well.

Parameter

Project

A project will be assigned to you which contains all the data requested by your specifications. For example, special entities "Events, tours, POI, etc.". Moreover, the entities can be located in a particular region or desired structure of administrative areas. It is important to include the assigned project code as the query parameter.

For more information see Infocenter service endpoints.

Paging

Always expect a second page

The data deliverd by our Api (except search) is saved in Azure Cosmos DB which is a distributed document database designed to always perform and answer in a meaningful way. To be able to do so it splits up queries into multiple pages of results when:
Data volume – Each page of query results is capped at 4 MB. (the select parameter in our api does not affect this)
Execution time – Every query execution is capped at 5 seconds. Even if you run a query and results aren’t available yet, you will always get a response back from Azure Cosmos DB after 5 seconds.
Performance - There are also cases where the query engine returns results in multiple pages because it’s better for query performance. The query engine may also split up results due to throttling.

These 2 parameters are used to control and handle the paging:

top

This is desired pagesize of the client. In most cases this is what you get. But if you query top=10000 you will most likely NOT get 10000 results but several pages. The top value is overridden by Cosmos DB.

default: top = 10
top = -1 instructs the Cosmos DB to choose the ideal pagesize -> this should be used to download all data

continuationToken

This parameter is needed to get to the next page of data. In order to apply it correctly, there are some steps that need to be done. After calling a specific endpoint, you will get in the response the property nextPageToken which you must send with the next page request.

Info

To use the nextPageToken manually (for example in Postman) you need to perform the follwoing steps with it.
Normally this should be done automatically if the nextPageToken is used by a programming language.

The \" must be replaced with "

"nextPageToken": "{\"token\":\"+RID:~eSdPALbCSmYKAAAAAAAAAA==#RT:1#TRC:10#ISV:2#IEO:65567#QCF:4#FPC:AgEAAAAyAAHAAPwxQP8fIUD/7xJAbdv+bRNArw/of/ezI0D/7+7//2MRQO//EUD2/zFA9/9BQAEA\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}",
So the provided token will look like this:

{"token":"+RID:~eSdPALbCSmYKAAAAAAAAAA==#RT:1#TRC:10#ISV:2#IEO:65567#QCF:4#FPC:AgEAAAAyAAHAAPwxQP8fIUD/7xJAbdv+bRNArw/of/ezI0D/7+7//2MRQO//EUD2/zFA9/9BQAEA","range":{"min":"","max":"FF"}}
Then you must encode it using URL encoder before using it in the query.

%7B%22token%22%3A%22%2BRID%3A%7EeSdPALbCSmYKAAAAAAAAAA%3D%3D%23RT%3A1%23TRC%3A10%23ISV%3A2%23IEO%3A65567%23QCF%3A4%23FPC%3AAgEAAAAyAAHAAPwxQP8fIUD%2F7xJAbdv%2BbRNArw%2Fof%2FezI0D%2F7%2B7%2F%2F2MRQO%2F%2FEUD2%2FzFA9%2F9BQAEA%22%2C%22range%22%3A%7B%22min%22%3A%22%22%2C%22max%22%3A%22FF%22%7D%7D

Last update: March 11, 2022 13:29:54