🐝 broodminder-data
Make BroodMinder beehive data easily accessible across diverse consumption use cases — bulk export, periodic delta sync, OpenAPI 3.1, and AI agents via MCP.
broodminder-data provides a unified developer platform for BroodMinder beehive sensor telemetry (internal/ambient temperature, relative humidity, scale weight, swarm indicators, acoustics, radar, and inspection notes). This project provides a published OpenAPI 3.1 specification, a Python CLI and client SDK, and a Model Context Protocol (MCP) server for AI agents.
5 Core Consumption Modalities
┌──────────────────────────────────────────────┐
│ BroodMinder Cloud API │
└──────────────────────┬───────────────────────┘
│
┌───────────▼───────────┐
│ broodminder-data │
└───────────┬───────────┘
│
┌──────────────────┬───────────────┼───────────────┬──────────────────┐
▼ ▼ ▼ ▼ ▼
📦 Bulk Export 🔄 Delta Sync 📜 OpenAPI 3.1 🤖 MCP Server 🐍 Python SDK / CLI
Full history Incremental Published spec Claude, Cursor, Typed models &
JSON / CSV / NDJSON catch-up cron & Redocly docs Antigravity CLI scriptable client
- 📦 Bulk Historical Export: Walks your entire apiary → hive → device hierarchy with rate-limit-aware, resumable 180-day windowing to extract complete multi-year histories into compressed JSON, NDJSON, and CSV.
- 🔄 Periodic Delta Sync: Lightweight, incremental polling engine designed for regular cron or background services, fetching only new readings since the last checkpoint while buffering for late-arriving BLE uploads.
- 📜 Published OpenAPI 3.1 Specification: Formal, validated OpenAPI 3.1 contract covering all observed endpoints, query parameters, error responses (including HTTP 412 auth responses), and canonical telemetry schemas.
- 🤖 Model Context Protocol (MCP) Server: Native MCP integration (
broodminder-mcp) connecting AI agents (Claude Desktop, Antigravity CLI, Cursor, Windsurf, Claude Code) directly to hive metrics, temperature trends, weight deltas, and notes. - 🐍 Unified Python Client Library & CLI: Strongly-typed domain models, offline sandbox mode, and a standalone
broodminderCLI.
Architecture Discussions & Roadmap
We are tracking each expanded capability in GitHub Discussions. Join the conversation:
- 💬 Discussion #148: Periodic Delta Sync Engine for Incremental Telemetry & Continuous Ingestion
- 💬 Discussion #149: Published OpenAPI 3.1 Specification & Interactive Documentation (Redocly/Swagger)
- 💬 Discussion #150: Model Context Protocol (MCP) Server for Hive Monitoring & AI Agent Integration
- 💬 Discussion #151: Unified Python Client SDK and Standalone CLI Library
Table of Contents
- Features
- What You Get
- Get an API Key
- Installation
- Configuration
- Quickstart Usage
- 🔋 Battery Health & Offline Sensor Monitoring
- OpenAPI 3.1 Specification & Interactive Docs
- Model Context Protocol (MCP) Server
- Python SDK Usage
- PyPI Packaging & Automated Publishing
- Output Files & Schema
- API Behavior & Rate Limits
- Testing & Quality Gates
- Project Structure
- Privacy & Security
- Contributing
- License
Features
- 📦 Complete export — walks every apiary → hive → device and pulls all readings and notes across your entire history.
- 🔁 Resumable — checkpoints each time window; stop and re-run anytime and it skips what's already fetched.
- 🚦 Rate-limit-aware — respects the ~1000 calls/day cap, self-throttles, and resumes cleanly after a
429. - 🧹 Idempotent outputs — de-duplicates overlapping windows, so re-runs never double-count.
- 🗜️ Compact — raw and flattened outputs are gzipped (a multi-year, 90-hive account is tens of MB).
- 📜 OpenAPI 3.1 spec — formal machine-readable API definition with Redocly validation.
- 🤖 Agent-ready — MCP server architecture for conversational hive analysis and automated inspections.
- 🧪 Contract-tested — live contract test suite pins the API's real behavior and acts as a canary when upstream changes.
- 🔌 Reusable client —
bm/client.pyis transport-clean and easy to lift into a notebook, script, or MCP server.
What You Get
A flattened, analysis-ready row per reading:
| field | description |
|---|---|
apiaryId, apiaryName |
apiary the hive belongs to |
hiveId, hiveName |
hive identity |
positionID, deviceId |
sensor position + device (deviceId is the unique series key) |
timestamp, datetime |
Unix epoch seconds (UTC) + ISO-8601 string |
batteryLevel, chargeRemaining |
device power (nullable; the two alternate) |
m_temperature |
temperature (all devices) |
m_humidity |
relative humidity (humidity-capable devices) |
m_weight |
scale weight (hives with a scale) |
m_swarmState |
BroodMinder swarm indicator |
m_audio |
acoustic reading (audio-capable devices; unit/scale unconfirmed) |
m_radar |
movement/activity indicator (radar-equipped devices) |
Metric presence varies by device type — temperature is near-universal; weight appears only on hives with a scale; audio and radar appear on specialized monitors.
Get an API Key
The External User API is in alpha. Request a key from BroodMinder (support@broodminder.com). The key is tied to your account and only authorizes access to your own data.
Installation
From PyPI
# Core package
pip install broodminder-data
# With Model Context Protocol (MCP) agent support:
pip install "broodminder-data[mcp]"
From Source (Local Development)
git clone https://github.com/petry-projects/broodminder-data.git
cd broodminder-data
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pip install -e ".[mcp,dev]"
Requires Python 3.10+.
Configuration
cp .env.example .env
Edit .env and paste your key:
BROODMINDER_API_KEY=your-api-key-here
BROODMINDER_BASE_URL=https://external-api.mybroodminder.com
.env is git-ignored and never leaves your machine.
Quickstart Usage
1. Discover Account Topology
Confirm auth and see your apiaries, hives, and a sensor data sample:
.venv/bin/python scripts/discover.py
2. Bulk History Export
Pull historical telemetry (resumable; respects the daily quota):
.venv/bin/python scripts/extract_all.py --start 2025-01-01
Options:
| flag | default | purpose |
|---|---|---|
--start YYYY-MM-DD |
2021-01-01 |
history start |
--end YYYY-MM-DD |
today (UTC) | history end |
--catchup |
off | resume forward from each hive's latest completed window in manifest.json |
--window-days N |
180 |
request window size (API caps at ~6 months) |
--apiary NAME|ID |
all | limit to one apiary (repeatable) |
--max-calls N |
900 |
stop before this many API calls (daily-cap guard) |
--reverse |
off | walk newest→oldest (for backfilling) |
--stop-after-empty N |
0 |
with --reverse, stop a hive after N empty windows |
--no-notes |
off | skip the notes endpoint |
3. Incremental Catch-up Sync
Resume forward from each hive's latest extracted window:
.venv/bin/python scripts/extract_all.py --catchup
4. Build Analysis-Ready Datasets
Convert raw windows into clean, de-duplicated NDJSON and CSV:
.venv/bin/python scripts/flatten.py --merge
5. Inspect Battery Health & Offline Sensors
Identify sensors that have low batteries or stopped reporting:
.venv/bin/python scripts/battery_health.py
# or via entrypoint: broodminder-battery
🔋 Battery Health & Offline Sensor Monitoring
Answers the critical question: "What batteries are low and need to be changed?"
In beehive deployments, two distinct conditions indicate battery replacement or inspection:
- Low Battery (<80%): Cold cluster and winter ambient temperatures accelerate coin-cell and alkaline voltage dropoff. Sensors dipping below 80% should be checked or replaced before winter cluster closure.
- "Not Reporting" (Silent Dropouts): When a battery fully dies in the field, the sensor simply goes dark. Sensors that have not reported data for more than 7 days are flagged as stale.
# Scan local dataset and show devices needing attention (<80% or >7d stale)
.venv/bin/python scripts/battery_health.py
# Show all devices including healthy ones
.venv/bin/python scripts/battery_health.py --all
# Custom warning thresholds
.venv/bin/python scripts/battery_health.py --threshold 75 --stale-days 5
# Filter by apiary
.venv/bin/python scripts/battery_health.py --apiary "Home"
# Export as JSON or CSV
.venv/bin/python scripts/battery_health.py --format json
.venv/bin/python scripts/battery_health.py --format csv
# Automation/Alerting mode (exits with code 1 if devices need attention)
.venv/bin/python scripts/battery_health.py --check
OpenAPI 3.1 Specification & Interactive Docs
broodminder-data maintains a formal OpenAPI 3.1 specification (also accessible via the root symlink openapi.yaml).
Local Linting & Preview
Using Redocly CLI:
# Lint specification against OpenAPI 3.1 rules
npx @redocly/cli lint openapi.yaml
# Launch interactive documentation preview server
npx @redocly/cli preview-docs openapi.yaml
Model Context Protocol (MCP) Server
Connect your hive data directly to AI agents (Claude Desktop, Antigravity CLI, Cursor, Windsurf, Claude Code):
Agent Configuration (claude_desktop_config.json or mcp.json)
{
"mcpServers": {
"broodminder": {
"command": "python3",
"args": ["-m", "bm.mcp_server"],
"env": {
"BROODMINDER_API_KEY": "your-api-key-here"
}
}
}
}
Core MCP Tools
get_apiary_summary: High-level inventory of apiaries, hives, and device counts.get_hive_status: Latest sensor telemetry (brood temperature, ambient temperature, humidity, weight).get_telemetry_trends: Time-series rollups (min, max, mean, delta) over specified lookback windows.get_hive_notes: Recent inspection notes, treatments, and queen observations.get_device_health: Battery levels and sync freshness across sensors.
Python SDK Usage
from bm.client import BroodMinderClient
# Automatically reads BROODMINDER_API_KEY from environment or .env
client = BroodMinderClient()
# List apiaries and hives
apiaries = client.get_apiaries()
for apiary in apiaries:
print(f"Apiary: {apiary['name']} (ID: {apiary['apiary_id']})")
hives = client.get_hives(apiary_id=apiary['apiary_id'])
for hive in hives:
print(f" - Hive: {hive['name']}")
# Fetch time-series readings for a device (epoch seconds)
readings = client.get_device_readings(
device_id="42:11:22:33:44:55",
start=1704067200, # 2024-01-01T00:00:00Z
end=1706745600, # 2024-02-01T00:00:00Z
)
print(f"Fetched {len(readings)} readings")
PyPI Packaging & Automated Publishing
broodminder-data uses automated, tokenless PyPI Trusted Publishing (OIDC).
1. Tokenless Trusted Publishing Architecture
Releases publish directly from GitHub Actions without storing long-lived, sensitive API tokens:
- GitHub Actions exchanges its cryptographic OIDC ID token with PyPI for a short-lived upload token.
- PyPI validates the repository (
petry-projects/broodminder-data), workflow (publish.yml), and environment (pypi).
2. Onboarding Steps (First Release Setup)
Before publishing the first release, the account owner registers a Pending Publisher on PyPI:
- Log in to pypi.org/manage/account/publishing/.
- Under "Add a pending publisher", enter:
- PyPI Project Name:
broodminder-data - Owner:
petry-projects - Repository name:
broodminder-data - Workflow name:
publish.yml - Environment name:
pypi
- PyPI Project Name:
- Click "Add publisher".
3. Local Onboarding & Verification
Run the onboarding tool to inspect registry availability, build the sdist and wheel, and verify package metadata:
# Probe PyPI status, build sdist/wheel, and run twine verification
python scripts/pypi_onboard.py
4. Automated Publishing Workflow
- Automated on Merge to
main: When a PR bumping the packageversioninpyproject.tomlis merged tomain,.github/workflows/publish.ymldetects that git tagv<version>does not exist yet, builds and verifies the distribution packages withtwine check --strict, publishes to PyPI tokenlessly via Trusted Publishing OIDC, and automatically creates the git tag and GitHub Release with generated release notes. - GitHub Release Trigger: Publishing a release manually or via the GitHub UI also triggers
.github/workflows/publish.yml. - Manual Trigger (with Dry Run): You can run the workflow manually via
workflow_dispatchwithdry_run: true(default) to test artifact generation without releasing.
Output Files & Schema
Extracted data is saved under data/extract/ (git-ignored):
| file | contents |
|---|---|
raw/<hiveId>/<start>-<end>.readings.json.gz |
lossless raw responses (replay source) |
raw/<hiveId>/<start>-<end>.notes.json.gz |
lossless raw notes |
manifest.json |
per-window progress + row counts (drives resume) |
readings.ndjson.gz |
one JSON object per reading (analysis-ready) |
readings.csv.gz |
same, columnar |
notes.ndjson |
one object per note |
coverage.json |
per-hive earliest/latest reading + counts |
API Behavior & Rate Limits
The machine-readable description is in openapi.yaml. Notable quirks handled automatically:
- Authentication:
X-Api-Keyheader. Missing or invalid keys return HTTP 412 (not 401/403). - Time Windows: Maximum ~6 months per request — auto-chunked.
- No Pagination: Each window is a single JSON array payload.
- Rate Limit: ~1,000 calls per UTC day with no
Retry-Afterheader — the client tracks calls, self-throttles, and catches429responses cleanly.
Testing & Quality Gates
# Run unit & offline tests
.venv/bin/python -m pytest
# Byte-compile verification
python3 -m compileall bm scripts tests
- Offline tests (
tests/test_offline.py,tests/test_scripts_refactor.py): Run fast and hermetically without network access. - Live contract tests (
tests/test_contract.py): Automatically run whenBROODMINDER_API_KEYis present to verify live API compatibility; skip gracefully otherwise. - OpenAPI validation:
npx @redocly/cli lint openapi.yaml.
Project Structure
broodminder-data/
├── bm/
│ ├── __init__.py
│ └── client.py # Reusable BroodMinderClient (auth, retry, windowing)
├── scripts/
│ ├── discover.py # Auth check + account topology/schema sample
│ ├── extract_all.py # Resumable, budget-aware extraction (--catchup)
│ ├── flatten.py # Raw → NDJSON/CSV/coverage (--merge)
│ ├── cron_sync.sh # Routine unattended forward catch-up sync
│ └── cron_backfill.sh # Initial unattended multi-day backfill
├── tests/
│ ├── conftest.py
│ ├── test_offline.py # Fast deterministic unit tests
│ ├── test_scripts_refactor.py # Script unit test coverage
│ └── test_contract.py # Live contract tests (skip without key)
├── openapi/
│ └── broodminder-openapi.yaml # OpenAPI 3.1 specification
├── openapi.yaml -> openapi/broodminder-openapi.yaml # Root symlink
├── redocly.yaml # Redocly linting & preview configuration
├── requirements.txt # Runtime dependencies
└── pyproject.toml # Build configuration & metadata
Privacy & Security
.env (your API key) and data/ (your extracted hive data) are git-ignored and never leave your machine.
All test fixtures use synthetic or anonymized values. Please never paste an API key or raw hive telemetry into an issue, PR, or discussion.
Contributing
See CONTRIBUTING.md, SECURITY.md, and the Code of Conduct. Check out open Discussions to weigh in on upcoming features and architectural decisions.
License
MIT © Petry Projects.
Metadata
Release files for broodminder-data 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| broodminder_data-0.1.3.tar.gz | 60.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| broodminder_data-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.0 kB
Release files / broodminder_data-0.1.3.tar.gz
| Download URL | broodminder_data-0.1.3.tar.gz |
|---|---|
| Size | 60.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5759244cffb4ca5be3f023f00d7bab6b309f81b904b5536e508d4ba72d28e96d
|
|
BLAKE2b-256 checksum How to use checksums |
0b32cef87e2029ec53750f7667272a83cb746379b11c51f953205dea6a688ca7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / broodminder_data-0.1.3-py3-none-any.whl
| Download URL | broodminder_data-0.1.3-py3-none-any.whl |
|---|---|
| Size | 17.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2c5c043e89da5368d636741451388189e4b1b3ac95db369ac237cd6390284f4d
|
|
BLAKE2b-256 checksum How to use checksums |
0b32f17ff3cbf79240045160a1f77d7b27ec488e07c6d4bf2ca6ccf4673bedd7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log