Fundamentals
Api sources SDK to manage non-native data sources like Garmin, Oura, Fitbit, etc.
1. Overview
Features
- Get available data sources
- Retrieve an authorization (connection) url for a data source.
- Revoke (disconnect) a data source
Android Studio
Android Studio Narwhal 4 Feature Drop | 2025.1.4 or higher is recommended.
2. Installation
In your build.gradle (app) set your min and target sdk version like below:
minSdk 26
targetSdk 36
In your build.gradle (app module) add the required dependencies.
- Latest
version:
- Latest stable version: 1.0.0
implementation("io.tryrook.android:rook-api-sources:version")
3. Initialize
All SDK functions are located in the RookApiSources, you need to create an instance and initialize with the following
parameters:
- clientUUID
- secret
- environment
- packageName (Optional, if not provided, the SDK will retrieve it from Context.)
RookApiSources only has in-memory storage to avoid multiple initializations we recommend using the singleton pattern with a ServiceLocator or with dependency injection.
val apiSources = RookApiSources(Context)
// Available environments:
//
// * SANDBOX ➞ Use this during your app development process.
// * PRODUCTION ➞ Use this ONLY when your app is published to the PlayStore.
val apiEnvironment = if (BuildConfig.DEBUG) ApiEnvironment.SANDBOX
else ApiEnvironment.PRODUCTION
// Enable logging only on debug builds
if (BuildConfig.DEBUG) {
apiSources.enableLocalLogs()
}
val configuration = ApiConfiguration(
clientUUID = CLIENT_UUID,
secret = SECRET,
environment = apiEnvironment,
)
RookApiSources.initRook(configuration)
You must register your applicationId (package name) and its corresponding secret in the ROOK Portal before
attempting to initialize the SDK. Failure to register these credentials will cause the initialization to fail with an
ApiNotAuthorizedException.
The ROOK Portal supports independent configurations for Sandbox and Production environments. Each environment requires its own unique pair of Package Name and secret
If you come from a previous version you MUST re-initialize the SDK with the new authentication flow.
4. Usage
Get data source authorizer
To get the authorization url for a specific data source call getDataSourceAuthorizer providing:
- userID
- dataSourceType - One of:
- "Garmin"
- "Oura"
- "Polar"
- "Fitbit"
- "Withings"
- "Whoop"
- "Dexcom"
- redirectUrl (optional - default
null) - After the user successfully connects to a data source, the user will be redirected to this URL.
RookApiSources.getDataSourceAuthorizer(userID, dataSource, REDIRECT_URL).fold(
{
// Success
},
{ throwable ->
// Hanlde error
}
)
It will return an instance of DataSourceAuthorizer:
data class DataSourceAuthorizer(
val dataSource: String // The name of the data source.
val authorized: Boolean, // True if the data source is connected, false otherwise.
val authorizationUrl: String?, // The URL to authorize the data source
)
If the user is not authorized, an authorizationUrl is provided, otherwise authorizationUrl will be null.
Get authorized data sources
To get all authorized data sources for the current user getAuthorizedDataSourcesV2 providing:
- userID
RookApiSources.getAuthorizedDataSourcesV2(userID).fold(
{
// Success
},
{ throwable ->
// Hanlde error
}
)
It will return a list of AuthorizedDataSourceV2:
data class AuthorizedDataSourceV2(
val name: String, // The name of the data source.
val authorized: Boolean, // True if the data source is connected, false otherwise.
val imageUrl: String, // The image URL of the data source.
)
Please note that authorized only represents the user connection status, and not whether the data source is currently
active (sending data) or has granted permissions.
For SDK-based data sources (such as Apple Health and Health Connect), this endpoint authorized == true indicates that
the user was created by SDK with the corresponding updateUserId function, means that the user is linked with ROOK via
SDK, but not indicates if the user granted permissions or not.
For API-based data sources (such as Fitbit, Garmin, and Withings), authorized == true indicates that the user has
authorized ROOK to retrieve data through the respective third-party platform.
Disconnect from a data source
To disconnect (revoke authorization) from a data source call revokeDataSource providing:
- userID
- dataSourceType - One of:
- DataSourceType.GARMIN
- DataSourceType.OURA
- DataSourceType.POLAR
- DataSourceType.FITBIT
- DataSourceType.WITHINGS
- DataSourceType.WHOOP
RookApiSources.revokeDataSource(userID, DataSourceType.WITHINGS).fold(
{
// Success
},
{ throwable ->
// Hanlde error
}
)
5. known exceptions
rook-api-sources returns custom exceptions wrapped in a Result object in each function when an issue is encountered.
Below there is a list of all ROOK exceptions, their description/cause 📜 and how to handle them if encountered 🔧.
ApiHttpRequestException
📜 An HTTP request failed, this usually means an error in ROOK servers.
🔧 Check if you configured the SDK credentials correctly, if that is OK look for
the httpCode and httpMessage properties and send a report to ROOK support.
ApiNotAuthorizedException
📜 The requested operation requires an authorization level that your clientUUID doesn't have.
🔧 Check if you configured the SDK credentials correctly, if that is OK send a report to ROOK support, some of the features of the SDK require a special level of authorization that are not included in the basic level.
ApiNotInitializedException
📜 The SDK was not initialized or failed to initialize.
🔧 Call apiSources.initRook() and wait for a successful result.
ApiSessionExpiredException
📜 The SDK session expired and could not be automatically recovered.
🔧 Re-initialize the SDK with a valid Client UUID and secret. Ensure that the secret and package name of your app are registered in the ROOK portal.
ApiTimeoutException
📜 An HTTP request waited too long and could not be completed. This can happen because an unavailable or unstable internet connection.
🔧 Check your connectivity and try again.
6. Best practices
Prefer Custom Tabs over webview
When building your own connections page inside your app you will need to take the user to the selected provider web page so they can log in and give read permissions, usually a web view may be sufficient however some providers web pages like Polar may not be displayed correctly or even be functional with a web view, for this we recommend to replace your entire web view flow with Chrome's Custom Tabs and using an App Link as a redirectUrl so the user is redirected to your app when the web based part of the flow finishes.
You can get started with Custom Tabs in the official documentation.
You can read more about App links in the official documentation