NAV
Shell PHP Go

Introduction

Welcome to the Open Ticket API documentation. This site explains some important, overarching concepts use by our API. After you have read this information, you can find a list of available endpoints and detailed documentation for each in our Swagger Docs .

Authentication

Open Ticket uses OAuth2 for authentication using the Authorization Code grant. This grant type ensures no user credentials are shared with the client owner, while still allowing the owner’s application(s) to access the API.

It is expected of the reader to be familiar with the basic user-company-whitelabel structure used by Openticket and OAuth. This document only provides a bare-bones overview on how to connect to the Openticket services.

For this description we have the following definitions:

Requesting tokens in principle is a very simple and straightforward process consisting of the following steps:

  1. Request access to a user’s account by redirecting the user to a specific endpoint. Redirect to https://auth.openticket.tech/token/authorize)
  2. Wait for a callback containing a nonce.
  3. Use the provided nonce to request a token. Request at https://auth.openticket.tech/token
  4. Use the issued tokens to place requests.

It is assumed the application which needs access to the Openticket systems can store the issued access (and refresh) tokens securely!

Scopes

Currently, scopes are unused, any token can be used to access any service. Scopes will be introduced in the future to enable a more nuanced approach to requesting access. Tokens issued are likely to remain valid after this change. When the introduction of a scope will invalidate tokens, affected client owners will be contacted.

Creating a client

An OAuth client is required when seting up a connection to the Openticket systems. Creating clients is a simple process. Open the dashboard and navigate to: Company settings -> OAuth Clients. Only two fields are required:

  1. Name: A descriptive name will be presented to the user.
  2. Redirect URL: The URL the user will be redirected to after approving or declining access.

After providing these two fields, a set of credentials will be given. An identifier, and a secret. Note, ensure that the secret is actually kept secret and is never made public, this includes keeping the secrit out of git repositories. Any token issued by a client having a leaked secret will be invalidated!

These credentials will be needed to request a token.

Requesting a token

As stated previously, requesting a token consists of a few steps:

  1. Requesting authorization to access a users’s account.
  2. Receive a nonce, which can be used to request a token (once).
  3. Send some authenticated requests.
  4. When the token expires, request further tokens when needed.

Each of these 4 steps will be described seperately,

Requesting authorization

Redirecting the user, do not forget to set/replace all settings accordingly

// Make sure state is actually usable and dynamically generated, not a constant!
var state = "RANDOM STRING"
http.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
	uri := fmt.Sprintf("https://auth.openticket.tech/token/authorize?client_id=%v&redirect_url=%v&state=%v&response_type=code",
		os.Getenv("OAUTH_CLIENT_ID"),
		os.Getenv("OAUTH_CLIENT_REDIRECT"),
		state)

	http.Redirect(w, r, uri, http.StatusSeeOther)
})

http.ListenAndServe(":8080", nil)
curl -XGET "https://auth.openticket.tech/token/authorize?client_id=$OAUTH_CLIENT_ID&redirect_uri=$OAUTH_CLIENT_REDIRECT&response_type=code&state=RANDOM_STRING"
// Using Laravel
Route::get('/redirect', function (Request $request) {
    $request->session()->put('state', $state = Str::random(40));

    return redirect('https://auth.openticket.tech/token/authorize?' . http_build_query([
        'client_id' => env('OAUTH_CLIENT_ID', ''),
        'redirect_uri' => env('OAUTH_CLIENT_REDIRECT', ''),
        'response_type' => 'code',
        'state' => $state,
    ]));
});

To start the process of connecting your application to users, the following information is needed:

  1. OAuth client identifier: as provided after creating the OAuth client.
  2. OAuth client redirect url: as setup when creating the OAuth client.
  3. State: A (random) identifier, your application uses to identify the response. When redirecting this state is included.

To start the request, issue a redirect to https://auth.openticket.tech/token. Examples on how to redirect are provided on the right.

Handling authorization response

// Using Laravel
Route::get('/callback', function (Request $request) {
    $state = $request->session()->pull('state');

    throw_unless(
        strlen($state) > 0 && $state === $request->state,
        InvalidArgumentException::class
    );

    $response = (new GuzzleHttp\Client)->post('https://auth.openticket.tech/token', [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => env('OAUTH_CLIENT_ID', ''),
            'client_secret' => env('OAUTH_CLIENT_SECRET', ''),

            'redirect_uri' => env('OAUTH_CLIENT_REDIRECT', ''),
            'code' => $request->code,
        ],
    ]);

    return json_decode((string) $response->getBody(), true);
});
# Shells do not receive requests. Nothing to do here.
http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
	resp, _ := http.PostForm("https://auth.openticket.tech/token", url.Values{
		"grant_type":    {"authorization_code"},
		"client_id":     {os.Getenv("OAUTH_CLIENT_ID")},
		"client_secret": {os.Getenv("OAUTH_CLIENT_SECRET")},
		"redirect_url":  {os.Getenv("OAUTH_CLIENT_REDIRECT")},
		"code":          r.URL.Query()["code"],
	})

	io.Copy(w, resp.Body)
})

http.ListenAndServe(":8080", nil)

Resulting in the following response

{
    "token_type": "Bearer",
    "expires_in": 259200,
    "access_token": "THE_ACTUAL_TOKEN",
    "refresh_token": "REFRESH_TOKEN",
    "refresh_token_expires_in": 31535999,
    "info": {
    	...
    }
}

Info contains information on the user, the company, and the whitelabel. The user info also includes the roles of this user

After the user has authenticated and either approved or declined your application accessing the data, your callback url will be called with the following query parameters:

code is not a token, and cannot be used to authenticate requests to the Openticket systems! It can only be used to request a token! Note, each code can only be used once and expires quickly. To request a new token for a previously authorized user, a different request exists which is described below.

A token can be requested, by crafting a request containing the code parameter and the OAuth Client credentials. When issueing a token, not only the token is returned, but also information on the user associated with the token is returned. Not only user information, but also information on the user’s company and whitelabel are included.

Token response

A token contains the following fields:

As can be seen from the expires_in and refresh_token_expires_in fields, neither the access_token nor the refresh_token are valid indefinetly, but expire at some point. In general two statements on these TTLs will hold:

  1. refresh_token_expires_in is much greater than expires_in, to ensure access to the Openticket systems is maintained even when access is only incidental.
  2. The TTL’s are constant.

Though these are true in general, they cannot be relied upon to hold forever. When needed, these values can be changed without any prior notice. Though TTLs will not be changed retroactively for previously issued tokens.

Issuing requests

curl -H "Authorization: Bearer $ACCESS_TOKEN" https://auth.openticket.tech/user/me
// Using a guzzle client
$response = $client->request('GET', 'https://auth.openticket.tech/user/me', [
    'headers' => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer '.$accessToken,
    ],
]);

echo $response->getBody();
r, _ := http.NewRequest(http.MethodGet, "https://auth.openticket.tech/user/me", nil)
r.Header["Authorization"] = []string{"Bearer: " + accessToken}
resp, _ := http.DefaultClient.Do(r)

bts, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(bts))

Resulting in the following response

{
	"guid": "6e26d618-354b-11eb-9322-acde48001122",
	"default_company_id": "6eac75a2-354b-11eb-9322-acde48001122",
	"whitelabel_id": "6eea7dc0-354b-11eb-9322-acde48001122",
	"name": "Mart Pluijmaekers",
	"email": "[email protected]",
	"phone": null,
	"created_at": "2011-12-13T11:12:13+02:00",
	"updated_at": "2020-12-13T14:15:16+01:00",
	"deleted_at": null
}

Using the access_token retrieved in the previous request, requests can be authenticated by including a header called Authorization. The contents of this header should contain the token type (“Bearer”) and the access_token separated by a single space.

Almost all requests require the authorization header. All available API’s and endpoints can be found here .

When a token is (no longer) valid, the API should respond with a 401 status code.

Refreshing a token

// Using Laravel
$refreshToken = $request->session()->pull('refresh_token');
$response = (new GuzzleHttp\Client)->post('https://auth.openticket.tech/token', [
    'form_params' => [
        'grant_type' => 'refresh_token',
        'refresh_token' => $refreshToken,

        'client_id' => env('OAUTH_CLIENT_ID', ''),
        'client_secret' => env('OAUTH_CLIENT_SECRET', ''),
    ],
]);

echo $response->getBody();
curl -XPOST -F "grant_type=refresh_token" -F "refresh_token=$REFRESH_TOKEN" -F "client_id=$OAUTH_CLIENT_ID" -F "client_secret=$OAUTH_CLIENT_SECRET" https://auth.openticket.tech/token
resp, _ := http.PostForm("https://auth.openticket.tech/token", url.Values{
	"grant_type":    {"refresh_token"},
	"refresh_token": {refreshToken},

	"client_id":     {os.Getenv("OAUTH_CLIENT_ID")},
	"client_secret": {os.Getenv("OAUTH_CLIENT_SECRET")},
})

bts, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(bts))

Resulting in the following response

{
    "token_type": "Bearer",
    "expires_in": 259200,
    "access_token": "NEW_ACCESS_TOKEN",
    "refresh_token": "NEW_REFRESH_TOKEN",
    "refresh_token_expires_in": 31535999,
    "info": {
    	...
    }
}

Access tokens expire, by default, after three days. When a token has expired it can no longer be used. To reduce the need for re-authorizing a refresh_token is provided with the access_token. refresh_tokens can only be used to request new access_tokens, not to access the services! By default, a refresh_token expires in 365 days.

When an access_token has expired, a new token can be requested using the refresh_token grant-type. When requesting a new token using the refresh token grant type a new access and refresh token are issued. A refresh_token can only be used once!.

The response structure is equal to requesting a token using the authorization_code grant.

Notes

Openticket imposes some limits on tokens: