foxglove.client (foxglove-client package)¶
foxglove.client is the Python client for the Foxglove API. It is published separately from the
SDK, as the foxglove-client package, and its source
is in the foxglove-python repository. The
torch and ray extras of foxglove-sdk install it.
This page describes foxglove-client 0.23. It covers the methods of
Client that work with datasets, episodes, data coverage, and custom
properties.
Pass timezone-aware datetime values for time arguments. The client converts them with
astimezone(), so a naive datetime is read as local time. Times in results, such as
created_at and start_time, are datetime objects. Result dictionaries use snake_case
keys. Values that the client passes through unchanged, such as creation_context and a
recording’s location, keep the API’s field names.
The REST API that these methods call is documented at https://docs.foxglove.dev/api.
The examples on this page use the client that the first example creates.
- class foxglove.client.Client¶
Client for the Foxglove API.
- __init__(token, host='api.foxglove.dev')¶
Create a client.
- Parameters:
token (str) – Required. API key sent with every request.
host (str) – Optional, default
"api.foxglove.dev". Host name of the API.
import os from foxglove.client import Client client = Client(token=os.environ["FOXGLOVE_API_TOKEN"])
Datasets¶
- Client.create_dataset(*, project_id, name, description=None, episode_ids=None)¶
Create a dataset, optionally seeding the first version with episodes.
- Parameters:
project_id (str) – Required. Project that owns the dataset.
name (str) – Required. 1–100 characters. Unique in the Project, case-insensitive.
description (str) – Optional, default
None. 1–500 characters.episode_ids (list[str]) – Optional, default
None. At most 2,000 episode IDs.
- Returns:
The dataset, with
id,project_id,name,description,creator_org_member_id,creator_api_key_id,created_at,updated_at,episode_count, and the countsadded,updated,removed, andalready_presentforepisode_ids.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 409 when the name is taken.
dataset = client.create_dataset( project_id="prj_123", name="Training candidates", episode_ids=["ep_1"], )
- Client.get_datasets(*, project_id=None, name=None, sort_by=None, sort_order=None, limit=None, cursor=None)¶
List datasets.
- Parameters:
project_id (str) – Optional, default
None. Restrict to one Project.name (str) – Optional, default
None. Case-insensitive substring of the dataset name.sort_by (str) – Optional, default
None, which sorts bycreated_at. One ofname,created_at,updated_at, orepisode_count.sort_order (str) – Optional, default
None.ascordesc.limit (int) – Optional, default
None, which returns up to 2,000 datasets. Page size, 0–2000.cursor (str) – Optional, default
None. Cursor from a previous page.
- Returns:
A page of datasets, each as
get_dataset()returns it.- Return type:
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
page = client.get_datasets(project_id="prj_123") for d in page.auto_paging_iter(): print(d["id"], d["name"], d["episode_count"])
- Client.get_dataset(*, dataset_id)¶
Return one dataset.
- Parameters:
dataset_id (str) – Required. Dataset ID.
- Returns:
The dataset, with
id,project_id,name,description,creator_org_member_id,creator_api_key_id,created_at,updated_at, andepisode_count.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the dataset does not exist.
dataset = client.get_dataset(dataset_id="dset_123") print(dataset["name"], dataset["episode_count"]) print(dataset["updated_at"].isoformat())
- Client.update_dataset(*, dataset_id, name=None, description=...)¶
Update a dataset’s name, description, or both.
- Parameters:
dataset_id (str) – Required. Dataset ID.
name (str) – Optional, default
None, which leaves the name unchanged. 1–100 characters.description (str or None) – Optional. 1–500 characters. Omit it to leave the description unchanged, or pass
Noneto clear it.
- Returns:
The updated dataset, as
get_dataset()returns it.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 409 when the name is taken.
dataset = client.update_dataset( dataset_id="dset_123", description=None )
- Client.delete_dataset(*, dataset_id)¶
Delete a dataset. Its episodes remain.
- Parameters:
dataset_id (str) – Required. Dataset ID.
- Returns:
None.- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the dataset does not exist.
scratch = client.create_dataset( project_id="prj_123", name="Scratch" ) client.delete_dataset(dataset_id=scratch["id"])
- Client.get_dataset_episodes(*, dataset_id, sort_by=None, sort_order=None, limit=None, cursor=None, start=None, end=None, has_missing_recordings=None, recording_id=None, properties_query=None, include_recordings=False, include_properties=False, include_creation_context=False)¶
List the episodes in a dataset’s latest committed version, or in its draft if no version is committed.
- Parameters:
dataset_id (str) – Required. Dataset ID.
sort_by (str) – Optional, default
None, which sorts byadded_at. One ofadded_at,created_at,start_time, orend_time.sort_order (str) – Optional, default
None.ascordesc.limit (int) – Optional, default
None, which returns up to 2,000 episodes. Page size, 0–2000.cursor (str) – Optional, default
None. Cursor from a previous page.start (datetime.datetime) – Optional, default
None. Start of a time range. Episodes whose time window overlaps the range are returned. Pass it together withend.end (datetime.datetime) – Optional, default
None. End of the time range.has_missing_recordings (bool) – Optional, default
None.Truereturns episodes with a missing recording.Falsereturns episodes whose recordings are all available.recording_id (str) – Optional, default
None. Return episodes that contain this recording.properties_query (str) – Optional, default
None. Space-separatedkey:valueterms. Episodes that match every term are returned.include_recordings (bool) – Optional, default
False. Addrecordingsto each episode.include_properties (bool) – Optional, default
False. Addpropertiesto each episode.include_creation_context (bool) – Optional, default
False. Addcreation_contextto each episode.
- Returns:
A page of dicts with
added_at,added_in_version,has_missing_recordings, andepisode, which has the keys thatget_episodes()lists.- Return type:
- Raises:
ValueError – If only one of
startandendis given.requests.exceptions.HTTPError – If the API returns an error, for example 404 when the dataset does not exist.
page = client.get_dataset_episodes(dataset_id="dset_123") for m in page.auto_paging_iter(): print(m["episode"]["id"], m["added_in_version"])
- Client.update_dataset_episodes(*, dataset_id, add=None, remove=None, update=None)¶
Stage episode additions, removals, and episode version changes in a dataset’s draft.
- Parameters:
dataset_id (str) – Required. Dataset ID.
add (list) – Optional, default
None. At most 2,000 episodes to add. Each item is an episode ID, which selects the latest episode version, or a dict{"id": ..., "version": ...}in whichversionis optional.remove (list[str]) – Optional, default
None. At most 2,000 episode IDs to remove.update (list) – Optional, default
None. At most 2,000 episodes in the draft whose episode version changes, in the same forms asadd.
- Returns:
The counts
added,updated,removed, andalready_present.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example when an episode is in
updateand also inaddorremove.
client.update_dataset_episodes( dataset_id="dset_123", add=["ep_new"], remove=["ep_old"] )
- Client.get_dataset_versions(*, dataset_id, sort_order=None, limit=None, cursor=None)¶
List a dataset’s versions: its committed versions and its draft.
- Parameters:
dataset_id (str) – Required. Dataset ID.
sort_order (str) – Optional, default
None.ascordesc.limit (int) – Optional, default
None, which returns up to 2,000 versions. Page size, 0–2000.cursor (str) – Optional, default
None. Cursor from a previous page.
- Returns:
A page of versions, each with
version_number,description,created_at,committed_at,committed_by_org_member_id,committed_by_api_key_id,episode_count,added_episode_count,removed_episode_count, andchanged_episode_count. The draft’scommitted_atisNone.- Return type:
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the dataset does not exist.
page = client.get_dataset_versions(dataset_id="dset_123") for v in page.auto_paging_iter(): print(v["version_number"], v["committed_at"])
- Client.get_dataset_version(*, dataset_id, version_number)¶
Return one dataset version.
- Parameters:
dataset_id (str) – Required. Dataset ID.
version_number (int) – Required. Dataset version number.
- Returns:
The version, with
version_number,description,created_at,committed_at,committed_by_org_member_id,committed_by_api_key_id,episode_count,added_episode_count,removed_episode_count,changed_episode_count, andhas_missing_recordings.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the version does not exist.
v = client.get_dataset_version( dataset_id="dset_123", version_number=2 )
- Client.update_dataset_version(*, dataset_id, version_number, description)¶
Set the description of a committed version or of the draft.
- Parameters:
dataset_id (str) – Required. Dataset ID.
version_number (int) – Required. Dataset version number.
description (str or None) – Required. New description, 1–2048 characters, or
Noneto clear it.
- Returns:
The version, as
get_dataset_version()returns it.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the version does not exist.
client.update_dataset_version( dataset_id="dset_123", version_number=2, description=None, )
- Client.get_dataset_version_episodes(*, dataset_id, version_number, sort_by=None, sort_order=None, limit=None, cursor=None, start=None, end=None, has_missing_recordings=None, recording_id=None, properties_query=None, include_recordings=False, include_properties=False, include_creation_context=False)¶
List the episodes in one dataset version, at the episode versions it pins.
- Parameters:
dataset_id (str) – Required. Dataset ID.
version_number (int) – Required. Dataset version number.
sort_by (str) – Optional, default
None, which sorts byadded_at. One ofadded_at,created_at,start_time, orend_time.sort_order (str) – Optional, default
None.ascordesc.limit (int) – Optional, default
None, which returns up to 2,000 episodes. Page size, 0–2000.cursor (str) – Optional, default
None. Cursor from a previous page.start (datetime.datetime) – Optional, default
None. Start of a time range. Episodes whose time window overlaps the range are returned. Pass it together withend.end (datetime.datetime) – Optional, default
None. End of the time range.has_missing_recordings (bool) – Optional, default
None.Truereturns episodes with a missing recording.Falsereturns episodes whose recordings are all available.recording_id (str) – Optional, default
None. Return episodes that contain this recording.properties_query (str) – Optional, default
None. Space-separatedkey:valueterms. Episodes that match every term are returned.include_recordings (bool) – Optional, default
False. Addrecordingsto each episode.include_properties (bool) – Optional, default
False. Addpropertiesto each episode.include_creation_context (bool) – Optional, default
False. Addcreation_contextto each episode.
- Returns:
A page of dicts with
added_at,added_in_version,has_missing_recordings, andepisode, which has the keys thatget_episodes()lists.- Return type:
- Raises:
ValueError – If only one of
startandendis given.requests.exceptions.HTTPError – If the API returns an error, for example 404 when the version does not exist.
page = client.get_dataset_version_episodes( dataset_id="dset_123", version_number=2 ) for m in page.auto_paging_iter(): print(m["episode"]["id"], m["episode"]["version"])
- Client.compare_dataset_versions(*, dataset_id, version_number, base_version, limit=None, cursor=None, include_recordings=False, include_properties=False, include_creation_context=False)¶
Return the episodes added, removed, or changed from
base_versiontoversion_number.- Parameters:
dataset_id (str) – Required. Dataset ID.
version_number (int) – Required. Target version.
base_version (int) – Required. Base version.
limit (int) – Optional, default
None, which returns up to 2,000 changes. Page size, 0–2000.cursor (str) – Optional, default
None.next_cursorfrom a previous call.include_recordings (bool) – Optional, default
False. Addrecordingsto each episode.include_properties (bool) – Optional, default
False. Addpropertiesto each episode.include_creation_context (bool) – Optional, default
False. Addcreation_contextto each episode.
- Returns:
A dict with
changes,added_count,removed_count,changed_count, andnext_cursor. Each change hasadded_at,added_in_version,episode, andchange, which isadded,removed, orchanged. A changed episode also hasprevious_versionandprevious_episode. The counts are totals across all pages.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when a version does not exist.
diff = client.compare_dataset_versions( dataset_id="dset_123", version_number=2, base_version=1 )
- Client.commit_dataset(*, dataset_id, description=...)¶
Commit the draft as a new version and open the next draft.
- Parameters:
dataset_id (str) – Required. Dataset ID.
description (str or None) – Optional. Description of the committed version, 1–2048 characters. Omit it to keep the draft’s description, or pass
Noneto clear it.
- Returns:
A dict with
committedandeditable_version_number.committedis the committed version, with the keys thatget_dataset_versions()lists.editable_version_numberis the number of the new draft.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 409 when the draft has no changes.
client.commit_dataset( dataset_id="dset_123", description="Labels batch 12" )
- Client.discard_dataset(*, dataset_id)¶
Discard the staged changes in a dataset’s draft.
- Parameters:
dataset_id (str) – Required. Dataset ID.
- Returns:
The counts
discarded_adds,discarded_removes, anddiscarded_updates.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the dataset does not exist.
counts = client.discard_dataset(dataset_id="dset_123") for name, count in counts.items(): print(name, count)
- Client.restore_dataset_version(*, dataset_id, version_number, force=False)¶
Stage the changes that make the draft match a committed version.
- Parameters:
dataset_id (str) – Required. Dataset ID.
version_number (int) – Required. Committed version to restore.
force (bool) – Optional, default
False. Replace the pending changes in the draft.
- Returns:
The counts
added,updated,removed,discarded_adds,discarded_removes, anddiscarded_updates.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 409 when the draft has pending changes and
forceisFalse.
client.restore_dataset_version( dataset_id="dset_123", version_number=1 )
- Client.clone_dataset_version(*, dataset_id, version_number, name, description=None, include_history=None)¶
Create a new dataset from a committed version.
- Parameters:
dataset_id (str) – Required. Source dataset ID.
version_number (int) – Required. Committed version to clone.
name (str) – Required. Name of the new dataset, 1–100 characters. Unique in the Project, case-insensitive.
description (str) – Optional, default
None. 1–500 characters.include_history (bool) – Optional, default
None, which the API treats asFalse.Truecopies every version up to and including the cloned one.
- Returns:
The new dataset, as
get_dataset()returns it.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 409 when the name is taken.
client.clone_dataset_version( dataset_id="dset_123", version_number=2, name="eval-holdout", )
- Client.download_dataset(*, dataset_id, version_number, output_directory, topics=None, include_properties=False)¶
Export a committed version to a directory, as one MCAP file per episode and a
manifest.json.- Parameters:
dataset_id (str) – Required. Dataset ID.
version_number (int) – Required. Committed version number.
output_directory (str or os.PathLike) – Required. An empty directory, or a path that does not exist yet.
topics (list[str]) – Optional, default
None, which exports every topic. Topics to export.include_properties (bool) – Optional, default
False. Add each episode’s custom properties to the manifest.
- Returns:
The output directory.
- Return type:
pathlib.Path
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
RuntimeError – If the version is not committed, an episode in it has a missing recording,
output_directoryis a file or a directory with contents, or every episode fails to download.OSError – If a file cannot be written or a transfer is interrupted.
- Warns:
DatasetDownloadWarning– If some episodes fail to download. The manifest records each one.
client.download_dataset( dataset_id="dset_123", version_number=2, output_directory="out", )
Episodes¶
- Client.create_episodes(*, project_id, episodes)¶
Get or create up to 2,000 episodes. An item returns an existing episode when the time range, recordings, and custom properties of its latest version match.
- Parameters:
project_id (str) – Required. Project that owns the episodes.
episodes (list[dict]) – Required. 1–2000 items. Each item has exactly one of
recordings, a list of recording IDs, orevent_id. An item withrecordingscan setstart_timeandend_time, and takes its time range from the recordings when they are omitted. An item withevent_idtakes the event’s time range and the completed recordings of its device that overlap it. Any item can setproperties, a dict of episode custom property values. Allrecordingslists together hold at most 100,000 recordings, and allevent_iditems together resolve to at most 10,000.
- Returns:
One dict per item, in request order, with
idandcreated.createdisFalsefor an existing episode.- Return type:
list[dict]
- Raises:
ValueError – If an item has both or neither of
recordingsandevent_id, or hasevent_idtogether withstart_timeorend_time.requests.exceptions.HTTPError – If the API returns an error.
from datetime import datetime, timezone episodes = client.create_episodes( project_id="prj_123", episodes=[ { "recordings": ["rec_1"], "start_time": datetime( 2026, 11, 2, 18, 0, tzinfo=timezone.utc ), "end_time": datetime( 2026, 11, 2, 18, 5, tzinfo=timezone.utc ), "properties": {"task": "fold_towel"}, } ], )
- Client.get_episodes(*, project_id=None, start=None, end=None, has_missing_recordings=None, recording_id=None, exact_recording_ids=None, properties_query=None, sort_by=None, sort_order=None, limit=None, cursor=None, include_recordings=False, include_properties=False, include_creation_context=False)¶
List episodes, each at its latest version.
- Parameters:
project_id (str) – Optional, default
None. Restrict to one Project.start (datetime.datetime) – Optional, default
None. Start of a time range. Episodes whose time window overlaps the range are returned. Pass it together withend.end (datetime.datetime) – Optional, default
None. End of the time range.has_missing_recordings (bool) – Optional, default
None.Truereturns episodes with a missing recording.Falsereturns episodes whose recordings are all available.recording_id (str) – Optional, default
None. Return episodes that contain this recording.exact_recording_ids (list[str]) – Optional, default
None. Return episodes whose recordings are exactly these 1–50 recording IDs.properties_query (str) – Optional, default
None. Space-separatedkey:valueterms. Episodes that match every term are returned.sort_by (str) – Optional, default
None, which sorts bycreated_at. One ofcreated_at,start_time, orend_time.sort_order (str) – Optional, default
None.ascordesc.limit (int) – Optional, default
None, which returns up to 2,000 episodes. Page size, 0–2000.cursor (str) – Optional, default
None. Cursor from a previous page.include_recordings (bool) – Optional, default
False. Addrecordingsandhas_missing_recordingsto each episode.include_properties (bool) – Optional, default
False. Addpropertiesto each episode.include_creation_context (bool) – Optional, default
False. Addcreation_contextto each episode.
- Returns:
A page of episodes, each with
id,project_id,start_time,end_time,version,latest_version,creator_org_member_id,creator_api_key_id, andcreated_at. Each item ofrecordingshasid,path,location,start,end,device_id, andavailable.- Return type:
- Raises:
ValueError – If only one of
startandendis given, orexact_recording_idsis empty.requests.exceptions.HTTPError – If the API returns an error.
page = client.get_episodes(project_id="prj_123")
- Client.get_episode(*, episode_id, include_recordings=False, include_properties=False, version=None)¶
Return one episode.
- Parameters:
episode_id (str) – Required. Episode ID.
include_recordings (bool) – Optional, default
False. Addrecordingsandhas_missing_recordings.include_properties (bool) – Optional, default
False. Addproperties.version (int) – Optional, default
None, which selects the latest version. Episode version to return.
- Returns:
The episode, with
id,project_id,start_time,end_time,version,latest_version,creator_org_member_id,creator_api_key_id,created_at, andcreation_context. Each item ofrecordingshasid,path,location,start,end,device_id, andavailable.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the episode does not exist.
episode = client.get_episode(episode_id="ep_123")
- Client.update_episode(*, episode_id, applies_to_version=None, start_time=None, end_time=None, recordings=None, properties=None)¶
Update one episode. An update that changes the episode creates a new episode version.
- Parameters:
episode_id (str) – Required. Episode ID.
applies_to_version (int) – Optional, default
None. Episode version that the update applies to. The API rejects the update when it is not the latest version.start_time (datetime.datetime) – Optional, default
None. New inclusive start of the episode window.end_time (datetime.datetime) – Optional, default
None. New inclusive end of the episode window.recordings (dict) – Optional, default
None. Recording IDs to add and remove, as{"add": [...], "remove": [...]}.properties (dict) – Optional, default
None. Custom property values to merge into the episode’s properties. A value ofNoneunsets its key.
- Returns:
The episode at the resulting version, with the keys that
get_episodes()lists.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example when
applies_to_versionis not the latest version.
client.update_episode( episode_id="ep_123", properties={"outcome": "success"} )
- Client.update_episodes(*, episodes)¶
Update up to 2,000 episodes in one transaction. If one update fails, none is applied.
- Parameters:
episodes (list[dict]) – Required. At most 2,000 items. Each item has
idand can setapplies_to_version,start_time,end_time,recordings, andproperties, which have the same meaning as the parameters ofupdate_episode().- Returns:
One dict per item, in request order, with
idandversion, the episode’s resulting version.- Return type:
list[dict]
- Raises:
KeyError – If an item has no
id.requests.exceptions.HTTPError – If the API returns an error.
client.update_episodes( episodes=[ { "id": "ep_123", "properties": {"outcome": "success"}, } ] )
- Client.delete_episode(*, episode_id)¶
Delete an episode that no dataset holds.
- Parameters:
episode_id (str) – Required. Episode ID.
- Returns:
None.- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 409 when a dataset holds the episode.
client.delete_episode(episode_id="ep_123")
- Client.get_episode_versions(*, episode_id, limit=None, cursor=None)¶
List an episode’s versions, newest first.
- Parameters:
episode_id (str) – Required. Episode ID.
limit (int) – Optional, default
None, which returns up to 2,000 versions. Page size, 0–2000.cursor (str) – Optional, default
None. Cursor from a previous page.
- Returns:
A page of dicts with
version,created_at,creator_org_member_id,creator_api_key_id, andchanged_fields.- Return type:
- Raises:
requests.exceptions.HTTPError – If the API returns an error, for example 404 when the episode does not exist.
page = client.get_episode_versions(episode_id="ep_123")
- Client.iter_messages(*, device_id=None, device_name=None, session_id=None, session_key=None, start=None, end=None, topics=None, decoder_factories=None, project_id=None, episode_id=None, episode_version=None, recording_id=None, recording_key=None, replay_policy=None, replay_lookback_seconds=None)¶
Stream decoded messages. Messages are returned in log-time order across the selected topics.
startandendare required unlessepisode_idis given, orrecording_idorrecording_keyis given without a device.- Parameters:
device_id (str) – Optional, default
None. Device that originated the data. Requiresstartandend.device_name (str) – Optional, default
None. Name of the device that originated the data. Requiresstartandend.session_id (str) – Optional, default
None. Session to stream. Requiresstartandend.session_key (str) – Optional, default
None. Key of the session to stream. Requiresstartandend.start (datetime.datetime) – Optional, default
None. Inclusive start of the stream. Pass it together withend.end (datetime.datetime) – Optional, default
None. Inclusive end of the stream.topics (list[str]) – Optional, default
None, which streams every topic. Topics to stream.decoder_factories (list[DecoderFactory]) – Optional, default
None, which uses the client’s default decoders: JSON, plus Protobuf, ROS 1, and ROS 2 when the matchingmcapsupport package is installed. MCAP decoder factories to use instead.project_id (str) – Optional, default
None. Project of the device or session. Required withsession_key, and withdevice_namewhen the name exists in more than one Project.episode_id (str) – Optional, default
None. Episode to stream. Its time range is used whenstartandendare omitted.episode_version (int) – Optional, default
None, which selects the latest version. Episode version to stream. Requiresepisode_id.recording_id (str) – Optional, default
None. Recording to stream.recording_key (str) – Optional, default
None. Key of the recording to stream.replay_policy (str) – Optional, default
None.lastPerChanneladds the most recent message on each channel from beforestart.replay_lookback_seconds (float) – Optional, default
None. How far beforestartto look for those messages. Used withreplay_policy="lastPerChannel".
- Returns:
A generator of
(schema, channel, message, decoded_message)tuples.- Raises:
RuntimeError – If no device, session, recording, or episode is given,
episode_idis combined with another of them, a recording is combined with a session,episode_versionis given withoutepisode_id, orstartandendare missing when required.requests.exceptions.HTTPError – If the API returns an error.
for schema, channel, message, decoded in client.iter_messages( recording_id="rec_123", topics=["/camera/front"], ): print(channel.topic, message.log_time)
- Client.download_data(*, device_id=None, device_name=None, session_id=None, session_key=None, start=None, end=None, topics=None, output_format=OutputFormat.mcap, compression_format=None, callback=None, project_id=None, episode_id=None, episode_version=None, include_attachments=None, recording_id=None, recording_key=None, replay_policy=None, replay_lookback_seconds=None)¶
Download the data of a device, session, recording, or episode as bytes.
startandendare required unlessepisode_idis given, orrecording_idorrecording_keyis given without a device.- Parameters:
device_id (str) – Optional, default
None. Device that originated the data. Requiresstartandend.device_name (str) – Optional, default
None. Name of the device that originated the data. Requiresstartandend.session_id (str) – Optional, default
None. Session to download. Requiresstartandend.session_key (str) – Optional, default
None. Key of the session to download. Requiresstartandend.start (datetime.datetime) – Optional, default
None. Inclusive start of the time range. Pass it together withend.end (datetime.datetime) – Optional, default
None. Inclusive end of the time range.topics (list[str]) – Optional, default
None, which downloads every topic. Topics to download.output_format (OutputFormat) – Optional, default
OutputFormat.mcap. Format of the returned data.compression_format (CompressionFormat) – Optional, default
None, for which the API uses LZ4. Compression of the chunks in MCAP output.callback – Optional, default
None. A function that the client calls ascallback(progress=n)during the download, wherenis the number of bytes received so far.project_id (str) – Optional, default
None. Project of the device or session. Required withsession_key, and withdevice_namewhen the name exists in more than one Project.episode_id (str) – Optional, default
None. Episode to download. Its time range is used whenstartandendare omitted.episode_version (int) – Optional, default
None, which selects the latest version. Episode version to download. Requiresepisode_id.include_attachments (bool) – Optional, default
None. Include MCAP attachments. Applies to MCAP output for a recording, session, or episode.recording_id (str) – Optional, default
None. Recording to download.recording_key (str) – Optional, default
None. Key of the recording to download.replay_policy (str) – Optional, default
None.lastPerChanneladds the most recent message on each channel from beforestart.replay_lookback_seconds (float) – Optional, default
None. How far beforestartto look for those messages. Used withreplay_policy="lastPerChannel".
- Returns:
The data in
output_format.- Return type:
bytes
- Raises:
RuntimeError – If no device, session, recording, or episode is given,
episode_idis combined with another of them, a recording is combined with a session,episode_versionis given withoutepisode_id, orstartandendare missing when required.requests.exceptions.HTTPError – If the API returns an error.
data = client.download_data( episode_id="ep_123", topics=["/camera/front"] )
- Client.get_topics(*, device_id=None, device_name=None, start=None, end=None, include_schemas=False, project_id=None, session_id=None, session_key=None, episode_id=None, limit=None, offset=None, recording_id=None, recording_key=None, episode_version=None, sort_by=None, sort_order=None)¶
List the topics of a device, session, recording, or episode.
startandendare required withdevice_idordevice_name. Session, recording, and episode queries can omit them.- Parameters:
device_id (str) – Optional, default
None. Device to list topics for.device_name (str) – Optional, default
None. Name of the device to list topics for.start (datetime.datetime) – Optional, default
None. Start of the time range. Pass it together withend.end (datetime.datetime) – Optional, default
None. End of the time range.include_schemas (bool) – Optional, default
False. Addschemato each topic.project_id (str) – Optional, default
None. Restrict to one Project.session_id (str) – Optional, default
None. Session to list topics for.session_key (str) – Optional, default
None. Key of the session to list topics for.episode_id (str) – Optional, default
None. Episode to list topics for. Its time range is used whenstartandendare omitted.limit (int) – Optional, default
None, which returns up to 2,000 topics. Page size, 0–2000.offset (int) – Optional, default
None. Number of topics to skip.recording_id (str) – Optional, default
None. Recording to list topics for.recording_key (str) – Optional, default
None. Key of the recording to list topics for.episode_version (int) – Optional, default
None, which selects the latest version. Episode version to list topics for. Requiresepisode_id.sort_by (str) – Optional, default
None.topicorversion.sort_order (str) – Optional, default
None.ascordesc.
- Returns:
One dict per topic, with
topic,version,encoding,schema_encoding, andschema_name. Withinclude_schemas, each also hasschema, asbytesorNonewhen no schema is available.- Return type:
list[dict]
- Raises:
RuntimeError – If
episode_versionis given withoutepisode_id,episode_idis combined with a device, session, or recording, orstartandendare missing when required.requests.exceptions.HTTPError – If the API returns an error.
topics = client.get_topics(episode_id="ep_123") print([t["topic"] for t in topics])
Data coverage¶
- Client.get_coverage(*, start=None, end=None, device_id=None, device_name=None, tolerance=None, project_id=None, session_id=None, session_key=None, recording_id=None, recording_key=None, include_edge_recordings=None)¶
List the time ranges for which Foxglove has data.
- Parameters:
start (datetime.datetime) – Optional, default
None. Start of the time range. Required withendunless a recording or session is given.end (datetime.datetime) – Optional, default
None. End of the time range.device_id (str) – Optional, default
None. Restrict to one device.device_name (str) – Optional, default
None. Restrict to the device with this name.tolerance (int) – Optional, default
None. Minimum gap, in seconds, for two ranges to count as separate.project_id (str) – Optional, default
None. Restrict to one Project.session_id (str) – Optional, default
None. Restrict to one session.session_key (str) – Optional, default
None. Restrict to the session with this key.recording_id (str) – Optional, default
None. Restrict to one recording.recording_key (str) – Optional, default
None. Restrict to the recording with this key.include_edge_recordings (bool) – Optional, default
None, which the API treats asFalse. Include recordings from an Edge Site or a device running Foxlet. Each range then has animport_status.
- Returns:
One dict per range, with
device_id,device,start,end, andimport_status.deviceis the device summary as the API returns it.- Return type:
list[dict]
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
from datetime import datetime, timezone ranges = client.get_coverage( device_id="dev_123", start=datetime(2026, 11, 2, tzinfo=timezone.utc), end=datetime(2026, 11, 3, tzinfo=timezone.utc), )
Custom properties¶
The properties of an episode use keys that are defined as custom properties with
resource_type="episode".
- Client.create_custom_property(*, key, label, resource_type, value_type, enum_values=None)¶
Create a custom property.
- Parameters:
key (str) – Required. Immutable identifier used in queries. 1–32 characters from
A-Z,a-z,0-9,_, and-.label (str) – Required. Display label, 1–32 characters.
resource_type (str) – Required.
device,event,session, orepisode.value_type (str) – Required.
string,multiline-string,number,enum,boolean, ormulti-enum.enum_values (list[str]) – Optional, default
None. Allowed values. Required whenvalue_typeisenumormulti-enum.
- Returns:
The custom property, with
id,key,label,resource_type,value_type,enum_values, andhas_associated_data.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
client.create_custom_property( key="outcome", label="Outcome", resource_type="episode", value_type="enum", enum_values=["success", "failure"], )
- Client.get_custom_properties(*, resource_type=None)¶
List custom properties.
- Parameters:
resource_type (str) – Optional, default
None, which returns every type.device,event,session, orepisode.- Returns:
The custom properties, each as
get_custom_property()returns it.- Return type:
list[dict]
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
props = client.get_custom_properties(resource_type="episode")
- Client.get_custom_property(*, custom_property_id)¶
Return one custom property.
- Parameters:
custom_property_id (str) – Required. Custom property ID.
- Returns:
The custom property, with
id,key,label,resource_type,value_type,enum_values, andhas_associated_data.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
prop = client.get_custom_property(custom_property_id="cp_123")
- Client.update_custom_property(*, custom_property_id, label=None, enum_values=None)¶
Update a custom property’s label, allowed values, or both.
- Parameters:
custom_property_id (str) – Required. Custom property ID.
label (str) – Optional, default
None, which leaves the label unchanged. New display label, 1–32 characters.enum_values (list[str]) – Optional, default
None, which leaves the values unchanged. New list of allowed values. It contains every existing value and can add or reorder values.
- Returns:
The custom property, as
get_custom_property()returns it.- Return type:
dict
- Raises:
requests.exceptions.HTTPError – If the API returns an error.
client.update_custom_property( custom_property_id="cp_123", label="Outcome" )
- Client.delete_custom_property(*, custom_property_id)¶
Delete a custom property.
- Parameters:
custom_property_id (str) – Required. Custom property ID.
- Returns:
None.- Raises:
requests.exceptions.HTTPError – If the API returns an error.
client.delete_custom_property(custom_property_id="cp_123")
Supporting types¶
- class foxglove.client.Page¶
One page of results from a list method.
- items¶
The results on this page, as a list.
- next_cursor¶
Cursor of the next page, or
Noneon the last page.
- previous_cursor¶
Cursor of the previous page, or
Nonewhen the API returns none.
- auto_paging_iter()¶
Yield the results on this page, then fetch each following page and yield its results.
- Returns:
An iterator over the results.
- Raises:
requests.exceptions.HTTPError – If the API returns an error for a following page.
for dataset in client.get_datasets().auto_paging_iter(): print(dataset["name"])
- class foxglove.client.DatasetDownloadWarning¶
Warning that
Client.download_dataset()emits when some episodes fail to download. A subclass ofUserWarning.
- class foxglove.client.OutputFormat¶
Output formats for
Client.download_data(). Anenum.Enum.- bag = "bag1"¶
A
.bagfile.
- mcap = "mcap"¶
An
.mcapfile.
- mcap0 = "mcap0"¶
Deprecated. Use
mcap.
- class foxglove.client.CompressionFormat¶
Chunk compression formats for
Client.download_data(). Anenum.Enum.- none = ""¶
No compression.
- zstd = "zstd"¶
Zstandard compression.
- lz4 = "lz4"¶
LZ4 compression.