api-sources
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
2. Installation
- Latest
version:
- Latest stable version: 4.0.0
- LTS version (supported until September 27, 2026): 1.2.0
flutter pub add rook_sdk_core
3. Initialize
All SDK functions are located in the RookApiSources, you need to create an instance using your credentials,
RookApiSources only has in-memory storage to avoid multiple instances we recommend using the singleton pattern with
dependency injection.
// Available environments:
//
// * SANDBOX ➞ Use this during your app development process.
// * PRODUCTION ➞ Use this ONLY when your app is published to the PlayStore.
RookEnvironment rookEnvironment =
isDebug ? RookEnvironment.sandbox : RookEnvironment.production;
// Enable logging only on debug builds
bool enableLogs = isDebug;
RookApiSources rookApiSources = RookApiSources(
clientUUID: Secrets.clientUUID,
secret: Secrets.secret,
appId: "YOUR BUNDLE ID (IOS) OR PACKAGE NAME (Android)",
environment: rookEnvironment,
enableLogs: enableLogs,
);
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
SDKNotAuthorizedException.
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.
void example() async {
try {
final authorizer = await rookApiSources.getDataSourceAuthorizer(
userID: userID,
dataSource: "Fitbit",
redirectUrl: null,
);
// Success
} catch (error) {
// Handle error
}
}
It will return an instance of DataSourceAuthorizer:
class DataSourceAuthorizer {
String dataSource; // The name of the data source.
bool authorized; // True if the data source is connected, false otherwise.
String? authorizationUrl; // 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
void example() async {
try {
final dataSources = await rookApiSources.getAuthorizedDataSourcesV2(
userID: userID,
);
// Success
} catch (exception) {
// Handle error
}
}
It will return a list of AuthorizedDataSourceV2:
class AuthorizedDataSourceV2 {
String name; // The name of the data source.
bool authorized; // True if the data source is connected, false otherwise.
String imageUrl; // 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
void example() async {
try {
await rookApiSources.revokeDataSource(
userID: userID,
dataSource: dataSourceType,
);
// Success
} catch (error) {
// Handle error
}
}
5. known exceptions
Every SDK returns custom exceptions wrapped in a Future 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 🔧.
ConnectTimeoutException
📜 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.
HttpRequestException
📜 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 message property and send a report to ROOK support.
SDKNotAuthorizedException
📜 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.
SessionExpiredException
📜 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.
UnknownException
📜 Unknown exceptions from the OS (Android/IOS) or the platform (Flutter).
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 use a plugin like flutter_custom_tabs which uses Custom Tabs for Android and SFSafariViewController for IOS.
You can read more about Android App links in the official flutter documentation and Native documentation
You can read more about IOS Universal links in the official flutter documentation and Native documentation