diff --git a/.kiro/steering/development-workflow.md b/.kiro/steering/development-workflow.md
index 9946ad0..5be1938 100644
--- a/.kiro/steering/development-workflow.md
+++ b/.kiro/steering/development-workflow.md
@@ -39,7 +39,30 @@ Distributions are created in the `dist/` directory as both sdist and wheel forma
 - Source code goes in `src/python/` directories
 - Tests go in `test/python/` directories
 - Each component needs a BUILD file for Pants configuration
-- Version numbers are set in BUILD files
+
+## Versioning and Releases
+
+Version numbers must be updated in three places before merging:
+
+1. `CHANGELOG.md` — add a new section for the version with a description of changes
+2. `BUILD` — update the `version` in `python_artifact()` (e.g., `version="0.1.5"`)
+3. `pyproject.toml` — update the `version` field to match
+
+For example, for the core library these files are:
+- `common/CHANGELOG.md`
+- `common/src/python/redcap_api/BUILD`
+- `common/src/python/redcap_api/pyproject.toml`
+
+### Release Process
+
+The CI build (`.github/workflows/build.yml`) triggers on git tags matching `v*`. At build time, it overrides the `version=` line in BUILD files using `sed` to match the git tag. This means the git tag is the source of truth for the released artifact version.
+
+To release:
+1. Ensure all three version files are updated and merged to main
+2. Create and push a git tag: `git tag v0.1.5 && git push origin v0.1.5`
+3. The workflow will lint, test, build, and upload the packages as a GitHub release
+
+Note: The workflow only overrides BUILD file versions, not `pyproject.toml`. Since Pants uses the BUILD file's `python_artifact` version for packaging, this doesn't affect the built artifact. Keep `pyproject.toml` in sync manually for consistency.
 
 ## Before Committing
 
diff --git a/.kiro/steering/project-overview.md b/.kiro/steering/project-overview.md
index 294c876..c978947 100644
--- a/.kiro/steering/project-overview.md
+++ b/.kiro/steering/project-overview.md
@@ -31,4 +31,6 @@ This repository contains a Python library for interacting with the REDCap API, d
 
 ## Build System
 
-This is a Pants-based monorepo. Each component has its own BUILD file defining dependencies and build targets. Version numbers are set in BUILD files, not in setup.py or pyproject.toml.
+This is a Pants-based monorepo. Each component has its own BUILD file defining dependencies and build targets.
+
+Version numbers must be kept in sync across three files per package: `CHANGELOG.md`, `BUILD` (in `python_artifact()`), and `pyproject.toml`. The CI release workflow overrides the BUILD file version from the git tag at build time, but all three should be updated before merging. See the development workflow steering doc for full release details.
diff --git a/common/CHANGELOG.md b/common/CHANGELOG.md
index 2cbeb09..7aadbc6 100644
--- a/common/CHANGELOG.md
+++ b/common/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 Documentation of release versions of `redcap-api`
 
+## 0.1.5
+
+* Adds optional `date_range_begin` and `date_range_end` parameters to `REDCapProject.export_records()` for filtering records by modification date
+
 ## 0.1.3
 
 * Updates to allow REDCapProject to also export reports
diff --git a/common/src/python/redcap_api/BUILD b/common/src/python/redcap_api/BUILD
index 119f627..59caaaa 100644
--- a/common/src/python/redcap_api/BUILD
+++ b/common/src/python/redcap_api/BUILD
@@ -15,7 +15,7 @@ python_distribution(
     sdist=True,
     provides=python_artifact(
         name="redcap-api",
-        version="0.1.4",
+        version="0.1.5",
         description="Library for interacting with the REDCap API",
         author="NACC",
         author_email="nacchelp@uw.edu",
diff --git a/common/src/python/redcap_api/pyproject.toml b/common/src/python/redcap_api/pyproject.toml
index 0d20712..17ba662 100644
--- a/common/src/python/redcap_api/pyproject.toml
+++ b/common/src/python/redcap_api/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "redcap-api"
-version = "0.1.3"
+version = "0.1.5"
 description = "Library for interacting with the REDCap API"
 license-files = ["LICENSE"]
 authors = [{ name = "NACC", email = "nacchelp@uw.edu" }]
diff --git a/common/src/python/redcap_api/redcap_project.py b/common/src/python/redcap_api/redcap_project.py
index d4a6160..582cce9 100644
--- a/common/src/python/redcap_api/redcap_project.py
+++ b/common/src/python/redcap_api/redcap_project.py
@@ -313,6 +313,8 @@ def export_records(
         forms: Optional[list[str]] = None,
         events: Optional[list[str]] = None,
         filters: Optional[str] = None,
+        date_range_begin: Optional[str] = None,
+        date_range_end: Optional[str] = None,
     ) -> List[Dict[str, str]] | str:
         """Export records from the REDCap project.
 
@@ -323,6 +325,14 @@ def export_records(
             forms (Optional): List of forms to be included
             events (Optional): List of events to be included
             filters (Optional) : Filter logic as a string (e.g. [age]>30)
+            date_range_begin (Optional): Return only records created or
+                modified after this date/time. Format: YYYY-MM-DD HH:MM:SS
+                (e.g., '2017-01-01 00:00:00'). If not specified, assumes
+                no begin time.
+            date_range_end (Optional): Return only records created or
+                modified before this date/time. Format: YYYY-MM-DD HH:MM:SS
+                (e.g., '2017-01-01 00:00:00'). If not specified, uses the
+                current server time.
 
         Returns:
             The list of records (JSON objects) or
@@ -354,6 +364,14 @@ def export_records(
         if filters:
             data["filterLogic"] = filters
 
+        # If date range begin specified, export only records modified after.
+        if date_range_begin:
+            data["dateRangeBegin"] = date_range_begin
+
+        # If date range end specified, export only records modified before.
+        if date_range_end:
+            data["dateRangeEnd"] = date_range_end
+
         message = "failed to export records"
         if exp_format.lower() == "json":
             return self.__redcap_con.request_json_value(data=data, message=message)
