python-oda
python-oda is a Python client for Ocean Data Access (ODA), eOdyn's REST API.
It lets you search and download oceanographic data through a filterable, typed API.
Features
- Command-line interface — browse and download products, datasets, documents and reports
from the terminal with the
oda-clicommand, no Python required - High-level, typed API — browse products, datasets, documents and reports through a single
entry point (
Oda), with results returned as typed Pydantic models - Flexible authentication — authenticate with a username/password, an existing JWT (access + refresh token), or OAuth2 client credentials
- Automatic token handling — access tokens are refreshed transparently, and API calls are retried once with a fresh token if they fail due to an expired/invalid token
- Lazy, filterable pagination — search products, datasets, documents and reports with server-side filtering and ordering, iterating results lazily as pages are fetched
- Streaming downloads — download documents and reports as a byte stream, with an optional
progress bar (powered by
tqdm) or a custom progress tracker - Concurrent downloads — download multiple documents or reports in parallel across a thread pool, with a configurable number of workers (5 by default)
- Built-in data readers — convert downloaded documents directly into pandas, polars or xarray objects, or plug in your own custom reader
- Fully typed with annotations and checked with mypy, PEP561 compatible
Installation
pip install python-oda
Optional extras are available for the built-in data readers: python-oda[pandas],
python-oda[polars] and python-oda[xarray].
Usage
Authentication
oda supports three authentication methods.
Credentials can also be provided via the
ODA_USERNAME/ODA_PASSWORD environment variables, in which case Oda() can be instantiated
without an explicit authentication argument.
from oda import Oda
from oda.core.authentication import AuthClient, AuthJWT, AuthUser
# Username / password
oda = Oda(authentication=AuthUser(username="my-user", password="my-password"))
# Existing JWT (access token, optionally with a refresh token)
oda = Oda(authentication=AuthJWT(access_token="...", refresh_token="..."))
# OAuth2 client credentials
oda = Oda(authentication=AuthClient(client_id="my-client", client_secret="my-secret"))
Browsing products and datasets
# Find products matching a filter
for product in oda.products.find(provider="eOdyn", order_by="+name"):
print(product)
# Find datasets matching a filter
for dataset in oda.datasets.find(type="currents", tags_in=["OS"]):
print(dataset)
Finding and downloading documents
# List documents in a dataset
for document in oda.documents.find(dataset_name="altimetry-sealevel-l3-swot"):
print(document.name, document.start_datetime, document.size)
# Download all matching documents to disk, with a progress bar
oda.documents.download(dataset_name="altimetry-sealevel-l3-swot", output_path="./downloads")
# Download concurrently across a thread pool (per-file byte progress is disabled beyond 1 worker)
oda.documents.download(dataset_name="altimetry-sealevel-l3-swot", output_path="./downloads", workers=4)
# Or download a single document into memory and load it directly as a DataFrame
document = next(iter(oda.documents.find(dataset_name="altimetry-sealevel-l3-swot", name="SWOT_L3_LR_SSH_Expert_outre-mer_053_464_20260726T173752_20260726T182918_v3.0.nc")))
df = document.download().to_pandas() # also available: .to_polars(), .to_xarray()
# Filter documents by date range
from datetime import datetime
for document in oda.documents.find(
dataset_name="altimetry-sealevel-l3-swot",
date__gte=datetime(2026, 7, 1),
date__lte=datetime(2026, 7, 26),
):
print(document.name, document.start_datetime)
Finding and downloading reports
for report in oda.reports.find(dataset_name="altimetry-sealevel-l3-swot", document_name="SWOT_L3_LR_SSH_Expert_outre-mer_053_464_20260726T173752_20260726T182918_v3.0.nc"):
print(report)
oda.reports.download(
dataset_name="altimetry-sealevel-l3-swot",
document_name="SWOT_L3_LR_SSH_Expert_outre-mer_053_464_20260726T173752_20260726T182918_v3.0.nc",
output_path="./downloads",
)
Command-line interface
python-oda also ships a CLI, installed as the oda-cli command, for browsing and downloading
products, datasets, documents and reports without writing any Python.
The CLI is configured entirely through environment variables:
| Variable | Description |
|---|---|
ODA_USERNAME, ODA_PASSWORD |
Credentials used to authenticate (required) |
ODA_API_URL |
ODA API base URL (default: https://oda.eodyn.com) |
AUTH_HOST |
URL of the authentication service (default: auto-discovered from ODA_API_URL) |
Run oda-cli --help to see this reminder at any time.
# Check that your credentials are valid
oda-cli whoami
# Browse
oda-cli products find --provider eOdyn
oda-cli datasets find --type currents --tag OS
oda-cli documents find --dataset-name altimetry-sealevel-l3-swot --date-gte 2026-07-01
oda-cli reports find --dataset-name altimetry-sealevel-l3-swot --document-name my-document
# Download
oda-cli documents download --dataset-name altimetry-sealevel-l3-swot --output-path ./downloads
oda-cli reports download --dataset-name altimetry-sealevel-l3-swot --document-name my-document
# Output as JSON lines instead of a table (e.g. for piping into jq)
oda-cli documents find --dataset-name altimetry-sealevel-l3-swot --json
Run oda-cli --help or oda-cli <command> --help for the full list of options.
Contact
For questions or support, contact support-it@eodyn.com.
Metadata
Release files for python-oda 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_oda-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / python_oda-0.2.1-py3-none-any.whl
| Download URL | python_oda-0.2.1-py3-none-any.whl |
|---|---|
| Size | 157.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
39cfbcebe2e2d7a04201703953203cde6545a591dcff999645cd266b2ab19ffd
|
|
BLAKE2b-256 checksum How to use checksums |
4f724e3f195d63370dbab20836f5c8c352ed6a61f377b4b20b2cec3131810154
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.13.5 Linux/5.15.0-185-generic
|