Getting Started

Hi 👋 and welcome to M3! We are excited about your interest in the data and our work. This page is meant to take you through setting everything up until your very first API request. An API, if you're unfamiliar with that term, is a standardized service for software to interact with each other (it's actually an abbreviation for Application Programming Interface). We offer our own M3 API as a REST infrastructure which is kind of the default for such endeavors with and for (social) sciences.

In the following, here's our four-step guide to get going.

Step 1: Register

You need to register for our API. It's free but it's necessary. That's because M3 is meant for researchers and particularly those within academic institutions. Hence, to get started you need to be granted access (which is based upon inspecting your institution). The process itself is easy: You go to the M3 API login page, click register, and enter the necessary details. Please use your institutional email address and verify it directly after registration (you'll get an email notification for that).

Now you can already work with the API. That is, you can read the documentation and experiment with the profile endpoint.

For the remainder of features, however, the M3 team needs to grant you appropriate permissions. We do so upon individual inspection (i.e., depending on your institution). We are automatically informed about your registration and typically grant access within 1-2 working days. In case you experience any issues or are in a real hurry, please reach out to us.

Step 2: Authenticate & Authorize

Once you have been granted adequate permission, you can interact with the M3 API. For that, you will need to authenticate yourself. If you are working with the API via the documentation page, authentication happens via the online log-in form. However, this will likely not remain the way how you work with the API. Instead, at one point, you will want to transfer to a programming language such as Python or R. For that, authentication works via a standard protocol called OAuth2.

OAuth2 builds on the principle of tokens. That's because code and everything related to authentication usually find its ways into the open internet, hence revealing your password(s). Instead, you use your credentials from registration (step 1) to get an access token which is a mathematical representation of a key that works for a specific amount of time and certifies that you are who you say you are. It hence allows the bearer of a token to access the API and is sometimes also referred to as a bearer token. Second, alongside your access/bearer token you need to get so-called refresh tokens which allow you to, well, refresh your access/bearer tokens before they expire. Ultimately, this allows you to control for how long your access is valid (i.e., until you stop renewing using your refresh token).

How to make that work?

  1. Start by getting your access token. Call https://login.m3.ifkw.lmu.de/auth/realms/m3-api/protocol/openid-connect/token and send your username and password along. This process also requires a client ID (m3-api), a grant type (password), and--depending on your used library--a scope (openid). You can send everything via a POST request (form-encoded via x-www-form-urlencoded, if you need to be specific).
    curl -X 'POST' \
      'https://login.m3.ifkw.lmu.de/auth/realms/m3-api/protocol/openid-connect/token' \
      --data '{"username": "your@email.ai", "password: "a_v3ry_s3cr3t_password", "client_id": "m3-api", "grant_type": "password"}'
    

    What you'll get is a JSON string that includes your access token, some meta information, and a refresh token:
    {
      "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqX05iV3FBUjVzWUppUW1EM1l2eGZtVmotcklnR0ZKTEdWcWdlbTJWZHBNIn0.eyJleHAiOjE3MTg5NzIzMzAsImlhdCI6MTcxODk3MjAzMCwianRpIjoiYWIxMzZmZDctZGUxNi00M2I0LTk5NWEtM2ExMzNlODVlZjc0IiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5tMy5pZmt3LmxtdS5kZS9hdXRoL3JlYWxtcy9tMy1hcGkiLCJhdWQiOlsibTMtYXBpIiwiYWNjb3VudCJdLCJzdWIiOiI4NjQ2ZDE1YS03MzZhLTQzNTUtOTNkOC1lZTU0ZDM1M2E5YzAiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJtMy1hcGkiLCJzZXNzaW9uX3N0YXRlIjoiMmQ5NGY3M2UtOTQ1YS00M2IwLWFiY2MtNTlmZjkxNjc0ZmViIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwczovL2FwaS5tMy5hdC5ibHVlc2hvZS5pbyJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJkZWZhdWx0LXJvbGVzLW0zLWFwaSIsInVtYV9hdXRob3JpemF0aW9uIiwiZ3JhZmFuYS1hZG1pbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Im0zLWFwaSI6eyJyb2xlcyI6WyJTdXBlcnVzZXJzIiwiU3RhZmYiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjJkOTRmNzNlLTk0NWEtNDNiMC1hYmNjLTU5ZmY5MTY3NGZlYiIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiTWFyaW8gSGFpbSIsInByZWZlcnJlZF91c2VybmFtZSI6ImhhaW1AaWZrdy5sbXUuZGUiLCJnaXZlbl9uYW1lIjoiTWFyaW8iLCJmYW1pbHlfbmFtZSI6IkhhaW0iLCJlbWFpbCI6ImhhaW1AaWZrdy5sbXUuZGUifQ.jLzibw-cgvQ4WrOrx8aRfhYZuc_KvYnR_noE9WXmltou6LI1zhNksYRyNRtxogm2iRjm0JDCkt4ZXoB6QsMdE2c8dKEXLThXPxEZ9y1fy6k5FM5bzb0XIaYkHdzNMqkU2dGWngtsIv9EsKGJGtgXLDRjY7pkiyg1k_rcZek6fRBD5j9KziCmlFZu8f57wTYprjgjgxVRoksolXNpYbFzAaHciEyO6LgXnfC33AZ2zzEXYqPip8gxDjj0o6aKrT5LFG0KqezSHeaaLA-AC8IYazJQzx9kcjyQJ2ca_7K3eezJVpvBaaW3lQXtidC5PMstr80Eb9iNi1rpTQ5qg6UDTg",
      "expires_in": 300,
      "refresh_expires_in": 1800,
      "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhMmIxMmVhNy1iNzIxLTRiYTUtYTBkMy02YTIxMTRjODk0N2MifQ.eyJleHAiOjE3MTg5NzM4MzAsImlhdCI6MTcxODk3MjAzMCwianRpIjoiNWMxNDg4NTgtZGE4ZC00Y2I3LThkOGQtNTFmOWYyMDY1ODk0IiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5tMy5pZmt3LmxtdS5kZS9hdXRoL3JlYWxtcy9tMy1hcGkiLCJhdWQiOiJodHRwczovL2xvZ2luLm0zLmlma3cubG11LmRlL2F1dGgvcmVhbG1zL20zLWFwaSIsInN1YiI6Ijg2NDZkMTVhLTczNmEtNDM1NS05M2Q4LWVlNTRkMzUzYTljMCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJtMy1hcGkiLCJzZXNzaW9uX3N0YXRlIjoiMmQ5NGY3M2UtOTQ1YS00M2IwLWFiY2MtNTlmZjkxNjc0ZmViIiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiMmQ5NGY3M2UtOTQ1YS00M2IwLWFiY2MtNTlmZjkxNjc0ZmViIn0.FJkwUBP8AunvpByHPc3TpK00L6Yn5CSG8CbxLCCPCGA",
      "token_type": "Bearer",
      "not-before-policy": 0,
      "session_state": "2d94f73e-945a-43b0-abcc-59ff91674feb",
      "scope": "profile email"
    }
    
  2. Use the access token for your API requests. You only need to include a header into your requests named Authorization and provide it with the bearer keyword along with your actual token (Bearer [token]). For the API to work as expected, you also need to signal it that you are accepting JSON responses only. Here is an example request, querying your own profile information.
    curl -X 'GET' \
      'https://api.m3.ifkw.lmu.de/api/v1/profile/' \
      -H 'Authorization: Bearer [access_token]' \
      -H 'Accept: application/json'
    
  3. To refresh your access/bearer token, simply call https://login.m3.ifkw.lmu.de/auth/realms/m3-api/protocol/openid-connect/token again with your current refresh token, the client ID, and a slightly adjusted grant type (refresh_token).
    curl -X 'POST' \
      'https://login.m3.ifkw.lmu.de/auth/realms/m3-api/protocol/openid-connect/token' \
      --data '{"refresh_token": "[refresh_token]", "client_id": "m3-api", "grant_type": "refresh_token"}'
    

Obviously, you might not want to do this whole step via cURL and you do not need to. Here are rudimentary Python and R scripts to accomplish the same thing.

import requests

# get your access/bearer and initial refresh token
access_response = requests.post("https://login.m3.ifkw.lmu.de/auth/realms/m3-api/protocol/openid-connect/token",
                                data={"username": "your@email.ai",
                                      "password": "a_v3ry_s3cr3t_password",
                                      "client_id": "m3-api",
                                      "grant_type": "password"})
access_token = access_response.json()["access_token"]
refresh_token = access_response.json()["refresh_token"]

# query the API
api_response = requests.get("https://api.m3.ifkw.lmu.de/api/v1/profile/",
                            headers={
                                "Authorization": f"Bearer {access_token}",
                                "Accept": "application/json"
                            })
print(api_response.json())

# refresh your bearer token
bearer_response = requests.post("https://login.m3.ifkw.lmu.de/auth/realms/m3-api/protocol/openid-connect/token",
                                data={"refresh_token": refresh_token,
                                      "client_id": "m3-api",
                                      "grant_type": "refresh_token"})
access_token = bearer_response.json()["access_token"]
refresh_token = bearer_response.json()["refresh_token"]

Step 3: Try out the API

Next, you want to scroll through our API documentation and see what it has to offer for you. You can also start by looking at our website-provided list of media outlets or our list of surveys.

Step 4: Scale up

Finally, now that you know how things work, it is time to tell you that others have also and already thought about how to properly embed OAuth2 into their applications. As such, there's libraries and packages out there that do some of aforementioned lifting for you. For example, in Python, you can use the python-keycloak library (Keycloak is the software that handles the OAuth2 protocol on M3's side). Use the KeycloakOpenID class and its token method to get things to work with M3 (also see the documentation). In R, you can use the httr package which offers an oauth2.0_token function (see their documentation for further details).