CWMSpy
CWMS REST API for Data Retrieval
Requirements.
Python 3.9+
Installation & Usage
pip install
pip install cwms-python
For users on Python 3.11+ who want the pandas 3.x stack, install into a fresh virtual environment and upgrade pandas explicitly:
python3.11 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
pip install cwms-python "pandas>=3,<4"
This keeps the default package install stable while allowing a modern Python environment to use pandas 3.x.
Then import the package:
import cwms
Authentication
cwms.init_session() supports both CDA API keys and Keycloak access tokens.
Use api_key= for the headless CDA API key flow, or token= for an OIDC access
token such as one saved by cwms-cli login.
import cwms
cwms.init_session(
api_root="https://cwms-data.usace.army.mil/cwms-data/",
token="ACCESS_TOKEN",
)
If both token and api_key are provided, cwms-python will use the token
and log a warning.
HTTP connection pools
Sessions created with cwms.init_session(api_root=..., pool_connections=100)
configure the same connection pool size and retry policy for HTTP and HTTPS.
This includes unencrypted internal HTTP CDA roots used by Batch jobs. The default
pool retains up to 100 connections per host for reuse; it does not cap concurrent
requests. Set pool_connections when creating the session to size that pool for
your workload. A Connection pool is full, discarding connection warning means
an extra connection is being closed instead of retained, not that a response or
its data was discarded. Check raised exceptions for actual request failures.
Errors and debugging
Failed HTTP requests raise cwms.api.ApiError. Its message includes the HTTP
status, method, URL, and CDA response body (including incident details when
provided). The original response is available as error.response. Custom
user-management errors retain these details too. Network exceptions propagate
with their original type. Invalid JSON responses raise ApiError with the
decoding exception as the cause; empty response bodies return an empty dictionary.
Concurrent time-series reads and writes raise cwms.api.BatchError if any
series or chunk fails. It subclasses RuntimeError, and error.failures
contains (series_or_chunk, original_exception) pairs for every failure.
Reads do not return incomplete results as success. Successful writes are not
rolled back. Failures while looking up time-series extents also propagate.
Chunk retries are limited to connection errors, timeouts, and HTTP
429/500/502/503/504; validation and other permanent errors fail immediately
at the chunk layer. The shared HTTP adapter retains its existing retry policy.
Enable request outcome and chunk diagnostics with Python logging:
import logging
logging.basicConfig(level=logging.WARNING)
logging.getLogger("cwms").setLevel(logging.DEBUG)
Request diagnostics include the method, endpoint, and response status, without request bodies or authentication headers.
Getting Started
import cwms
from datetime import datetime, timedelta
end = datetime.now()
begin = end - timedelta(days = 10)
data = cwms.get_timeseries(ts_id='Some.Fully.Qualified.Ts.Id',office_id='OFFICE1' , begin = begin, end = end)
#a cwms data object will be provided this object containes both the JSON as well
#as the values converted into a dataframe
#display the dataframe
df = data.df
print(df)
date-time value quality-code
0 2024-04-23 08:15:00 86.57 3
1 2024-04-23 08:30:00 86.57 3
2 2024-04-23 08:45:00 86.58 3
3 2024-04-23 09:00:00 86.58 3
4 2024-04-23 09:15:00 86.58 3
5 2024-04-23 09:30:00 86.58 3
6 2024-04-23 09:45:00 86.59 3
7 2024-04-23 10:00:00 86.58 3
#display JSON
json = data.JSON
print(json)
{'name': 'Some.Fully.Qualified.Ts.Id',
'office-id': 'MVP',
'units': 'ft',
'values': [['2024-04-23T08:15:00', 86.57, 3],
['2024-04-23T08:30:00', 86.57, 3],
['2024-04-23T08:45:00', 86.57999999999997, 3],
['2024-04-23T09:00:00', 86.57999999999997, 3],
['2024-04-23T09:15:00', 86.57999999999997, 3],
['2024-04-23T09:30:00', 86.57999999999997, 3],
['2024-04-23T09:45:00', 86.59, 3],
['2024-04-23T10:00:00', 86.57999999999997, 3]],
'version-date': None}
TimeSeries Profile API Compatibility Warning
Currently, the TimeSeries Profile API may not be fully supported until a new version of cwms-data-access is released with the updated endpoint implementation.
Contributing
Please view the contribution documentation here: [CONTRIBUTING.md]
Contributing and releases
See CONTRIBUTING.md for development checks, PR title conventions, and the Release Please publishing workflow.
Metadata
Release files for cwms-python 1.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 | |
|---|---|---|---|
| cwms_python-1.1.3.tar.gz | 51.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cwms_python-1.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 131.1 kB
Release files / cwms_python-1.1.3.tar.gz
| Download URL | cwms_python-1.1.3.tar.gz |
|---|---|
| Size | 51.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c8a7b33f693330ae13a24b84893d33a128449e38ef42ee852dbb0c855d04137e
|
|
BLAKE2b-256 checksum How to use checksums |
c81a5348a2ecf9336d2567ed32cf64b0a38017133f72208c76b7c1a377057f11
|
| 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 15, 2026.
Transparency logRelease files / cwms_python-1.1.3-py3-none-any.whl
| Download URL | cwms_python-1.1.3-py3-none-any.whl |
|---|---|
| Size | 79.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
03484b4f55ceb31b918693f2bf83f4e6771979d7638a75383baabe4f394feb6c
|
|
BLAKE2b-256 checksum How to use checksums |
4d37cf8a494cbe7cc6c53afa7eed319f9012b079f4eff646d0a5e360bb1158b3
|
| 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 15, 2026.
Transparency log