After successfully creating Spike API integration data stream of wearables recorded data becomes available for the application user when making api calls and also through the webhooks. Usually only data recorded from the moment of authorisation is shared, but Spike has developed mechanisms to fetch data recorded restrospectivelly as well. This page describes the feature called Backfill and principles of how to use it, as well as the limitations.

Configuration of your application

In admin console, under Application configuration you can find the setting called “Max Backfill (days)”. By default it’s disabled (set to nothing or 0). To enable the backfill mechanims you need to set the value to the required number of days and save it.

Core principles

Once backfill is enabled and new integration get created, where’s what you should expect
  • backfill is triggered post new integration creation, setting would have no effect on integration that are already created and have the same data accumulated by natular lifecycle
  • data delivery (API and webhooks) is unifiend, but backfilling process is unique to each provider, more about this in provider specific sections
  • backfilling mosly is asynchronous process. Seeking the best user experience for the application users, they will see integration being successfully created (redirected back to configured postback URL) and process might continue in the background

Provider specifics

Apple HealthKit

Data is stored exclusively on the device (iPhone). Backfilling is possible from the moment application user grants permissions and is limited by:
  • what data the user has on their device
  • what permissions your app has been granted (read access for specific data types)
  • user’s health app settings or deletions
  • your retention policy settings.
Because Apple doesn’t offer any other communication except HealthKit framework, you must query needed data manually in order to backfill. Before data is extracted it won’t be available to your backend over API calls. Enabling background data delivery also won’t perform the backfill as it’s designed for new data events. Examplary code below demonstrates the principles to do it, please adjust it to your own specific needs.
let statisticsType = StatisticsType.steps
let calendar = Calendar.current
let today = Date()

for dayOffset in 0..<7 {
    guard let startDate = calendar.date(byAdding: .day, value: -dayOffset, to: today) else {
        continue // This should not happen
    }
    
    let startOfDay = calendar.startOfDay(for: startDate)
    let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay)!

    // Call the getStatistics method for each day
    let statistics = try await spikeConnection.getStatistics(
        ofTypes: [statisticsType],
        from: startOfDay,
        to: endOfDay,
        interval: .day,
        filter: nil
    )
}

Android Health Connect

Data is stored exclusively on the device (running Android). Backfilling is possible from the moment application user grants permissions and is limited by:
  • what data the user has on their device
  • what permissions your app has been granted (read access for specific data types)
  • user’s health app settings or deletions
  • your retention policy settings.
  • 30 days period predating permission grant
Permission request timing is not relevant, meaning that if application user decides to approve permission week later by going directly into health connect settings menu, you will be able to access data 23 days prior to installing the app. Alternatively Google has introduced PERMISSION_READ_HEALTH_DATA_HISTORY, but it is a subject to recent versions of Android. Because Google doesn’t offer any other communication except health connect client, you must query needed data manually in order to backfill it. We recommend keeping this process asynchronous for the best user experience and segmented to ensure best performance. Before data is extracted it won’t be available to your backend over API calls. Enabling background data delivery also won’t perform the backfill as it’s designed for new data events. Examplary code below demonstrates the principles to do it, please adjust it to your own specific needs.
import java.time.LocalDate
import java.time.ZoneId
import java.time.Instant

val today = LocalDate.now()

for (dayOffset in 0 until 7) {
    val startDate = today.minusDays(dayOffset.toLong())
    val from: Instant = startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()
    val to: Instant = startDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()

    // Call the getStatistics method for each day
    val statistics = spikeConnection.getStatistics(
        types = setOf(StatisticsType.STEPS),
        from = from,
        to = to,
        interval = StatisticsInterval.DAY,
        filter = null
    )
}

Fitbit

No extra effort is needed from your side to backfill Fitbit data. Fitbit typically makes up to 90 days of data available, depending on the user’s settings. However, some data types - such as activities and heart rate time series - may only be available for the past 30 days. Backfilling begins automatically after the integration is created. This process is asynchronous and, due to provider request limits, may take anywhere from several minutes to several hours to complete. Recent days are prioritized for backfill to provide a better user experience. To know when data becomes available, you should listen for incoming webhooks.

Garmin

No extra effort is needed from your side to backfill Garmin data. Garmin typically makes up to 90 days of historical data available. Backfilling is automatically triggered after the integration is created, but note that only one backfill request is allowed per user per application. This usually isn’t an issue in production, but during development, repeatedly connecting and disconnecting the same Garmin account can prevent additional backfills from occurring. The backfill process is fully asynchronous and managed by Garmin, and depending on the amount of data requested, it may take several hours (sometimes up to 12 hours) to complete. Data events may not arrive in chronological order. To know when data becomes available, you should listen for incoming webhooks.

Oura

No extra effort is needed from your side to backfill Oura data. Oura generally provides up to 180 days of historical data, but heart rate data can only be backfilled for up to 30 days. We recommend limiting backfill requests to 30 days or less due to provider limitations and to ensure data consistency.

Polar

No extra effort is needed from your side to backfill Polar data. Generally Polar declares data availability up to 28 days.

Suunto

No extra effort is needed from your side to backfill Suunto data. Generally Suunto declares data availability up to 28 days.

Whoop

No extra effort is needed from your side to backfill Whoop data. Generally Whoop declares longer data availability (up to 180 days), but it’s not recommended to attempt longer than 30 days because of other provider limitations and consistency.

Withings

No extra effort is needed from your side to backfill Withings data. Generally Withings declares longer data availability (up to 90 days), but it’s not recommended to attempt longer than 30 days because of other provider limitations and consistency.