Skip to content

The FulcraAPI class

The main class for making Fulcra API functions.

This contains functions for authorizing a token, authenticating HTTP requests, making calls, and loading data.

apple_location_updates(start_time, end_time, fulcra_userid=None)

Retrieve the raw Apple location update samples during the specified period of time.

Requires an authorized access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object.

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object.

required
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts, each of which contains the data from a location update.

Examples:

To retrieve all location updates within a specific hour:

>>> updates = fulcra.apple_location_updates(
...     start_time="2023-09-24T20:00:00Z",
...     end_time="2023-09-24T21:10:00Z"
... )

To see the details of the first update:

>>> updates[0]
{'speed': -1, 'horizontal_accuracy_meters': 35, 'longitude_degrees':
-117.15661336566698, 'source_is_simulated_by_software': False,
'source_is_produced_by_accessory': False, 'latitude_degrees':
32.706505158026005, 'vertical_accuracy_meters': 3.0130748748779297,
'course_heading_accuracy_degrees': -1, 'course_heading_degrees': -1,
'ellipsoidal_altitude_meters': -6.280021667480469, 'floor': 0,
'speed_accuracy_meters': -1, 'altitude_meters': 29.17388153076172, 'uuid':
'e80feacc-54e9-414f-86cb-8d6ebd85ea41', 'timestamp':
'2023-09-24T20:39:28.056+00:00'}

apple_location_visits(start_time, end_time, fulcra_userid=None)

Retrieve the raw Apple location visit samples during the specified period of time.

Requires an authorized access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object.

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object.

required
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts, each of which contains the data from a location visit.

Examples:

To retrieve all location updates within a specific hour:

>>> visits = fulcra.apple_location_visits(
...     start_time="2023-09-24T20:00:00Z",
...     end_time="2023-09-24T21:10:00Z"
... )

To see the details of the first update:

>>> visits[0]
{'longitude_degrees': -117.1224047932943, 'latitude_degrees':
32.75812770726706, 'arrival_date': '0001-01-01T00:00:00+00:00',
'departure_date': '2023-09-25T01:42:16.998+00:00',
'horizontal_accuracy_meters': 32.93262639589646, 'uuid':
    '935971dd-0822-49ef-a74f-b09a24d68c3a'}

apple_workouts(start_time, end_time, fulcra_userid=None)

Retrieve the list of Apple workouts that occurred (at least partially) during the specified time range.

Requires an authorized access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object.

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object.

required
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts, each of which contains the data from a workout.

Examples:

To retrieve all workouts during a time period:

>>> workouts = fulcra.apple_workouts(
...     start_time = "2023-09-21 07:00:00.000Z",
...     end_time = "2023-09-22 07:00:00.000Z"
... )

To inspect the details of a workout:

>>> workouts[0]
{'start_date': '2023-09-21T19:18:31.733000Z', 'end_date':
'2023-09-21T19:49:08.773000Z', 'has_undetermined_duration': False,
'apple_workout_id': '480b25fe-b229-41b9-bf13-7ccf5e2092ec', 'duration':
1837.0397539138794, 'extras': {'HKTimeZone': 'America/Los_Angeles',
'HKAverageMETs': '4.37848 kcal/hr·kg' ... }

authorize()

Request a device token, then prompt the user to authorize it.

This uses the Device Authorization workflow, which requires the user to visit a link and confirm that the code shown on the screen matches.

This function will attempt to open the link in a new browwser tab (using webbrowser module); it will also be either print()ed out (or display()ed out if run inside Jupyter).

The function will wait until the user visits the page and authentiactes, or until a specified time has passed.

Raises an exception on failure.

Examples:

fulcra.authorize() Use your browser to log in to Fulcra. If the tab does not open automatically, visit this URL to authenticate: https://fulcra.us.auth0.com/activate?user_code=SJZC-GRBW

When the authorization succeeds, the following will be displayed:

Authorization succeeded.

calendar_events(start_time, end_time, calendar_ids=None, fulcra_userid=None)

Retrieve the list of calendar events that occur (at least partially) during the specified time range.

To request events from another user's store, pass their user ID as the fulcra_userid parameter.

Requires an authorized access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object.

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object.

required
calendar_ids Optional[List[str]]

If included, the query results are limited to events that are on the specified calendars.

None
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts, each of which contains the data from a calendar event.

Examples:

To retrieve all calendar events that span a given range of time:

>>> cal_events = fulcra.calendar_events(
...     start_time = "2023-09-24 07:00:00.000Z",
...     end_time = "2023-09-25 07:00:00.000Z",
...     calendar_ids=["01fb4138-db27-4792-867d-5cfbdc720165"]
... )

To inspect the details of an event:

>>> cal_events[0]
{'calendar_event_id': 'c409a249-24cd-4c19-b763-3683cc21b9f8',
'calendar_id': '01fb4138-db27-4792-867d-5cfbdc720165', 'start_date':
'2023-09-24T20:10:00Z', 'end_date': '2023-09-24T21:10:00Z',
'allow_new_time_proposals': None, 'alarms':
['19b7692e-7434-44be-a5ba-c8dfa338deb6'], 'availability': 'free',
'calendar_item_external_identifier':
'7kukuqrfedlm2f9tfbe684r6cqpk9mrk0aqdeoan7jdbr93e7963lagn9uq6pdsbac40',
'calendar_item_identifier': '22153B27-4BEE-480C-9627-F2EABC698103',
'event_identifier':
'EC9D6240-04A7-4869-9D2E-1A7648EA7732:7kukuqrfedlm2f9tfbe684r6cqpk9mrk0aqdeoan7jdbr93e7963lagn9uq6pdsbac40',
'creation_date': '2023-09-16T23:27:22Z', 'has_alarms': True,
'has_attendees': True, 'has_notes': True, 'has_recurrence_rules':
False, 'is_all_day': False, 'is_detached': False, 'last_modified_date':
'2023-09-16T23:27:26Z', 'location': 'PETCO Park', 'notes':
'This event was created from an email you received in Gmail.',
'occurrence_date': '2023-09-24T20:10:00Z', 'organizer':
'22381502-0af3-487a-820c-e22aa4cae201', 'recurrence_rules': None,
'status': 'confirmed', 'geolocation': None, 'time_zone':
'America/Los_Angeles (fixed)', 'title':
'St. Louis Cardinals at San Diego Padres', 'url': None,
'extras': {}, 'participants': [{'is_current_user': True,
'participant_role': 'required', 'participant_type': 'person',
'participant_status': 'accepted', 'url': 'mailto:cstone@gmail.com',
'contact_id': '00900185-b290-4f1c-860d-e4433024a943',
'name': 'cstone@gmail.com'}]}

calendars(fulcra_userid=None)

Retrieve the list of calendars available in your data store.

To request the calendars from another user's store, pass their user ID as the fulcra_userid parameter.

Requires an authorized access token.

Parameters:

Name Type Description Default
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts, each of which represents a calendar.

Examples:

To retrieve all calendars from your data store:

>>> calendars = fulcra.calendars()
>>>

To inspect the details of a calendar:

>>> calendars[0]
{'calendar_id': '02b761da-46d0-4074-a9c8-406fd0de3adf', 'calendar_name':
'Birthdays', 'calendar_color':
'[0.5098039507865906,0.5843137502670288,0.686274528503418,1.0]',
'calendar_source_id': '03da9f61-7b58-4021-8f40-a93548258faf',
'calendar_source_name': 'Other', 'fulcra_source': 'apple_calendar'}

custom_input_events(start_time, end_time, source=None, fulcra_userid=None)

Retrieves events from Fulcra custom inputs, along with any metadata, for the requested time ranges.

Requires a valid access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object

required
source Optional[str]

When specified, the full name of the source to query records from

None
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for

None

Returns:

Type Description
List[Dict]

A list of events; each event is represnted by a dict.

fulcra_api(access_token, url_path)

Make a call to the given url path (e.g. /v0/data/time_series_grouped?...) with the specified access token.

Parameters:

Name Type Description Default
access_token str

The access token to authenticate the request with

required
url_path str

The path of the URL to use (e.g. "/v0/data/...")

required

Returns:

Type Description
bytes

The raw response data (as bytes). Raises an exception on failure.

get_fulcra_userid()

Retrieve the currently authorized Fulcra UserID.

Returns:

Type Description
str

the Fulcra UserID of the currently-authorized user.

get_shared_datasets()

Retrieves datasets that have been shared with the currently authenticated user

Examples:

    >>> datasets = fulcra_client.get_shared_datasets()
    >>> datasets[0]
    {'permission_id': 'cf362f80-ef41-4c08-b5e3-b18bd3d1524b', 'created_at': '2024-08-21T17:52:10.658596Z', 'time_start': None, 'time_end': None, 'fulcra_userid': 'a24a9667-c2c6-4bbf-9a0f-4Bej0afcb521', 'fulcra_user_name': 'John Doe', 'fulcra_user_picture': 'https://lh3.googleusercontent.com/a/ACg8ocL-ggGYjOFq23Dfbf5GohDXbk01AoGmL0gCSbooVBXDgWeTLJk=s47-d', 'datashare_name': 'Provisioned for data analysis'}

location_at_time(time, window_size=14400, include_after=False, reverse_geocode=False, fulcra_userid=None)

Gets the user's location at the specified time. If no sample is available for the exact time, searches for the closest sample up to window_size seconds back. If include_after is true, then also searches window_size seconds forward.

Parameters:

Name Type Description Default
time Union[str, datetime]

The point in time to get the user's location for.

required
window_size int

The size (in seconds) to look back (and optionally forward) for samples

14400
include_after bool

When true, a sample that occurs after the requested time may be returned if it is the closest one.

False
reverse_geocode bool

When true, Fulcra will attempt to reverse geocode the location and include the details in the results.

False
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts; the first dict is the best location sample.

Examples:

location = fulcra.location_at_time( ... time = "2024-01-24 00:00:00-08:00", ... )

location [{'speed': 0, 'horizontal_accuracy_meters': 4.848857421534995, 'longitude_degrees': -117.15709954484828, 'latitude_degrees': 32.707083bb994486, 'vertical_accuracy_meters': 3.2114044806616686, 'course_heading_accuracy_degrees': 180, 'course_heading_degrees': 87.05299950647989, 'ellipsoidal_altitude_meters': 32.700060645118356, 'floor': 0, 'speed_accuracy_meters': 0.9654413396512306, 'altitude_meters': 6.15396384336054, 'uuid': '59b2d63b-9b0b-436f-a66f-01129e1b33dd', 'timestamp': '2024-01-24T00:01:45.941+00:00', 'location_source': 'apple_location_update'}]

location_time_series(start_time, end_time, change_meters=None, sample_rate=900, look_back=14400, reverse_geocode=False, fulcra_userid=None)

Retrieve a time series of locations that the user was at. This uses the most precise underlying data sources available at the given time.

Requires a valid access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object

required
change_meters Optional[float]

when specified, subsequent samples that are fewer than this many meters away will not be included.

None
sample_rate int

The length (in seconds) of each sample

900
look_back int

The maximum number of seconds in the past to look back to find a value for a sample.

14400
reverse_geocode bool

When true, Fulcra will attempt to reverse geocode the locations and include the details in the results.

False
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of samples; each sample represents a location sample.

Examples:

>>> locations = fulcra.location_time_series(
...     start_time = "2024-06-06T19:00:00-07:00",
...     end_time = "2024-06-06T20:00:00-07:00",
...     reverse_geocode = True
... )
>>> print(pd.DataFrame(locations))
                                  slice_time        lat        long                           time  distance_change_m                                            address                                   location_details
0  2024-06-07T02:00:00+00:00  32.706814 -117.156455   2024-06-07T01:50:10.92+00:00                NaN  Petco Park, 100 Park Boulevard, San Diego, CA ...  {'annotations': {'DMS': {'lat': '32° 42' 25.87...
1  2024-06-07T02:15:00+00:00  32.706722 -117.156576  2024-06-07T02:03:56.903+00:00          15.281598  Petco Park, 100 Park Boulevard, San Diego, CA ...  {'annotations': {'DMS': {'lat': '32° 42' 25.87...
2  2024-06-07T02:30:00+00:00  32.706699 -117.156583  2024-06-07T02:22:07.571+00:00           2.588992  Petco Park, 100 Park Boulevard, San Diego, CA ...  {'annotations': {'DMS': {'lat': '32° 42' 25.87...
3  2024-06-07T02:45:00+00:00  32.706699 -117.156583  2024-06-07T02:22:07.571+00:00           0.000000  Petco Park, 100 Park Boulevard, San Diego, CA ...  {'annotations': {'DMS': {'lat': '32° 42' 25.87...

metric_samples(start_time, end_time, metric, fulcra_userid=None)

Retrieve the raw samples related to the given metric that occurred for the user during the specified period of time.

In cases where samples cover ranges and not points in time, a sample will be returned if any part of its range intersects with the requested range.

As an example, if you have start_date as 14:00 and end_date at 15:00, and there is a sample that covers 13:30-14:30, it will be included.

Requires an authorized access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object.

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object.

required
metric str

The name of the metric to retrieve samples for.

required
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Examples:

>>> samples = fulcra.metric_samples(
...     start_time="2023-08-09 07:00:00.000Z",
...     end_time="2023-08-10 07:00:00.000Z",
...     metric="StepCount"
... )

To inspect the first sample:

>>> samples[0]
{'start_date': '2023-08-10T06:05:10.726+00:00', 'end_date':
'2023-08-10T06:05:13.285+00:00', 'extras': None,
'has_undetermined_duration': False, 'unit': 'count', 'count': 1,
'uuid': '74983a94-8816-4b95-bbbd-d4108149261a', 'value': 8,
'source_properties': {'name': 'b c’s iPhone', 'version': '16.6',
'productType': 'iPhone12,8', 'operatingSystemVersion': [16, 6, 0],
'sourceBundleIdentifier':
'com.apple.health.F8872676-6D45-4981-8E14-C009D0AE5F27'},
'device_properties': {'name': 'iPhone', 'model':
'iPhone', 'manufacturer': 'Apple Inc.',
'hardwareVersion': 'iPhone12,8',
'softwareVersion': '16.6'}}

metric_time_series(start_time, end_time, metric, sample_rate=60, replace_nulls=False, fulcra_userid=None, calculations=None)

Retrieve time-series data from a single Fulcra metric, covering the time starting at start_time (inclusive) until end_time (exclusive).

If specified, the sample_rate parameter defines the number of seconds per sample. This value can be smaller than 1. The default value is 60 (one sample per minute).

Requires a valid access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object

required
metric str

The name of the time-series metric to retrieve

required
sample_rate float

The length (in seconds) of each sample

60
replace_nulls Optional[bool]

When true, replace all NA/null/None values with 0

False
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None
calculations Optional[list[str]]

When present, specifies additional calculations to perform for each time slice. The current values are: - max: The maximum value for each time window - min: The minimum value for each time window - delta: The delta between the maximum and minimum value for each time window - mean: The mean value for each time window - uniques: The list of unique values for each time window - allpoints: The list of all values for each time window - rollingmean: The rolling mean value for each time window. This mean is calculated relative to the beginning of the requested sample

None

Returns:

Type Description
DataFrame

a pandas DataFrame containing the data. For time ranges where data is missing, the values will be <NA>.

Examples:

To retrieve a dataframe containing the StepCount metric:

>>> df = fulcra.metric_time_series(
...     start_time = "2024-01-24 00:00:00-08:00",
...     end_time = "2024-01-25 00:00:00-08:00",
...     sample_rate = 1,
...     metric = "StepCount"
... )

The index of the DataFrame will be the time:

df.index DatetimeIndex(['2024-01-24 08:00:00+00:00', '2024-01-24 08:00:01+00:00', '2024-01-24 08:00:02+00:00', '2024-01-24 08:00:03+00:00', '2024-01-24 08:00:04+00:00', '2024-01-24 08:00:05+00:00', '2024-01-24 08:00:06+00:00', '2024-01-24 08:00:07+00:00', '2024-01-24 08:00:08+00:00', '2024-01-24 08:00:09+00:00', ... '2024-01-25 07:59:50+00:00', '2024-01-25 07:59:51+00:00', '2024-01-25 07:59:52+00:00', '2024-01-25 07:59:53+00:00', '2024-01-25 07:59:54+00:00', '2024-01-25 07:59:55+00:00', '2024-01-25 07:59:56+00:00', '2024-01-25 07:59:57+00:00', '2024-01-25 07:59:58+00:00', '2024-01-25 07:59:59+00:00'], dtype='datetime64[us, UTC]', name='time', length=86400, freq=None)

The non-index column(s) in the dataframe will be related to the metric.

df.columns Index(['step_count'], dtype='object')

metrics_catalog()

Gets the list of time-series metrics that are available for this user.
These metrics can be passed to the `metric_time_series` and
`time_series_grouped` functions.

Returns:
    The metrics, including descriptions.

Examples:

        >>> metrics = fulcra_client.metrics_catalog()
        >>> metrics[0]
        {'name': 'AFibBurden', 'description': "A discrete measure of the percentage of time that the user's heart shows signs

of atrial fibrillation (AFib) during a given monitoring period.", 'unit': 'percent', 'is_time_series': True, 'metric_kind': 'discrete', 'value_column': 'afib_burden'} >>> metrics[1] {'name': 'ActiveCaloriesBurned', 'description': 'A cumulative measure of the amount of active energy the user has burned.', 'unit': 'cal', 'is_time_series': True, 'metric_kind': 'cumulative', 'value_column': 'active_calories_burned'}

simple_events(start_time, end_time, categories=None, fulcra_userid=None)

Retrieve the events that occurred during the specified period of time, optionally filtering by categories.

If included, the categories parameter only includes events from the specified categories.

Requires an authorized access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object.

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object.

required
categories Optional[List[str]]

When present, the categories to filter on. Only events matching these categories will be returned.

None
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description
List[Dict]

A list of dicts, each of which represents an event.

Examples:

To retrieve the stored events during a given range:

>>> simple_events = fulcra.simple_events(
...     start_time="2022-05-01 04:00:00.000Z",
...     end_time="2023-08-03 04:00:00.000Z"
... )

To get the details of an event:

>>> simple_events[0]
{'event_body': 'relieved', 'category': 'mood', 'event_id':
'12680011-6668-4c8e-b4cd-3ca429445ac0', 'timestamp':
'2022-09-21T05:51:22Z'}

time_series_grouped(start_time, end_time, metrics, sample_rate=60, replace_nulls=False, fulcra_userid=None)

Retrieve a time-series data frame containing the specified set of Fulcra metrics from start_time (inclusive) until end_time (exclusive).

If specified, the sample_rate parameter defines the number of seconds per sample. This value can be smaller than 1. The default value is 60 (one sample per minute).

Requires a valid access token.

Parameters:

Name Type Description Default
start_time Union[str, datetime]

The start of the time range (inclusive), as an ISO 8601 string or datetime object

required
end_time Union[str, datetime]

The end of the range (exclusive), as an ISO 8601 string or datetime object

required
metrics List[str]

The names of the time-series metrics to include in the result

required
sample_rate float

The length (in seconds) of each sample

60
replace_nulls Optional[bool]

When true, replace all NA/null/None values with 0

False
fulcra_userid Optional[str]

When present, specifies the Fulcra user ID to request data for.

None

Returns:

Type Description

a pandas DataFrame containing the data. For time ranges where data is missing, the values will be <NA>.

Examples:

To retrieve a dataframe containing four different metrics (DistanceTraveledOnFoot, AppleWatchExerciseTime, ActiveCaloriesBurned, and BasalCaloriesBurned):

>>> df = fulcra.time_series_grouped(
...     start_time = "2023-07-01 04:00:00.000Z",
...     end_time = "2023-07-10 04:00:00.000Z",
...     metrics=["DistanceTraveledOnFoot",
...         "AppleWatchExerciseTime",
...         "ActiveCaloriesBurned",
...         "BasalCaloriesBurned"
...     ]
... )

The index of the DataFrame will be the time:

>>> df.index
DatetimeIndex(['2023-07-01 04:00:00+00:00',
               '2023-07-01 04:01:00+00:00',
               '2023-07-01 04:02:00+00:00',
               '2023-07-01 04:03:00+00:00',
               '2023-07-01 04:04:00+00:00',
               '2023-07-01 04:05:00+00:00',
               '2023-07-01 04:06:00+00:00',
               '2023-07-01 04:07:00+00:00',
               '2023-07-01 04:08:00+00:00',
               '2023-07-01 04:09:00+00:00',
               ...
               '2023-07-10 03:50:00+00:00',
               '2023-07-10 03:51:00+00:00',
               '2023-07-10 03:52:00+00:00',
               '2023-07-10 03:53:00+00:00',
               '2023-07-10 03:54:00+00:00',
               '2023-07-10 03:55:00+00:00',
               '2023-07-10 03:56:00+00:00',
               '2023-07-10 03:57:00+00:00',
               '2023-07-10 03:58:00+00:00',
            '2023-07-10 03:59:00+00:00'],
              dtype='datetime64[ns, UTC]', name='time', length=12960,
                freq=None)

Each metric requested will add at least one column to the dataframe:

>>> df.columns
Index(['distance_on_foot', 'apple_watch_exercise_time',
       'active_calories_burned', 'basal_calories_burned'],
        dtype='object')