Authenticating with the TimeLog REST API

Introduction

This page will go through the various scenarios for obtaining an access token that can be used to access the TimeLog REST API. The authentication process is following the OAuth2 standard.

Overview

  • You need a valid API Key to send requests to the API endpoints. You can request your key by writing to support@timelog.com including details about company name, developer name, use case outline and a redirect URI to your app
  • The API has an access rate limit applied to it
  • The API will only respond to secured communication done over HTTPS
  • Response to every request is sent in JSON format
  • The request method (verb) determines the nature of action you intend to perform. A request made using the GET method implies that you want to fetch something from TimeLog, and POST implies you want to save something new to TimeLog
  • The API calls will respond with appropriate HTTP status codes for all requests

Authentication

The default process for obtaining an Access Token for the TimeLog REST API is using the OAuth2 Hybrid Flow.

Hybrid flow is a combination of the implicit and authorization code flow. In hybrid flow the identity token is transmitted via the browser channel and contains the signed protocol response along with signatures for other artifacts like the authorization code. After successful validation of the response, the back-channel is used to retrieve the access and refresh token.

This is the recommended flow for native applications that want to retrieve access tokens (and possibly refresh tokens as well) and is used for server-side web applications and native desktop/mobile applications.

Sample requests

You can use our Postman request collection to get started:

The OAuth2 flow

Step 1 Starting the authentication flow

You need to construct a authentication request (like below) that you can send the user to.

GET /connect/authorize?
    client_id={api_key}&
    scope=openid offline_access tlp&
    response_type=code id_token&
    redirect_uri=https://{your app callback URL}&
    nonce={random key for replay protection}&
    state={ramdon key for CSRF/replay protection}
Host: newlogin.timelog.com

(URL encoding removed, and line breaks added for readability)

Available scopes:

openid Required Required for completing the authentication
tlp Optional Used when your application needs to call any TimeLog REST API endpoints
offline_access Optional Used when your application wants to utilize refresh tokens to avoid repeatable asking the user to log in

Step 2 Open the link in a browser

If you are building a web application, simply direct the user the authentication request URI. If you are building a mobile application, open an inline browser and direct the user to the authentication request URI.

The user will be redirected to the redirect_uri included as part of the authentication request. For web applications, this is an endpoint in your application that may handle the next steps of the OAuth2 process. For mobile applications, you normally need to specify an intent-filter for Android apps or a URL Scheme for iPhone apps.

Step 3 Wait for the callback and extract the authentication code

You should expect a callback that looks like the example below (URL encoding removed, and line breaks added for readability).

GET /callback?
    code=e1d3e238e608e8e1db6036173460a87585117babf2676f3bb55d0d675c552392&
    id_token={lengthy JWT encoded string}&
    scope=openid tlp offline_access&
    session_state={string} HTTP/1.1
Host: localhost:5001

The essential part is the code parameter also referred to as the authorization code. This code can be exchanged for a access/refresh token pair using the /connect/token endpoint.

You can inspect the id_token parameter using a JWT decoder and verify that the nonce matches the one you sent in the authentication request.

Step 4 Exchange the authorization code for the token pair

You need to construct a token request (like below) that your app can use to request the access/refresh token pair.

POST /connect/token HTTP/1.1
Host: newlogin.timelog.com
Content-Type: application/x-www-form-urlencoded

    client_id={api_key}&
    client_secret={api_secret}&
    grant_type=authorization_code&
    code={authorization code}
    redirect_uri=https://{your app callback URL}

(URL encoding removed, and line breaks added for readability)

Expect the following JSON object back:

{
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyQkFEMzM5MTUwRDhERDA3M0U1MUVFNTQ0M0NCRjNCOTNCMTI2MkMiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJJcnJUT1JVTmpkQno1UjdsUkR5X081T3hKaXcifQ.eyJuYmYiOjE1MTYxMDQ0NjcsImV4cCI6MTUxNjEwNDc2NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoic2FtcGxlYXBwIiwibm9uY2UiOiJ6eGMiLCJpYXQiOjE1MTYxMDQ0NjcsImF0X2hhc2giOiJoeENpbG5adHo4SmhyUmZ4NmxsNGdnIiwic2lkIjoiODVjYmM0NTk3MjQ0YjBkMjlmMmQxMGVkNjhhMjNkZTkiLCJzdWIiOiJsb2NhbDo4MiIsImF1dGhfdGltZSI6MTUxNjEwMzUyMSwiaWRwIjoibG9jYWwiLCJhbXIiOlsicHdkIl19.EN3dFx91dcFoeGTHUEaXMFxn0BOCKu9TOIxbfblKHDIKOdqXJ7mUrgdN6pHBHSlbe2RthFhr1c8NLYj6pPJUH_2GM30Jeu_lPlqtioobbU8EfOGvNdMtjyTRGK9LGt8WxZsNrxrN85XEycwJ3izNha-2r0KbqSse8F3NfUstc5vxdgejWbzh4hnIJKfSRHNrctCFLxH_xaCH9motxtrGibgLft7t8GevXWtRmmm0Asc639xcMb7fXLG9htNDye6LhbMkQBszUgY0W5GPqBBVV0e8cHtyaW9GYg3zm4E7wNDaJCvfmP7dZe4zc16HNyzmxTwpajFh4TqvrGNAZ-X-bA",
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyQkFEMzM5MTUwRDhERDA3M0U1MUVFNTQ0M0NCRjNCOTNCMTI2MkMiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJJcnJUT1JVTmpkQno1UjdsUkR5X081T3hKaXcifQ.eyJuYmYiOjE1MTYxMDQ0NjcsImV4cCI6MTUxNjEwODA2NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJ0bHBhcGkiXSwiY2xpZW50X2lkIjoic2FtcGxlYXBwIiwic3ViIjoibG9jYWw6ODIiLCJhdXRoX3RpbWUiOjE1MTYxMDM1MjEsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsInRscGFwaSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.IprVwhRgBfZlKkxed5G1kagSMJLPrxHrNjukVRB2kPaTI61lZzW6MV8pxke2hlEhyCTYbx90EKIpc42bAm0SDX8wIm9GjvdPfQylOtGeRwENxKL8sVNWNPR8dyN-3-Qr-2QCxGY2FKjHgDVJ0kn1XPTf9yw5hXXOu0eS2jTIluAJVw3a6KkoNQcDh4BufyoqLmbe7FvaXb3Dx6zYGHvC4ED8GOVHzN2u2iCOZHu6o6NsBJ-5HV0pgS54Fjs9BTstgsF86dduBEPO5K3WAYZJokSh_dJ5FtSR4UBOvJvfXkk5Vi65BU_900GgHGyHICyAUao1mpO3RB_L1lXsFJ0LVw",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "7f44506257829e088723e63fb8d827b32d4f9277dff34490a64e2418d4584453"
}

Step 5 Determine the TimeLog API endpoint

Due to the nature of each TimeLog instance having its own URL, we provide an API endpoint for finding the endpoint associated with a given access token. Use a request constructed as below to fetch the details:

GET /api/ResolveUri HTTP/1.1
Host: newlogin.timelog.com
Authorization: Bearer {access_token}

Expect the following JSON object back:

{
    "url": "https://app4.timelog.com/soxdemo"
}

Step 6 Call the TimeLog API endpoint

Now you have all the pieces to start the interaction with the TimeLog REST API. You may access the API documentation for your specific TimeLog instance appending /for-now-an-unknown-url to the URL returned in step 4. For example:

https://app4.timelog.com/soxdemo/for-now-an-unknown-url

You may for example get a list of customers using a request like below:

GET soxdemo/api/customer/all HTTP/1.1
Host: app4.timelog.com
Authorization: Bearer {access_token}

Step 7 Refresh your token

All access_token issued will expire at some point. Normally after 3600 seconds. You can use the refresh token to get a new access token. Use a request like below to get access again.

POST /connect/token HTTP/1.1
Host: newlogin.timelog.com
Content-Type: application/x-www-form-urlencoded

    client_id={api_key}&
    client_secret={api_secret}&
    grant_type=refresh_token&
    refresh_token={refresh token}
    redirect_uri=https://{your app callback URL}

(URL encoding removed, and line breaks added for readability)

Expect the following JSON object back:

{
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyQkFEMzM5MTUwRDhERDA3M0U1MUVFNTQ0M0NCRjNCOTNCMTI2MkMiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJJcnJUT1JVTmpkQno1UjdsUkR5X081T3hKaXcifQ.eyJuYmYiOjE1MTYxMDQ0NjcsImV4cCI6MTUxNjEwNDc2NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoic2FtcGxlYXBwIiwibm9uY2UiOiJ6eGMiLCJpYXQiOjE1MTYxMDQ0NjcsImF0X2hhc2giOiJoeENpbG5adHo4SmhyUmZ4NmxsNGdnIiwic2lkIjoiODVjYmM0NTk3MjQ0YjBkMjlmMmQxMGVkNjhhMjNkZTkiLCJzdWIiOiJsb2NhbDo4MiIsImF1dGhfdGltZSI6MTUxNjEwMzUyMSwiaWRwIjoibG9jYWwiLCJhbXIiOlsicHdkIl19.EN3dFx91dcFoeGTHUEaXMFxn0BOCKu9TOIxbfblKHDIKOdqXJ7mUrgdN6pHBHSlbe2RthFhr1c8NLYj6pPJUH_2GM30Jeu_lPlqtioobbU8EfOGvNdMtjyTRGK9LGt8WxZsNrxrN85XEycwJ3izNha-2r0KbqSse8F3NfUstc5vxdgejWbzh4hnIJKfSRHNrctCFLxH_xaCH9motxtrGibgLft7t8GevXWtRmmm0Asc639xcMb7fXLG9htNDye6LhbMkQBszUgY0W5GPqBBVV0e8cHtyaW9GYg3zm4E7wNDaJCvfmP7dZe4zc16HNyzmxTwpajFh4TqvrGNAZ-X-bA",
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyQkFEMzM5MTUwRDhERDA3M0U1MUVFNTQ0M0NCRjNCOTNCMTI2MkMiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJJcnJUT1JVTmpkQno1UjdsUkR5X081T3hKaXcifQ.eyJuYmYiOjE1MTYxMDQ0NjcsImV4cCI6MTUxNjEwODA2NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJ0bHBhcGkiXSwiY2xpZW50X2lkIjoic2FtcGxlYXBwIiwic3ViIjoibG9jYWw6ODIiLCJhdXRoX3RpbWUiOjE1MTYxMDM1MjEsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsInRscGFwaSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.IprVwhRgBfZlKkxed5G1kagSMJLPrxHrNjukVRB2kPaTI61lZzW6MV8pxke2hlEhyCTYbx90EKIpc42bAm0SDX8wIm9GjvdPfQylOtGeRwENxKL8sVNWNPR8dyN-3-Qr-2QCxGY2FKjHgDVJ0kn1XPTf9yw5hXXOu0eS2jTIluAJVw3a6KkoNQcDh4BufyoqLmbe7FvaXb3Dx6zYGHvC4ED8GOVHzN2u2iCOZHu6o6NsBJ-5HV0pgS54Fjs9BTstgsF86dduBEPO5K3WAYZJokSh_dJ5FtSR4UBOvJvfXkk5Vi65BU_900GgHGyHICyAUao1mpO3RB_L1lXsFJ0LVw",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "7f44506257829e088723e63fb8d827b32d4f9277dff34490a64e2418d4584453"
}

Note! That the refresh token can only be used once. You will need to store the updated refresh token to use next time your access token expires.

Rate Limits

API access rate limits are applied at a per-key basis in unit time. Access to the API using a key does at this time not have a hard limit, however we monitor usage closely and may at any time enforce rate limitations upon excessive usage patterns for a particular key.

Support

For help regarding accessing the API, feel free to drop in a line at support@timelog.com.

Terms of Use

We collect information from you when you register on our site. When registering as a developer, as appropriate, you may be asked to provide your: company name, name and e-mail address. You may, however, visit our site anonymously.

By registrering as a developer (by requesting an API key), we might email you information about API service updates, scheduled down time, breaking changes and similar to allow you to react proactively on these changes.