Toshl Developer

OAuth

Apps can connect to the API using the OAuth 2.0 authorization framework. Currently the only available authorization grant type is authorization code.

Before you can start using the API, you need to register an application. It will take you about a minute to set everything up.

In order to authenticate a user a client must:

  1. Ask the user for access permissions.
  2. Exchange the authorization code for an access token.
  3. Use the access token to make authenticated requests.
  4. Use the refresh token to obtain a new access token if it expires.

Authorize a user

To authorize a user simply redirect her to this URL:

GET https://toshl.com/oauth2/authorize

Parameters

client_id
required
The value provided to you when you registered your application.

Example value: 952D5C48-FA56-44AE-9F20-595061024374
response_type
required
Set to code indicating that an authorization code will be returned to the application after the user approves the authorization request.

Example value: code
scope
optional
The data your application is requesting access to. Send a space separated list of scope types. If scope is not provided the scope set during app registration will be used.

Example value: expenses:rw incomes:rw
redirect_uri
optional
The location URI where the user should be returned to after they approve access for your app. If no redirect_uri is provided the one used when registering the app will be used.

Example value: https://example.com/cb
state
recommended
A unique value used by your application in order to prevent cross-site request forgery (CSRF) attacks on your implementation. Value will be truncated to 255 characters and returned as is in the response.

Scope types

The following is a list of data your application is requesting access to. Send a space separated list of scope types. If scope is not provided the scope set during app registration will be used. If scope is used during the authorization step, it must be the same as the one used during app registration.

expenses:r Request read access to users expenses.
expenses:rw Request read & write access to users expenses.
incomes:r Request read access to users incomes.
incomes:rw Request read & write access to users incomes.
budgets:r Request read access to users budgets.
budgets:rw Request read & write access to users budgets.
user:r Request read access to users information (email, name etc).
user:rw Request read & write access to users information (email, name etc).

Note: If user grants access to expenses or incomes that implicitly means they give access to tags, repeats and export as well.

Access granted

When the user grants access, the client will be redirected to the provided redirect_uri with additional query parameters.

GET https://client.example.com/cb?code=xyz&state=abc
code The authorization code that you will use to obtain an access token.

Example value: 952D5C48-FA56-44AE-9F20-595061024374
state
optional
The value of the state parameter passed in the initial request to the authorization server.

Note: Code is valid for 30 seconds. If the token request is not made in that time the process must start over again. The client must not use the same code twice. If so, all tokens issued for this code will be revoked.

If used (recommended), the state value should be compared against the original value. If the values do not match, it is possible a malicious user is attempting to perform a cross-site request forgery attack on the application, so the OAuth flow should not be continued.

The callback endpoint ideally should not load HTML but only extract the provided parameters and then redirect to a new page without the provided parameters (thus not exposing the code to the end-user). Toshl staff will make security audits of your implementations on a periodical basis and will block your app if any problems are detected in your implementation. For more information refere to the OAuth spec.

Errors

If the user declines or the request itself is malformed, the server will inform the client by adding the parameters error and state (if present) to the query part of the redirect_uri.

GET https://client.example.com/cb?error=access_denied&state=xyz
invalid_request The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
unauthorized_client The client is not authorized to request an authorization code using this method.
access_denied The resource owner or authorization server denied the request.
unsupported_response_type The authorization server does not support obtaining an authorization code using this method.
invalid_scope The requested scope is invalid, unknown, or malformed.
server_error The authorization server encountered an unexpected condition that prevented it from fulfilling the request.
temporarily_unavailable The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.

Obtaining an access token

To complete the authorization process you must use the code to obtain an access_token which you can then use to make authorized requests on behalf of the user.

POST https://toshl.com/oauth2/token

Parameters

code
required
Code obtained in the authorization step.

Example value: 952D5C48-FA56-44AE-9F20-595061024374
grant_type
required
Grant type must be set to authorization_code.

Example value: authorization_code
redirect_uri
optional
Redirect URI must be included if it was included in the Authorization step. The values of both must be the same for the request to succeed.

Example value: https://example.com/cb

In addition you must specify your client_id and client_secret in a HTTP Basic Authorization header (client_id as the user and client_secret as the password). This is what an example of the final request would look like:

$ curl -i "https://toshl.com/oauth2/token" \
  --user CLIENT_ID:CLIENT_SECRET \
  -X POST -d "grant_type=authorization_code" -d "code=CODE"

Response

If the request is properly authenticated the server will issue and return an OAuth access and refresh token in a JSON-encoded response.

{
    "access_token": "f2eb339292dd1cd22a064797129b3de4",
    "token_type": "bearer",
    "expires_in": 3600,
    "refresh_token": "swl3839021ddjjwoowlksmdsao190921AbhUkdsajHH",
    "scope": "expenses:read expenses:write"
}

Note: Special care must be taken in storing access_token and refresh_token on the client.

access_token
required
The issued access token.
Example value: 760511AC-3C70-4085-B156-8A154BBFF6DE
token_type
required
The issued access token type. For authorization code always set to bearer.
expires_in
required
Access token lifetime in seconds.

Example value: 3600
refresh_token
required
Refresh token that can be used to prolong users authorization without requiring the user to re-authenticate. The refresh token will expire after one month and can be revoked at any time by the user or Toshl staff.
Example value: 5E9F1F4A-88F6-4CD8-B080-D71D4037DA33
scope
optional
Returned if the list requested by the client is not identical to the one granted by the user.

Example value: expenses:rw incomes:rw

Errors

The authorization server will respond with an HTTP 400 (Bad Request) status code and a JSON document that includes a single error parameter with one of the following values:

invalid_request The request is missing a required parameter, includes an unsupported parameter value (other than grant type), repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.
invalid_client Client authentication failed.
invalid_grant The provided authorization grant (e.g. authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
unauthorized_client The authenticated client is not authorized to use this authorization grant type.
unsupported_grant_type The authorization grant type is not supported by the authorization server.
invalid_scope The requested scope is invalid, unknown, or malformed.

Example

{
    "error":"invalid_request"
}

Refreshing an access token

When the access token expires you can use the issued refresh_token to obtain a new access token.

POST https://toshl.com/oauth2/token

Parameters

grant_type
required
Grant type must be set to refresh_token.
refresh_token
required
The refresh token issued with the expired access token.

Example value: 952D5C48FA5644AE-9F20-595061024374
scope
optional
The scope must be the same as the one initially returned during authorization code exchange.

Example value: expenses:rw incomes:rw

In addition you must specify your client_id and client_secret in a HTTP Basic Authorization header (client_id as the user and client_secret as the password). This is what an example of the final request would look like:

$ curl -i "https://toshl.com/oauth2/token" \
  --user CLIENT_ID:CLIENT_SECRET \
  -X POST -d "grant_type=refresh_token" -d "refresh_token=TOKEN" -d "scope=SCOPE"

For a list of possible errors see token request error list.

Revoke access

A user may decide to revoke access to the application. To do so send the refresh_token retrieved in the token step to the following endpoint.

$ curl -i "https://toshl.com/oauth2/revoke" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -X POST -d "refresh_token=REFRESH_TOKEN"

This will remove all access and refresh tokens thus essentially logging the user out of the application.

Parameter

refresh_token
required
Refresh token retrieved in the token step.

Accessing protected resources

API utilises the use of bearer tokens for authorization. The preferred way of authorizing requests is by sending the bearer token in a HTTP Authorization header.

Signing requests

This is a simple example of fetching your expenses. Go ahead, try this out -> paste the curl statement into your terminal. It will return your expenses according to the endpoint documentation.

curl https://api.toshl.com/expenses \
     -H "Authorization: Bearer T9cE5asGnuyYCCqIZFoWjFHvNbvVqHjl"

Errors

For a list of possible errors check the endpoint error list.