Cloud authentication

You can use ManicTime Cloud API in order to programmatically access timeline data using Timeline API.

Authentication

ManicTime Cloud API uses OpenID Connect for authentication. OpenId Connect is built on top of OAuth 2.0, specifically, Oauth 2.0 Authorization Code flow is used, where after successful login your app gets authorization code which it can use to get access token. You use access token in order to make authorized API calls.

Using API

You need to follow these steps in order to successfully use ManicTime Cloud API:
1. Register your app in order to get client ID and client secret.
2. Get OpenID Connect configuration in order to get all endpoint URLs.
3. Open login page where user can enter username and password.
4. Get authorization code after successful login.
5. Get refresh and access tokens using authorization code.
6. Call API using access token.
7. Get new access token using refresh token.
8. Use the API

An OpenId Connect client library can help you with most steps or you can implement everything yourself.

To quickly get the Bearer token and try how it works, you can use this sample. Once you get the Bearer token, use something like Postman to generate requests.

1. Register your app

You need to register your app on API client management page in order to get client ID and client secret. You also need to specify callback URL where your app will listen for HTTP requests in order to receive authorization code.

2. Get OpenID Connect configuration

Your app can use OpenID Connect configuration URL in order to get all endpoint URLs.

Request (from your app)

GET https://login.manictime.com/.well-known/openid-configuration  
Accept: application/json

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

{
    "issuer": "https://login.manictime.com",
    "jwks_uri": "https://login.manictime.com/.well-known/openid-configuration/jwks",
    "authorization_endpoint": "https://login.manictime.com/connect/authorize",
    "token_endpoint": "https://login.manictime.com/connect/token",
    "userinfo_endpoint": "https://login.manictime.com/connect/userinfo",
    "end_session_endpoint": "https://login.manictime.com/connect/endsession",
    "check_session_iframe": "https://login.manictime.com/connect/checksession",
    "revocation_endpoint": "https://login.manictime.com/connect/revocation",
    "introspection_endpoint": "https://login.manictime.com/connect/introspect",
    "device_authorization_endpoint": "https://login.manictime.com/connect/deviceauthorization",
    "frontchannel_logout_supported": true,
    "frontchannel_logout_session_supported": true,
    "backchannel_logout_supported": true,
    "backchannel_logout_session_supported": true,
    "scopes_supported": ["openid", "email", "profile", "manictimeapi", "offline_access"],
    "claims_supported": ["sub", "email", "email_verified", "name", "family_name", "given_name", "middle_name", "nickname", "preferred_username", "profile", "picture", "website", "gender", "birthdate", "zoneinfo", "locale", "updated_at"],
    "grant_types_supported": ["authorization_code", "client_credentials", "refresh_token", "implicit", "password", "urn:ietf:params:oauth:grant-type:device_code"],
    "response_types_supported": ["code", "token", "id_token", "id_token token", "code id_token", "code token", "code id_token token"],
    "response_modes_supported": ["form_post", "query", "fragment"],
    "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"],
    "id_token_signing_alg_values_supported": ["RS256"],
    "subject_types_supported": ["public"],
    "code_challenge_methods_supported": ["plain", "S256"],
    "request_parameter_supported": true
}

3. Open login page

Use authorization_endpoint URL from OpenID Connect configuration to open login page in browser.

Request (from browser)

GET https://login.manictime.com/connect/authorize
 ?response_type=code
 &nonce=<nonce>
 &state=<state>
 &code_challenge=<code_challenge>
 &code_challenge_method=S256
 &client_id=<client_id>
 &scope=openid+profile+manictimeapi+offline_access
 &redirect_uri=<redirect_uri>

nonce - Random string generated by your app. It is used for ID token validation. It prevents replay attack.
state - Random string generated by your app. It us used for request validation when receiving authorization code. It prevents cross-site request forgery (CSRF) attacks.
code_challenge - BASE64-URL-encoded string of the SHA256 of code verifier. Code verifier is random string generated by your app. It must be between 43 and 128 characters long and use only following characters: [A-Z], [a-z], [0-9], "-", ".", "_", "~". Code verifier is used later when using authorization code to get access token. It prevents authorization code from being intercepted.
client_id - Client ID you received on API client management page. See 1. Register your app.
redirect_uri - Callback URL you configured on API client management page. See 1. Register your app.

Sample request

GET https://login.manictime.com/connect/authorize
  ?response_type=code
  &nonce=EmKTkcNT2g-MYB_AdDjvGw
  &state=vCJwIVcaQq35yKP7P_he0w
  &code_challenge=vP9KwpuaE2keCezOtlre_rGrlKm8zt_39SNJURh2pdk
  &code_challenge_method=S256
  &client_id=xqAuIkiJUj6S6DHVRBSlUIaiQm4kgeVx
  &scope=openid+profile+manictimeapi+offline_access
  &redirect_uri=http%3A%2F%2F127.0.0.1%3A4000

Browser will display login page where user can enter username and password.

4. Get authorization code

After successful login, browser will call callback URL where your app can get authorization code from query string.

Request (from browser to your app)

GET <redirect_uri>
  ?code=<code>
  &scope=openid+profile+manictimeapi+offline_access
  &state=<state>

code - Authorization code to use for getting refresh and access tokens.
state - Random string generated by your application when calling authorization_endpoint. Your app should verify that it matches generated string. See 3. Open login page.

Sample request

GET http://127.0.0.1:4000/
  ?code=93A570CEBF2208064DC27F2C52DBDD792B4E41978E7AE2C8B03C362AF472F8BD
  &scope=openid%20profile%20manictimeapi%20offline_access
  &state=vCJwIVcaQq35yKP7P_he0w
  &session_state=mRbyx_Yo2KrVm-XpwUK6MA4jZ2H5JKxK5vlycQG2n2o.CD80142FCEE3DDF78200E9427DBDA116

Your app should return HTML response which will be displayed in the browser informing user of successful login.

5. Get refresh and access tokens

You can use received authorization code to get refresh and access token using token_endpoint URL from OpenID Connect configuration.

Request (from your app)

POST https://login.manictime.com/connect/token
Content-Type: application/x-www-form-urlencoded
Accept: application/json

grant_type=authorization_code
&code=<code>
&redirect_uri=<redirect_uri>
&code_verifier=<code_verifier>
&client_id=<client_id>
&client_secret=<client_secret>

code - Authorization code received from authentication server. See 4. Get authorization code.
redirect_uri - Callback URL you configured on client registration page. See 1. Register your app.
code_verifier - Random string generated by your application associated with code_challenge that was generated when calling authorization_endpoint. See 3. Open login page.
client_id - Client ID you received on API client management page. See 1. Register your app.
client_secret - Client secret you received on API client management page. See 1. Register your app.

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

{
  "id_token": <id_token>,
  "access_token": <access_token>,
  "expires_in": 3600,
  "token_type": "Bearer",
  "refresh_token": <refresh_token>,
  "scope":"openid profile manictimeapi offline_access"
}

Sample request

POST https://login.manictime.com/connect/token
Host: login.manictime.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=93A570CEBF2208064DC27F2C52DBDD792B4E41978E7AE2C8B03C362AF472F8BD
&redirect_uri=http%3A%2F%2F127.0.0.1%3A4000
&code_verifier=bXotQCtP39visoKdQ5D0-dzy2AUNPjfj1B0wu4rWtEQ
&client_id=xqAuIkiJUj6S6DHVRBSlUIaiQm4kgeVx
&client_secret=BzJfaDfyvZinbqe37ZMeYosWk%2FVMBQf7mSzzJ%2BiaA5K0VrD8xrrMS7pdzBmhLSfQ

Sample response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

{
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2MDc2MjQzNzksImV4cCI6MTYwNzYyNDY3OSwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5tYW5pY3RpbWUuY29tIiwiYXVkIjoieHFBdUlraUpVajZTNkRIVlJCU2xVSWFpUW00a2dlVngiLCJub25jZSI6IkVtS1RrY05UMmctTVlCX0FkRGp2R3ciLCJpYXQiOjE2MDc2MjQzNzksImF0X2hhc2giOiIwTnQyOXVYNGYxa0ZDVmNGYXhVZVN3Iiwic19oYXNoIjoiaXRrR2pDU1JpbjZ6QmJFRlJXaWx3QSIsInNpZCI6IjhBN0VDMzI1NUNBMzE4QjdGQUI1MTg2MUE1NDY3MTUyIiwic3ViIjoiZTFmNzg0ZjItNTQ1MC00NjJhLWE1OWQtNWVkMmNhZTkwMmVkIiwiYXV0aF90aW1lIjoxNjA3NjI0MTU4LCJpZHAiOiJsb2NhbCIsImFtciI6WyJwd2QiXX0.eA8D9qhWwrv6VFH8ymmbuM5XODLPDzYXAXJ40uGYKg531_pUXhFyHLRxrqu7Lbpyk47AK__eVcJ7yhANBvfn-7bMANvRnQqiooiOST5lpLvgRkzoOkUV39KwmaOVowWiJ5w2JLOQnAmhQ5Wk2M3dJ9CbPb_x0faPaVAgMO1n_YyUOBkhnqw1SlOh9kjn15bpZBJdEy39j4qt2nz4wuk8zpul6Xq2nCLygdPhuywLdIUUf923JWHRhAuoJouX-WjfW2hP9c3aug8EqVIbbmbEIeneiJlvZcEG1Ev1VQEZdeqayGCBIYmUKq4jMQG3M3-AG9gfKTle9Yf977UfFfqQjQ",
    "access_token": "B34CB9B34502923E5893FA1CD877660C2CD4A770F29F6B395F7F38C59794B0FD",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "9026B52292F5D579904DE017DDCFA223F5484CCF8268B7B98D31524886E8BD56",
    "scope": "openid profile manictimeapi offline_access"
}

6. Call API

You can need to include access token with each API call.

Request (from your app)

GET https://api.manictime.com/v1/profile
Authorization: Bearer <access_token>

access_token - Access token received from authentication server. See 5. Get refresh and access tokens.

Sample request

GET https://api.manictime.com/v1/profile
Authorization: Bearer B34CB9B34502923E5893FA1CD877660C2CD4A770F29F6B395F7F38C59794B0FD 

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
    "serverUrl": "https://cloud.manictime.com/abcdef/",
    "license": "abc",
    "links": [
        {
            "rel": "self",
            "url": "https://api.manictime.com/v1/profile"
        }
    ]
}

7. Get new access token

Access token expires after one hour. You can user token_endpoint URL from OpenID Connect configuration to get new access token.

Request (from your app)

POST https://login.manictime.com/connect/token
Accept: application/json
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=<refresh_token>
&client_id=<client_id>
&client_secret=<client_secret>

refresh_token - Refresh token received from authentication server. See 5. Get refresh and access tokens.
client_id - Client ID you received on API client management page. See 1. Register your app.
client_secret - Client secret you received on API client management page. See 1. Register your app.

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

{
  "id_token": <id_token>,
  "access_token": <access_token>,
  "expires_in": 3600,
  "token_type": "Bearer",
  "refresh_token": <refresh_token>,
  "scope": "openid profile manictimeapi offline_access"
}

Sample request

POST https://login.manictime.com/connect/token
Accept: application/json
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=9026B52292F5D579904DE017DDCFA223F5484CCF8268B7B98D31524886E8BD56
&client_id=xqAuIkiJUj6S6DHVRBSlUIaiQm4kgeVx
&client_secret=BzJfaDfyvZinbqe37ZMeYosWk%2FVMBQf7mSzzJ%2BiaA5K0VrD8xrrMS7pdzBmhLSfQ

Sample response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

{
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2MDc2MjQzODAsImV4cCI6MTYwNzYyNDY4MCwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5tYW5pY3RpbWUuY29tIiwiYXVkIjoieHFBdUlraUpVajZTNkRIVlJCU2xVSWFpUW00a2dlVngiLCJpYXQiOjE2MDc2MjQzODAsImF0X2hhc2giOiJNRnhYOFY4dGI2VXNyWXRadnR0aUZ3Iiwic3ViIjoiZTFmNzg0ZjItNTQ1MC00NjJhLWE1OWQtNWVkMmNhZTkwMmVkIiwiYXV0aF90aW1lIjoxNjA3NjI0MTU4LCJpZHAiOiJsb2NhbCIsImFtciI6WyJwd2QiXX0.UYwkzgrnhIgIimrk5LBh-i6_P-Lr2LOwxYEJ1mMo_wBy9dzebGb4nRgPeTSimPA2qFEnqdL61IMPnPBAclVkeuSWzr32dbfTBS8v4rYR6buEtegEYPjNgiDnbedE1jyWwpqJLjiWKoLyZ9BM_DAlFWCndRgYNwo01sGQg_XEV37S2WTOFHF6W1Mn99VDDewtshT1JdhLojrGZ8Bb5X6W4uW_IpJUfUB5QdGxlBxXuxd3zirTbPschARwkoUvtpZkTH0mIc4yilXD2WRVzIG3cviKPkvF_HRKK2T7C7a4vIiy4m4ZZ8QMrp6Ye5kpu-XEXtCbrTQUJ1iN9ZP6nmCCLQ",
    "access_token": "F6D65B2D4B439C2A56EF69D5AA9691B7BCD0D0A0D336C617DF65E2EFFFE711B5",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "9026B52292F5D579904DE017DDCFA223F5484CCF8268B7B98D31524886E8BD56",
    "scope": "openid profile manictimeapi offline_access"
}

8. Use the API

In step 6. part of the response was the serverUrl. Use that URL to form API calls, like this:https://cloud.manictime.com/abdef/api/.... You can find samples of API calls here.