noaa_api

NOAA Climate Data Online API Client

This module provides an asynchronous client for interacting with the NOAA National Centers for Environmental Information (NCEI) Climate Data Online (CDO) Web Services API v2.

The NOAAClient class manages authentication, rate limiting, and connection handling while providing methods to access all available NOAA CDO endpoints including datasets, data categories, data types, locations, stations, and the actual climate data.

Features:

  • Asynchronous API access using aiohttp
  • Automatic rate limiting (5 requests/second, 10,000 requests/day)
  • Connection pooling and TCP connection caching
  • Strongly typed parameters and responses using Python type hints
  • Comprehensive endpoint coverage for all documented NOAA CDO Web Services
  • Proper resource management through async context managers

Example Usage:

import asyncio
from noaa_api import NOAAClient

async def main():
    # Best Practice: Use async context manager for automatic resource cleanup
    async with NOAAClient(token="YOUR_TOKEN_HERE") as client:
        # Query available datasets
        datasets = await client.get_datasets(limit=10)

        # Query multiple stations in a geographic region
        stations = await client.get_stations(
            extent="42.0,-90.0,40.0,-88.0",  # north,west,south,east
            datasetid="GHCND",
            limit=5
        )

        # Query specific weather data with unit conversion
        data = await client.get_data(
            datasetid="GHCND",
            startdate="2022-01-01",
            enddate="2022-01-31",
            stationid="GHCND:USW00094728",
            units="metric",  # Convert to metric units
            limit=100,
        )

        # Process the data...

if __name__ == "__main__":
    asyncio.run(main())

Important Technical Notes:

  1. Event Loop Management:

    # ❌ BAD: Creating multiple event loops can cause issues
    loop1 = asyncio.new_event_loop()
    client1 = await NOAAClient(token="TOKEN1")
    loop2 = asyncio.new_event_loop()  # Don't do this!
    client2 = await NOAAClient(token="TOKEN2")
    
    # ✅ GOOD: Share the same event loop for multiple clients
    async with NOAAClient(token="TOKEN1") as client1,             NOAAClient(token="TOKEN2") as client2:
        # Both clients share the same event loop
        await asyncio.gather(
            client1.get_datasets(),
            client2.get_datasets()
        )
    
  2. Resource Management:

    # ❌ BAD: Manual resource cleanup is error-prone
    client = NOAAClient(token="YOUR_TOKEN")
    try:
        await client.get_datasets()
    finally:
        client.close()  # Might miss some resources
    
    # ✅ GOOD: Use async context manager
    async with NOAAClient(token="YOUR_TOKEN") as client:
        await client.get_datasets()
    # Resources are automatically cleaned up
    
  3. Rate Limiting:

    # ❌ BAD: Parallel requests without shared rate limiter
    async def parallel_bad():
        tasks = []
        for i in range(20):
            client = NOAAClient(token="TOKEN")  # Each has separate limiter
            tasks.append(client.get_datasets())
        return await asyncio.gather(*tasks)  # May exceed rate limits
    
    # ✅ GOOD: Share client for parallel requests
    async def parallel_good():
        async with NOAAClient(token="TOKEN") as client:
            tasks = [client.get_datasets() for _ in range(20)]
            return await asyncio.gather(*tasks)  # Rate limits respected
    

Performance Tips:

  1. Connection Pooling:

    • The client maintains a pool of TCP connections
    • Reuse the same client instance for multiple requests
    • Default connection limit is 10 concurrent connections
  2. Pagination:

    • Use the limit and offset parameters for large result sets
    • Consider processing data in chunks for memory efficiency
  3. Data Volume:

    • Limit date ranges appropriately (1 year for daily data, 10 years for monthly)
    • Use specific station IDs when possible instead of broad geographic queries
    • Set includemetadata=False if metadata isn't needed
  4. Caching:

    • Consider caching frequently accessed metadata (stations, datasets)
    • Implement local caching for historical data that doesn't change

For more details, see the NOAA CDO Web Services v2 documentation: https://www.ncdc.noaa.gov/cdo-web/webservices/v2

  1"""
  2NOAA Climate Data Online API Client
  3===================================
  4
  5This module provides an asynchronous client for interacting with the NOAA National Centers for Environmental Information (NCEI) Climate Data Online (CDO) Web Services API v2.
  6
  7The `NOAAClient` class manages authentication, rate limiting, and connection handling while providing methods to access all available NOAA CDO endpoints including datasets, data categories, data types, locations, stations, and the actual climate data.
  8
  9Features:
 10---------
 11- Asynchronous API access using aiohttp
 12- Automatic rate limiting (5 requests/second, 10,000 requests/day)
 13- Connection pooling and TCP connection caching
 14- Strongly typed parameters and responses using Python type hints
 15- Comprehensive endpoint coverage for all documented NOAA CDO Web Services
 16- Proper resource management through async context managers
 17
 18Example Usage:
 19-------------
 20```python
 21import asyncio
 22from noaa_api import NOAAClient
 23
 24async def main():
 25    # Best Practice: Use async context manager for automatic resource cleanup
 26    async with NOAAClient(token="YOUR_TOKEN_HERE") as client:
 27        # Query available datasets
 28        datasets = await client.get_datasets(limit=10)
 29
 30        # Query multiple stations in a geographic region
 31        stations = await client.get_stations(
 32            extent="42.0,-90.0,40.0,-88.0",  # north,west,south,east
 33            datasetid="GHCND",
 34            limit=5
 35        )
 36
 37        # Query specific weather data with unit conversion
 38        data = await client.get_data(
 39            datasetid="GHCND",
 40            startdate="2022-01-01",
 41            enddate="2022-01-31",
 42            stationid="GHCND:USW00094728",
 43            units="metric",  # Convert to metric units
 44            limit=100,
 45        )
 46
 47        # Process the data...
 48
 49if __name__ == "__main__":
 50    asyncio.run(main())
 51```
 52
 53Important Technical Notes:
 54------------------------
 551. Event Loop Management:
 56   ```python
 57   # ❌ BAD: Creating multiple event loops can cause issues
 58   loop1 = asyncio.new_event_loop()
 59   client1 = await NOAAClient(token="TOKEN1")
 60   loop2 = asyncio.new_event_loop()  # Don't do this!
 61   client2 = await NOAAClient(token="TOKEN2")
 62
 63   # ✅ GOOD: Share the same event loop for multiple clients
 64   async with NOAAClient(token="TOKEN1") as client1, \
 65            NOAAClient(token="TOKEN2") as client2:
 66       # Both clients share the same event loop
 67       await asyncio.gather(
 68           client1.get_datasets(),
 69           client2.get_datasets()
 70       )
 71   ```
 72
 732. Resource Management:
 74   ```python
 75   # ❌ BAD: Manual resource cleanup is error-prone
 76   client = NOAAClient(token="YOUR_TOKEN")
 77   try:
 78       await client.get_datasets()
 79   finally:
 80       client.close()  # Might miss some resources
 81
 82   # ✅ GOOD: Use async context manager
 83   async with NOAAClient(token="YOUR_TOKEN") as client:
 84       await client.get_datasets()
 85   # Resources are automatically cleaned up
 86   ```
 87
 883. Rate Limiting:
 89   ```python
 90   # ❌ BAD: Parallel requests without shared rate limiter
 91   async def parallel_bad():
 92       tasks = []
 93       for i in range(20):
 94           client = NOAAClient(token="TOKEN")  # Each has separate limiter
 95           tasks.append(client.get_datasets())
 96       return await asyncio.gather(*tasks)  # May exceed rate limits
 97
 98   # ✅ GOOD: Share client for parallel requests
 99   async def parallel_good():
100       async with NOAAClient(token="TOKEN") as client:
101           tasks = [client.get_datasets() for _ in range(20)]
102           return await asyncio.gather(*tasks)  # Rate limits respected
103   ```
104
105Performance Tips:
106----------------
1071. Connection Pooling:
108   - The client maintains a pool of TCP connections
109   - Reuse the same client instance for multiple requests
110   - Default connection limit is 10 concurrent connections
111
1122. Pagination:
113   - Use the `limit` and `offset` parameters for large result sets
114   - Consider processing data in chunks for memory efficiency
115
1163. Data Volume:
117   - Limit date ranges appropriately (1 year for daily data, 10 years for monthly)
118   - Use specific station IDs when possible instead of broad geographic queries
119   - Set `includemetadata=False` if metadata isn't needed
120
1214. Caching:
122   - Consider caching frequently accessed metadata (stations, datasets)
123   - Implement local caching for historical data that doesn't change
124
125For more details, see the NOAA CDO Web Services v2 documentation:
126https://www.ncdc.noaa.gov/cdo-web/webservices/v2
127"""  # noqa: E501
128
129import importlib.metadata
130
131import noaa_api.json_responses as json_responses
132import noaa_api.json_schemas as json_schemas
133import noaa_api.parameter_schemas as parameter_schemas
134
135from .noaa import NOAAClient
136
137# Assign the selected schema attributes to the json_responses module
138
139__all__ = [
140    "NOAAClient",
141    "json_schemas",
142    "parameter_schemas",
143    "json_responses",
144]
145
146__version__ = importlib.metadata.version("noaa-api")
class NOAAClient:
  30class NOAAClient:
  31    """
  32    <span style="color:#4E97D8; font-weight:bold">Asynchronous client for accessing the NOAA NCEI Climate Data Online (CDO) Web API v2.</span>
  33
  34    This client handles API authentication, rate limiting, connection management, and
  35    provides methods to query all available NOAA CDO endpoints.
  36
  37    <span style="color:#2ECC71; font-weight:bold">Methods:</span>
  38    --------
  39     - <span style="color:#9B59B6">get_datasets</span>: Query information about available datasets.
  40     - <span style="color:#9B59B6">get_data_categories</span>: Query information about data categories.
  41     - <span style="color:#9B59B6">get_datatypes</span>: Query information about data types.
  42     - <span style="color:#9B59B6">get_location_categories</span>: Query information about location categories.
  43     - <span style="color:#9B59B6">get_locations</span>: Query information about locations.
  44     - <span style="color:#9B59B6">get_stations</span>: Query information about weather stations.
  45     - <span style="color:#9B59B6">get_data</span>: Query actual climate data based on specified parameters.
  46     - <span style="color:#9B59B6">close</span>: Close the aiohttp session.
  47
  48    <span style="color:#E67E22; font-weight:bold">Important Implementation Notes:</span>
  49    ------
  50     - <span style="color:#F1C40F">Event Loop Consistency</span>: Always make requests within the same event loop to
  51       take advantage of client-side rate limiting and TCP connection pooling. Using different
  52       event loops will reset rate limiters and require new connection establishment.
  53
  54     - <span style="color:#F1C40F">Rate Limiting</span>: The client automatically enforces NOAA's API rate limits
  55       (5 req/sec, 10,000 req/day) through AsyncLimiter. This prevents API throttling or
  56       blacklisting while optimizing throughput.
  57
  58     - <span style="color:#F1C40F">Connection Management</span>: Uses aiohttp's TCPConnector for connection pooling and
  59       reuse, significantly improving performance for multiple requests by avoiding
  60       the overhead of establishing new connections.
  61
  62     - <span style="color:#F1C40F">Context Manager Support</span>: The client can be used as an async context manager
  63       (`async with NOAAClient(...) as client:`) to ensure proper resource cleanup.
  64
  65    <span style="color:#2ECC71; font-weight:bold">Usage Notes:</span>
  66    ------
  67     - All query methods are asynchronous and return parsed JSON responses.
  68     - For ID-based queries, pass the ID as the first parameter.
  69     - For broader queries, use the keyword parameters to filter results.
  70     - Always provide your NOAA API token (sign up at https://www.ncdc.noaa.gov/cdo-web/token)
  71    """  # noqa: E501
  72
  73    __slots__: tuple[str, ...] = (
  74        "token",
  75        "tcp_connector",
  76        "aiohttp_session",
  77        "tcp_connector_limit",
  78        "keepalive_timeout",
  79        "is_client_provided",
  80        "_seconds_request_limiter",
  81        "_daily_request_limiter",
  82        "_most_recent_loop",
  83    )
  84
  85    token: str | None
  86    """
  87    The API token for authentication with NOAA API.
  88    """
  89
  90    tcp_connector: aiohttp.TCPConnector | None
  91    """
  92    TCP connector for managing HTTP connections. (Lazily initialized)
  93    """
  94
  95    aiohttp_session: aiohttp.ClientSession | None
  96    """
  97    Aiohttp session for making HTTP requests. (Lazily initialized)
  98    """
  99
 100    tcp_connector_limit: int
 101    """
 102    Maximum number of connections.
 103    """
 104
 105    keepalive_timeout: int
 106    """
 107    Timeout for keeping connections alive in seconds.
 108    """
 109
 110    is_client_provided: bool
 111    """
 112    Flag indicating if the client was provided by the user (using `provide_aiohttp_client_session`). In which case, context management will not close the client.
 113
 114    NOTE: If the token parameter is not set in the client headers, the `token` parameter will be used. If the `token` parameter is also none, a `MissingTokenError` will be raised.
 115    """  # noqa: E501
 116
 117    _seconds_request_limiter: aiolimiter.AsyncLimiter
 118    """
 119    Rate limiter for requests per second.
 120    """
 121
 122    _daily_request_limiter: aiolimiter.AsyncLimiter
 123    """
 124    Rate limiter for requests per day.
 125    """
 126
 127    _most_recent_loop: asyncio.AbstractEventLoop | None
 128
 129    ENDPOINT: ClassVar[str] = "https://www.ncei.noaa.gov/cdo-web/api/v2"
 130    """
 131    Base URL for the NOAA CDO API v2.
 132    """
 133
 134    def __init__(
 135        self,
 136        token: str | None,
 137        tcp_connector_limit: int = 10,
 138        keepalive_timeout: int = 60,  # Seconds
 139    ):
 140        """
 141        <span style="color:#4E97D8; font-weight:bold">Initialize the NOAA API client.</span>
 142
 143        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 144         - <span style="color:#9B59B6">token</span> (str): The API token for authentication with NOAA API.
 145           Get a token at: https://www.ncdc.noaa.gov/cdo-web/token
 146         - <span style="color:#9B59B6">tcp_connector_limit</span> (int, optional): Maximum number of connections.
 147           Higher limits allow more concurrent requests but consume more resources. Defaults to 10.
 148         - <span style="color:#9B59B6">keepalive_timeout</span> (int, optional): Timeout for keeping connections alive in seconds.
 149           Higher values maintain connections longer, reducing overhead for frequent requests. Defaults to 60.
 150
 151        <span style="color:#2ECC71; font-weight:bold">Notes:</span>
 152         - Using a higher connector limit is beneficial when making many parallel requests
 153         - The keepalive timeout should be adjusted based on your request frequency pattern
 154        """  # noqa: E501
 155        self.token = token
 156        self.tcp_connector_limit = tcp_connector_limit
 157        self.keepalive_timeout = keepalive_timeout
 158        self.tcp_connector = None
 159        self.aiohttp_session = None
 160        self.is_client_provided = False
 161        self._seconds_request_limiter = aiolimiter.AsyncLimiter(
 162            5,  # 5 requests per second
 163            1,  # 1 second
 164        )
 165
 166        self._daily_request_limiter = aiolimiter.AsyncLimiter(
 167            10_000,  # 10_000 requests per day
 168            60 * 60 * 24,  # 1 day
 169        )
 170
 171        self._most_recent_loop = None
 172
 173    def _find_token_location(self) -> TokenLocation:
 174        if self.aiohttp_session is None:
 175            if self.token is None:
 176                return TokenLocation.Nowhere
 177            else:
 178                return TokenLocation.InAttribute
 179
 180        if "token" in self.aiohttp_session.headers and self.token is None:
 181            return TokenLocation.InClientSessionHeaders
 182
 183        return TokenLocation.InAttributesAndClientSessionHeaders
 184
 185    async def __aenter__(self) -> Self:
 186        _ = await self._ensure()
 187        return self
 188
 189    async def __aexit__(
 190        self,
 191        exc_type: type[BaseException] | None,
 192        exc_value: Exception | None,
 193        traceback: types.TracebackType | None,
 194    ) -> None:
 195        if not self.is_client_provided:
 196            self.close()
 197
 198    async def provide_aiohttp_client_session(
 199        self, asyncio_client: aiohttp.ClientSession
 200    ) -> Self:
 201        """
 202        <span style="color:#4E97D8; font-weight:bold">Provide an existing aiohttp session for the client.</span>
 203
 204        <span style="color:#E67E22; font-weight:bold">Advanced Usage:</span>
 205        This method allows integrating the NOAA client with an existing aiohttp session,
 206        useful for applications that need to share connection pools or have complex
 207        HTTP client requirements.
 208
 209        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 210         - <span style="color:#9B59B6">asyncio_client</span> (aiohttp.ClientSession): The existing aiohttp session.
 211
 212        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 213         - Self: The client instance for method chaining
 214
 215        <span style="color:#E67E22; font-weight:bold">Important:</span>
 216        When using a provided session, you are responsible for closing it properly.
 217        The client will not close it even when using async context management.
 218        """  # noqa: E501
 219        self.aiohttp_session = asyncio_client
 220        self.is_client_provided = True
 221
 222        return self
 223
 224    async def _ensure(self) -> TokenLocation:
 225        """
 226        <span style="color:#4E97D8; font-weight:bold">Ensures that necessary resources exist for making API requests.</span>
 227
 228        This method lazily initializes the TCP connector and aiohttp session when needed,
 229        which allows for efficient resource management and supports integration with
 230        existing sessions.
 231
 232        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 233         - TokenLocation: The location of the token (Enum indicating where the token is stored)
 234
 235        <span style="color:#E67E22; font-weight:bold">Implementation Notes:</span>
 236        This method handles the complex logic of determining where the authentication
 237        token is stored and creating appropriate session headers. It rebuilds connections
 238        if the event loop has changed, ensuring proper resource management across
 239        different async contexts.
 240        """  # noqa: E501
 241        if self.tcp_connector is not None and self.tcp_connector._loop.is_closed():  # pyright: ignore[reportPrivateUsage]
 242            self.tcp_connector = None
 243
 244        if self.aiohttp_session is not None and self.aiohttp_session._loop.is_closed():  # pyright: ignore[reportPrivateUsage]
 245            self.aiohttp_session = None
 246
 247        if self.is_client_provided and self.aiohttp_session is None:
 248            return self._find_token_location()
 249
 250        if self.tcp_connector is None:
 251            self.tcp_connector = aiohttp.TCPConnector(
 252                limit=self.tcp_connector_limit, keepalive_timeout=self.keepalive_timeout
 253            )
 254
 255        if self.aiohttp_session is None:
 256            if self._find_token_location() == TokenLocation.InAttribute:
 257                self.aiohttp_session = aiohttp.ClientSession(
 258                    headers={"token": cast(str, self.token)},
 259                    connector=self.tcp_connector,
 260                )
 261
 262                return TokenLocation.InAttributesAndClientSessionHeaders
 263
 264            if self._find_token_location() == TokenLocation.Nowhere:
 265                self.aiohttp_session = aiohttp.ClientSession(
 266                    connector=self.tcp_connector
 267                )
 268
 269                return TokenLocation.Nowhere
 270
 271        return TokenLocation.InClientSessionHeaders
 272
 273    async def _make_request(
 274        self,
 275        url: str,
 276        parameters: parameter_schemas.AnyParameter | None = None,
 277        token_parameter: str | None = None,
 278    ) -> Any:
 279        """
 280        <span style="color:#4E97D8; font-weight:bold">Internal method to make a rate-limited API request.</span>
 281
 282        This method is the core mechanism for all API interactions, handling:
 283        - Event loop tracking and warning if changed
 284        - Rate limiting (both per-second and daily limits)
 285        - Token management and authentication
 286        - Parameter validation
 287        - HTTP request execution
 288
 289        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 290         - <span style="color:#9B59B6">url</span> (str): The API endpoint URL.
 291         - <span style="color:#9B59B6">parameters</span> (parameter_schemas.AnyParameter | None, optional): Query parameters. Defaults to None.
 292         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence over
 293           the `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 294           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 295
 296        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 297         - Any: The HTTP response JSON.
 298
 299        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 300         - ValueError: If 'limit' parameter exceeds 1000.
 301         - aiohttp.ClientResponseError: If the request fails.
 302         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 303
 304        <span style="color:#E67E22; font-weight:bold">Important Implementation Notes:</span>
 305        - <span style="color:#F1C40F">Event Loop Tracking</span>: Detects when requests are made from different event
 306          loops and resets rate limiters. For optimal performance, always make requests from
 307          the same event loop to maintain consistent rate limiting and connection pooling.
 308
 309        - <span style="color:#F1C40F">Rate Limiting</span>: Uses AsyncLimiter to enforce NOAA's API limits:
 310          - 5 requests per second
 311          - 10,000 requests per day
 312          These limits prevent API throttling while maximizing throughput.
 313
 314        - <span style="color:#F1C40F">TCP Connection Reuse</span>: Maintains persistent connections to reduce
 315          latency and overhead. When all requests are made in the same event loop, connections
 316          are efficiently reused, significantly improving performance.
 317
 318        - <span style="color:#F1C40F">Token Management</span>: Flexibly handles API tokens from multiple sources,
 319          with a clear precedence order: token_parameter > session headers > instance attribute.
 320        """  # noqa: E501
 321        if self._most_recent_loop is None:
 322            self._most_recent_loop = asyncio.get_running_loop()
 323
 324        elif self._most_recent_loop.is_closed():
 325            warnings.warn(
 326                "Preivous loop was closed. Please only make requests from the same loop in order to utilize client-side rate limiting and TCP Connection caching",  # noqa: E501
 327                RuntimeWarning,
 328                stacklevel=9,
 329            )
 330
 331            self._seconds_request_limiter = aiolimiter.AsyncLimiter(
 332                5,  # 5 requests per second
 333                1,  # 1 second
 334            )
 335
 336            self._daily_request_limiter = aiolimiter.AsyncLimiter(
 337                10_000,  # 10_000 requests per day
 338                60 * 60 * 24,  # 1 day
 339            )
 340
 341            self._most_recent_loop = asyncio.get_running_loop()
 342
 343        token_location: TokenLocation = await self._ensure()
 344
 345        if (
 346            parameters is not None
 347            and "limit" in parameters
 348            and parameters["limit"] > 1000
 349        ):
 350            raise ValueError("Parameter 'limit' must be less than or equal to 1000")
 351
 352        if token_location == TokenLocation.Nowhere and token_parameter is None:
 353            raise MissingTokenError(
 354                "Neither client with token in header nor `token` attribute is provided"
 355            )
 356
 357        if token_parameter is not None:
 358            async with (
 359                self._seconds_request_limiter,
 360                self._daily_request_limiter,
 361                cast(
 362                    aiohttp.ClientSession, self.aiohttp_session
 363                ).get(  # Client was already ensured
 364                    url,
 365                    params=cast(Mapping[str, str], parameters),
 366                    headers={"token": token_parameter},
 367                ) as response,
 368            ):
 369                response.raise_for_status()
 370                return await response.json()
 371
 372        if (
 373            token_location == TokenLocation.InAttributesAndClientSessionHeaders
 374            or TokenLocation.InClientSessionHeaders
 375        ):
 376            async with (
 377                self._seconds_request_limiter,
 378                self._daily_request_limiter,
 379                cast(
 380                    aiohttp.ClientSession, self.aiohttp_session
 381                ).get(  # Client was already ensured
 382                    url, params=cast(Mapping[str, str | int], parameters)
 383                ) as response,
 384            ):
 385                response.raise_for_status()
 386                return await response.json()
 387
 388        if token_location == TokenLocation.InAttribute:
 389            async with (
 390                self._seconds_request_limiter,
 391                self._daily_request_limiter,
 392                cast(
 393                    aiohttp.ClientSession, self.aiohttp_session
 394                ).get(  # Client was already ensured
 395                    url,
 396                    params=cast(Mapping[str, str], parameters),
 397                    headers={"token": cast(str, self.token)},
 398                ) as response,
 399            ):
 400                response.raise_for_status()
 401                return await response.json()
 402
 403    async def get_dataset_by_id(
 404        self, id: str, token_parameter: str | None = None
 405    ) -> json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON:
 406        """
 407        <span style="color:#4E97D8; font-weight:bold">Query information about a specific dataset by ID.</span>
 408        <span style="color:#3498DB">Endpoint: `/datasets/{id}`</span>
 409
 410        Retrieves detailed information about a single dataset identified by its unique ID.
 411        This endpoint provides comprehensive metadata about the dataset's structure, time range,
 412        coverage, and other attributes.
 413
 414        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 415         - <span style="color:#9B59B6">id</span> (str): The ID of the dataset to retrieve.
 416         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 417           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 418           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 419
 420        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 421         - json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
 422           dataset information or rate limit message.
 423
 424        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 425         - aiohttp.ClientResponseError: If the request fails.
 426         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 427
 428        <span style="color:#E67E22; font-weight:bold">Performance Note:</span>
 429        Individual ID lookups are generally faster than filtered queries against all datasets.
 430        When you know the specific dataset ID, use this method for better performance.
 431        """  # noqa: E501
 432        return cast(
 433            json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON,
 434            await self._make_request(
 435                f"{self.ENDPOINT}/datasets/{id}", token_parameter=token_parameter
 436            ),
 437        )
 438
 439    async def get_datasets(
 440        self,
 441        *,
 442        token_parameter: str | None = None,
 443        datatypeid: str | list[str] = "",
 444        locationid: str | list[str] = "",
 445        stationid: str | list[str] = "",
 446        startdate: str = "0001-01-01",  # YYYY-MM-DD
 447        enddate: str = "0001-01-01",  # YYYY-MM-DD
 448        sortfield: parameter_schemas.Sortfield = "id",
 449        sortorder: parameter_schemas.Sortorder = "asc",
 450        limit: int = 25,
 451        offset: int = 0,
 452    ) -> json_schemas.DatasetsJSON | json_schemas.RateLimitJSON:
 453        """
 454        <span style="color:#4E97D8; font-weight:bold">Query information about available datasets.</span>
 455        <span style="color:#3498DB">Endpoint: `/datasets`</span>
 456
 457        Retrieves a list of datasets matching the specified filter criteria. This endpoint
 458        allows comprehensive filtering to find datasets containing specific data types,
 459        locations, date ranges, and more.
 460
 461        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
 462        List parameters are automatically formatted as ampersand-separated strings.
 463        Providing a string or list of strings of ampersand-separated values is also supported.
 464
 465        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 466         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 467           over `token` attribute. Defaults to None.
 468         - <span style="color:#9B59B6">datatypeid</span> (str | list[str], optional): Filter by data type ID(s). Defaults to "".
 469         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
 470         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
 471         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 472         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 473         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
 474         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
 475         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
 476         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
 477
 478        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 479         - json_schemas.DatasetsJSON | json_schemas.RateLimitJSON: Dataset information or rate limit message.
 480
 481        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 482         - ValueError: If 'limit' parameter exceeds 1000.
 483         - aiohttp.ClientResponseError: If the request fails.
 484         - MissingTokenError: If authentication is missing.
 485
 486        <span style="color:#E67E22; font-weight:bold">Performance Tips:</span>
 487        - Use as many filter parameters as possible to reduce result size and improve response time
 488        - For large result sets, use pagination (limit and offset) to retrieve data in manageable chunks
 489        - Consider caching results for frequently accessed dataset information
 490        """  # noqa: E501
 491        return cast(
 492            json_schemas.DatasetsJSON | json_schemas.RateLimitJSON,
 493            await self._make_request(
 494                f"{self.ENDPOINT}/datasets",
 495                parameters={
 496                    "datatypeid": "&".join(datatypeid)
 497                    if isinstance(datatypeid, list)
 498                    else datatypeid,
 499                    "locationid": "&".join(locationid)
 500                    if isinstance(locationid, list)
 501                    else locationid,
 502                    "stationid": "&".join(stationid)
 503                    if isinstance(stationid, list)
 504                    else stationid,
 505                    "startdate": startdate,
 506                    "enddate": enddate,
 507                    "sortfield": sortfield,
 508                    "sortorder": sortorder,
 509                    "limit": limit,
 510                    "offset": offset,
 511                },
 512                token_parameter=token_parameter,
 513            ),
 514        )
 515
 516    async def get_data_category_by_id(
 517        self, id: str, token_parameter: str | None = None
 518    ) -> json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON:
 519        """
 520        <span style="color:#4E97D8; font-weight:bold">Query information about a specific data category by ID.</span>
 521        <span style="color:#3498DB">Endpoint: `/datacategories/{id}`</span>
 522
 523        Retrieves detailed information about a single data category identified by its unique ID.
 524        Data categories represent broad classifications of the types of data available.
 525
 526        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 527         - <span style="color:#9B59B6">id</span> (str): The ID of the data category to retrieve.
 528         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 529           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 530           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 531
 532        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 533         - json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
 534           data category information or rate limit message.
 535
 536        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 537         - aiohttp.ClientResponseError: If the request fails.
 538         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 539
 540        <span style="color:#E67E22; font-weight:bold">Note:</span>
 541        Individual ID lookups are more efficient than querying all data categories when you know the specific ID.
 542        """  # noqa: E501
 543        return cast(
 544            json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON,
 545            await self._make_request(
 546                f"{self.ENDPOINT}/datacategories/{id}", token_parameter=token_parameter
 547            ),
 548        )
 549
 550    async def get_data_categories(
 551        self,
 552        *,
 553        token_parameter: str | None = None,
 554        datasetid: str | list[str] = "",
 555        locationid: str | list[str] = "",
 556        stationid: str | list[str] = "",
 557        startdate: str = "0001-01-01",
 558        enddate: str = "0001-01-01",
 559        sortfield: parameter_schemas.Sortfield = "id",
 560        sortorder: parameter_schemas.Sortorder = "asc",
 561        limit: int = 25,
 562        offset: int = 0,
 563    ) -> json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON:
 564        """
 565        <span style="color:#4E97D8; font-weight:bold">Query information about available data categories.</span>
 566        <span style="color:#3498DB">Endpoint: `/datacategories`</span>
 567
 568        Retrieves a list of data categories matching the specified filter criteria. Data categories
 569        are high-level classifications for the types of data available through the NOAA API.
 570
 571        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
 572        List parameters are automatically formatted as ampersand-separated strings.
 573        Providing a string or list of strings of ampersand-separated values is also supported.
 574
 575        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 576         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 577           over `token` attribute. Defaults to None.
 578         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
 579         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
 580         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
 581         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 582         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 583         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
 584         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
 585         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
 586         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
 587
 588        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 589         - json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON: Data categories information or rate limit message.
 590
 591        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 592         - ValueError: If 'limit' parameter exceeds 1000.
 593         - aiohttp.ClientResponseError: If the request fails.
 594         - MissingTokenError: If authentication is missing.
 595
 596        <span style="color:#E67E22; font-weight:bold">Usage Tip:</span>
 597        Data categories are useful for exploratory navigation of the NOAA data. Use this endpoint to
 598        discover broad categories before drilling down to specific data types within those categories.
 599        """  # noqa: E501
 600        return cast(
 601            json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON,
 602            await self._make_request(
 603                f"{self.ENDPOINT}/datacategories",
 604                parameters={
 605                    "datasetid": "&".join(datasetid)
 606                    if isinstance(datasetid, list)
 607                    else datasetid,
 608                    "locationid": "&".join(locationid)
 609                    if isinstance(locationid, list)
 610                    else locationid,
 611                    "stationid": "&".join(stationid)
 612                    if isinstance(stationid, list)
 613                    else stationid,
 614                    "startdate": startdate,
 615                    "enddate": enddate,
 616                    "sortfield": sortfield,
 617                    "sortorder": sortorder,
 618                    "limit": limit,
 619                    "offset": offset,
 620                },
 621                token_parameter=token_parameter,
 622            ),
 623        )
 624
 625    async def get_datatype_by_id(
 626        self, id: str, token_parameter: str | None = None
 627    ) -> json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON:
 628        """
 629        <span style="color:#4E97D8; font-weight:bold">Query information about a specific data type by ID.</span>
 630        <span style="color:#3498DB">Endpoint: `/datatypes/{id}`</span>
 631
 632        Retrieves detailed information about a single data type identified by its unique ID.
 633        Data types represent specific measurements or observations available in the NOAA datasets.
 634
 635        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 636         - <span style="color:#9B59B6">id</span> (str): The ID of the data type to retrieve.
 637         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 638           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 639           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 640
 641        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 642         - json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
 643           data type information or rate limit message.
 644
 645        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 646         - aiohttp.ClientResponseError: If the request fails.
 647         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 648
 649        <span style="color:#E67E22; font-weight:bold">Data Type Details:</span>
 650        Individual data type records include information about the measurement units, period,
 651        and other important metadata that helps interpret the actual climate data.
 652        """  # noqa: E501
 653        return cast(
 654            json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON,
 655            await self._make_request(
 656                f"{self.ENDPOINT}/datatypes/{id}", token_parameter=token_parameter
 657            ),
 658        )
 659
 660    async def get_datatypes(
 661        self,
 662        *,
 663        token_parameter: str | None = None,
 664        datasetid: str | list[str] = "",
 665        locationid: str | list[str] = "",
 666        stationid: str | list[str] = "",
 667        datacategoryid: str | list[str] = "",
 668        startdate: str = "0001-01-01",
 669        enddate: str = "0001-01-01",
 670        sortfield: parameter_schemas.Sortfield = "id",
 671        sortorder: parameter_schemas.Sortorder = "asc",
 672        limit: int = 25,
 673        offset: int = 0,
 674    ) -> json_schemas.DatatypesJSON | json_schemas.RateLimitJSON:
 675        """
 676        <span style="color:#4E97D8; font-weight:bold">Query information about available data types.</span>
 677        <span style="color:#3498DB">Endpoint: `/datatypes`</span>
 678
 679        Retrieves a list of data types matching the specified filter criteria. Data types
 680        represent specific climate measurements or observations available in the NOAA datasets,
 681        such as temperature, precipitation, wind speed, etc.
 682
 683        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
 684        List parameters are automatically formatted as ampersand-separated strings.
 685        Providing a string or list of strings of ampersand-separated values is also supported.
 686
 687        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 688         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 689           over `token` attribute. Defaults to None.
 690         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
 691         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
 692         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
 693         - <span style="color:#9B59B6">datacategoryid</span> (str | list[str], optional): Filter by data category ID(s). Defaults to "".
 694         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 695         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 696         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
 697         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
 698         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
 699         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
 700
 701        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 702         - json_schemas.DatatypesJSON | json_schemas.RateLimitJSON: Data types information or rate limit message.
 703
 704        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 705         - ValueError: If 'limit' parameter exceeds 1000.
 706         - aiohttp.ClientResponseError: If the request fails.
 707         - MissingTokenError: If authentication is missing.
 708
 709        <span style="color:#E67E22; font-weight:bold">Research Tip:</span>
 710        When planning a climate data analysis project, first explore available data types to
 711        determine which measurements are available for your region and time period of interest.
 712        Use datacategoryid to narrow down to relevant measurement categories.
 713        """  # noqa: E501
 714        return cast(
 715            json_schemas.DatatypesJSON | json_schemas.RateLimitJSON,
 716            await self._make_request(
 717                f"{self.ENDPOINT}/datatypes",
 718                parameters={
 719                    "datasetid": "&".join(datasetid)
 720                    if isinstance(datasetid, list)
 721                    else datasetid,
 722                    "locationid": "&".join(locationid)
 723                    if isinstance(locationid, list)
 724                    else locationid,
 725                    "stationid": "&".join(stationid)
 726                    if isinstance(stationid, list)
 727                    else stationid,
 728                    "datacategoryid": "&".join(datacategoryid)
 729                    if isinstance(datacategoryid, list)
 730                    else datacategoryid,
 731                    "startdate": startdate,
 732                    "enddate": enddate,
 733                    "sortfield": sortfield,
 734                    "sortorder": sortorder,
 735                    "limit": limit,
 736                    "offset": offset,
 737                },
 738                token_parameter=token_parameter,
 739            ),
 740        )
 741
 742    async def get_location_category_by_id(
 743        self, id: str, token_parameter: str | None = None
 744    ) -> json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON:
 745        """
 746        <span style="color:#4E97D8; font-weight:bold">Query information about a specific location category by ID.</span>
 747        <span style="color:#3498DB">Endpoint: `/locationcategories/{id}`</span>
 748
 749        Retrieves detailed information about a single location category identified by its unique ID.
 750        Location categories classify the types of locations available in the NOAA data (e.g., cities, counties, states).
 751
 752        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 753         - <span style="color:#9B59B6">id</span> (str): The ID of the location category to retrieve.
 754         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 755           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 756           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 757
 758        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 759         - json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
 760           location category information or rate limit message.
 761
 762        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 763         - aiohttp.ClientResponseError: If the request fails.
 764         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 765
 766        <span style="color:#E67E22; font-weight:bold">Usage Context:</span>
 767        Location categories provide a way to understand the different geographical hierarchies
 768        available in the NOAA climate data. This is particularly useful when designing
 769        geospatial visualizations or analyses across different territorial divisions.
 770        """  # noqa: E501
 771        return cast(
 772            json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON,
 773            await self._make_request(
 774                f"{self.ENDPOINT}/locationcategories/{id}",
 775                token_parameter=token_parameter,
 776            ),
 777        )
 778
 779    async def get_location_categories(
 780        self,
 781        *,
 782        token_parameter: str | None = None,
 783        datasetid: str | list[str] = "",
 784        locationid: str | list[str] = "",
 785        startdate: str = "0001-01-01",
 786        enddate: str = "0001-01-01",
 787        sortfield: parameter_schemas.Sortfield = "id",
 788        sortorder: parameter_schemas.Sortorder = "asc",
 789        limit: int = 25,
 790        offset: int = 0,
 791    ) -> json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON:
 792        """
 793        <span style="color:#4E97D8; font-weight:bold">Query information about available location categories.</span>
 794        <span style="color:#3498DB">Endpoint: `/locationcategories`</span>
 795
 796        Retrieves a list of location categories matching the specified filter criteria. Location categories
 797        classify the geographical hierarchies available in the NOAA climate data, such as cities, counties,
 798        states, countries, or other territorial divisions.
 799
 800        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
 801        List parameters are automatically formatted as ampersand-separated strings.
 802        Providing a string or list of strings of ampersand-separated values is also supported.
 803
 804        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 805         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 806           over `token` attribute. Defaults to None.
 807         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
 808         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
 809         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 810         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 811         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
 812         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
 813         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
 814         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
 815
 816        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 817         - json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON: Location categories information or rate limit message.
 818
 819        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 820         - ValueError: If 'limit' parameter exceeds 1000.
 821         - aiohttp.ClientResponseError: If the request fails.
 822         - MissingTokenError: If authentication is missing.
 823
 824        <span style="color:#E67E22; font-weight:bold">Geographical Analysis Tip:</span>
 825        Location categories help organize spatial data into logical hierarchies. When designing
 826        geographical analyses, first explore the available location categories to determine
 827        the most appropriate spatial resolution for your research question.
 828        """  # noqa: E501
 829        return cast(
 830            json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON,
 831            await self._make_request(
 832                f"{self.ENDPOINT}/locationcategories",
 833                parameters={
 834                    "datasetid": "&".join(datasetid)
 835                    if isinstance(datasetid, list)
 836                    else datasetid,
 837                    "locationid": "&".join(locationid)
 838                    if isinstance(locationid, list)
 839                    else locationid,
 840                    "startdate": startdate,
 841                    "enddate": enddate,
 842                    "sortfield": sortfield,
 843                    "sortorder": sortorder,
 844                    "limit": limit,
 845                    "offset": offset,
 846                },
 847                token_parameter=token_parameter,
 848            ),
 849        )
 850
 851    async def get_location_by_id(
 852        self, id: str, token_parameter: str | None = None
 853    ) -> json_schemas.LocationIDJSON | json_schemas.RateLimitJSON:
 854        """
 855        <span style="color:#4E97D8; font-weight:bold">Query information about a specific location by ID.</span>
 856        <span style="color:#3498DB">Endpoint: `/locations/{id}`</span>
 857
 858        Retrieves detailed information about a single location identified by its unique ID.
 859        Locations represent geographical areas where climate data is collected.
 860
 861        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 862         - <span style="color:#9B59B6">id</span> (str): The ID of the location to retrieve.
 863         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 864           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 865           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 866
 867        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 868         - json_schemas.LocationIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
 869           location information or rate limit message.
 870
 871        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 872         - aiohttp.ClientResponseError: If the request fails.
 873         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 874
 875        <span style="color:#E67E22; font-weight:bold">Location Details:</span>
 876        Individual location records include important metadata such as coordinates, names,
 877        and other geographical attributes that help interpret the climate data associated
 878        with the location.
 879        """  # noqa: E501
 880        return cast(
 881            json_schemas.LocationIDJSON | json_schemas.RateLimitJSON,
 882            await self._make_request(
 883                f"{self.ENDPOINT}/locations/{id}", token_parameter=token_parameter
 884            ),
 885        )
 886
 887    async def get_locations(
 888        self,
 889        *,
 890        token_parameter: str | None = None,
 891        datasetid: str | list[str] = "",
 892        locationcategoryid: str | list[str] = "",
 893        datacategoryid: str | list[str] = "",
 894        startdate: str = "0001-01-01",
 895        enddate: str = "0001-01-01",
 896        sortfield: parameter_schemas.Sortfield = "id",
 897        sortorder: parameter_schemas.Sortorder = "asc",
 898        limit: int = 25,
 899        offset: int = 0,
 900    ) -> json_schemas.LocationsJSON | json_schemas.RateLimitJSON:
 901        """
 902        <span style="color:#4E97D8; font-weight:bold">Query information about available locations.</span>
 903        <span style="color:#3498DB">Endpoint: `/locations`</span>
 904
 905        Retrieves a list of locations matching the specified filter criteria. Locations represent
 906        geographical areas where climate data is collected, such as cities, counties, states,
 907        countries, or other territorial divisions.
 908
 909        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
 910        List parameters are automatically formatted as ampersand-separated strings.
 911        Providing a string or list of strings of ampersand-separated values is also supported.
 912
 913        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 914         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 915           over `token` attribute. Defaults to None.
 916         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
 917         - <span style="color:#9B59B6">locationcategoryid</span> (str | list[str], optional): Filter by location category ID(s). Defaults to "".
 918         - <span style="color:#9B59B6">datacategoryid</span> (str | list[str], optional): Filter by data category ID(s). Defaults to "".
 919         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 920         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
 921         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
 922         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
 923         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
 924         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
 925
 926        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 927         - json_schemas.LocationsJSON | json_schemas.RateLimitJSON: Locations information or rate limit message.
 928
 929        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 930         - ValueError: If 'limit' parameter exceeds 1000.
 931         - aiohttp.ClientResponseError: If the request fails.
 932         - MissingTokenError: If authentication is missing.
 933
 934        <span style="color:#E67E22; font-weight:bold">Spatial Analysis Tip:</span>
 935        When working with climate data across geographical regions, use the locationcategoryid
 936        parameter to narrow down locations to a specific category (e.g., states, countries)
 937        for more consistent analysis. Combine with datacategoryid to find locations where
 938        specific types of measurements are available.
 939        """  # noqa: E501
 940        return cast(
 941            json_schemas.LocationsJSON | json_schemas.RateLimitJSON,
 942            await self._make_request(
 943                f"{self.ENDPOINT}/locations",
 944                parameters={
 945                    "datasetid": "&".join(datasetid)
 946                    if isinstance(datasetid, list)
 947                    else datasetid,
 948                    "locationcategoryid": "&".join(locationcategoryid)
 949                    if isinstance(locationcategoryid, list)
 950                    else locationcategoryid,
 951                    "datacategoryid": "&".join(datacategoryid)
 952                    if isinstance(datacategoryid, list)
 953                    else datacategoryid,
 954                    "startdate": startdate,
 955                    "enddate": enddate,
 956                    "sortfield": sortfield,
 957                    "sortorder": sortorder,
 958                    "limit": limit,
 959                    "offset": offset,
 960                },
 961                token_parameter=token_parameter,
 962            ),
 963        )
 964
 965    async def get_station_by_id(
 966        self, id: str, token_parameter: str | None = None
 967    ) -> json_schemas.StationIDJSON | json_schemas.RateLimitJSON:
 968        """
 969        <span style="color:#4E97D8; font-weight:bold">Query information about a specific weather station by ID.</span>
 970        <span style="color:#3498DB">Endpoint: `/stations/{id}`</span>
 971
 972        Retrieves detailed information about a single weather station identified by its unique ID.
 973        Stations are physical locations where weather and climate data measurements are collected.
 974
 975        <span style="color:#2ECC71; font-weight:bold">Args:</span>
 976         - <span style="color:#9B59B6">id</span> (str): The ID of the station to retrieve.
 977         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
 978           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
 979           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
 980
 981        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
 982         - json_schemas.StationIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
 983           station information or rate limit message.
 984
 985        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
 986         - aiohttp.ClientResponseError: If the request fails.
 987         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
 988
 989        <span style="color:#E67E22; font-weight:bold">Data Precision:</span>
 990        Weather stations provide the most accurate and localized climate data since they
 991        represent exact measurement points. Station-level data is particularly valuable
 992        for precise local analyses and ground-truthing other data sources.
 993        """  # noqa: E501
 994        return cast(
 995            json_schemas.StationIDJSON | json_schemas.RateLimitJSON,
 996            await self._make_request(
 997                f"{self.ENDPOINT}/stations/{id}", token_parameter=token_parameter
 998            ),
 999        )
1000
1001    async def get_stations(
1002        self,
1003        *,
1004        token_parameter: str | None = None,
1005        datasetid: str | list[str] = "",
1006        locationid: str | list[str] = "",
1007        datacategoryid: str | list[str] = "",
1008        datatypeid: str | list[str] = "",
1009        extent: str = "",
1010        startdate: str = "0001-01-01",
1011        enddate: str = "0001-01-01",
1012        sortfield: parameter_schemas.Sortfield = "id",
1013        sortorder: parameter_schemas.Sortorder = "asc",
1014        limit: int = 25,
1015        offset: int = 0,
1016    ) -> json_schemas.StationsJSON | json_schemas.RateLimitJSON:
1017        """
1018        <span style="color:#4E97D8; font-weight:bold">Query information about available weather stations.</span>
1019        <span style="color:#3498DB">Endpoint: `/stations`</span>
1020
1021        Retrieves a list of weather stations matching the specified filter criteria. Weather stations
1022        are the physical locations where climate measurements are recorded, and typically provide
1023        the most precise and localized data available.
1024
1025        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
1026        List parameters are automatically formatted as ampersand-separated strings.
1027        Providing a string or list of strings of ampersand-separated values is also supported.
1028
1029        <span style="color:#2ECC71; font-weight:bold">Args:</span>
1030         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
1031           over `token` attribute. Defaults to None.
1032         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
1033         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
1034         - <span style="color:#9B59B6">datacategoryid</span> (str | list[str], optional): Filter by data category ID(s). Defaults to "".
1035         - <span style="color:#9B59B6">datatypeid</span> (str | list[str], optional): Filter by data type ID(s). Defaults to "".
1036         - <span style="color:#9B59B6">extent</span> (str, optional): Geospatial extent (bbox) filter in format "north,west,south,east". Defaults to "".
1037         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
1038         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
1039         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
1040         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
1041         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
1042         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
1043
1044        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
1045         - json_schemas.StationsJSON | json_schemas.RateLimitJSON: Stations information or rate limit message.
1046
1047        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
1048         - ValueError: If 'limit' parameter exceeds 1000.
1049         - aiohttp.ClientResponseError: If the request fails.
1050         - MissingTokenError: If authentication is missing.
1051
1052        <span style="color:#E67E22; font-weight:bold">Geospatial Filtering:</span>
1053        The stations endpoint is one of the few that supports the "extent" parameter for
1054        geographical bounding box filtering. This is particularly useful for finding all
1055        stations within a specific region defined by coordinates. For example:
1056        "extent=42.0,-90.0,40.0,-88.0" would find stations within that rectangle.
1057        """  # noqa: E501
1058        return cast(
1059            json_schemas.StationsJSON | json_schemas.RateLimitJSON,
1060            await self._make_request(
1061                f"{self.ENDPOINT}/stations",
1062                parameters={
1063                    "datasetid": "&".join(datasetid)
1064                    if isinstance(datasetid, list)
1065                    else datasetid,
1066                    "locationid": "&".join(locationid)
1067                    if isinstance(locationid, list)
1068                    else locationid,
1069                    "datacategoryid": "&".join(datacategoryid)
1070                    if isinstance(datacategoryid, list)
1071                    else datacategoryid,
1072                    "datatypeid": "&".join(datatypeid)
1073                    if isinstance(datatypeid, list)
1074                    else datatypeid,
1075                    "extent": extent,
1076                    "startdate": startdate,
1077                    "enddate": enddate,
1078                    "sortfield": sortfield,
1079                    "sortorder": sortorder,
1080                    "limit": limit,
1081                    "offset": offset,
1082                },
1083                token_parameter=token_parameter,
1084            ),
1085        )
1086
1087    async def get_data(
1088        self,
1089        datasetid: str,
1090        startdate: str,  # YYYY-MM-DD
1091        enddate: str,  # YYYY-MM-DD
1092        *,
1093        token_parameter: str | None = None,
1094        datatypeid: str | list[str] = "",
1095        locationid: str | list[str] = "",
1096        stationid: str | list[str] = "",
1097        units: parameter_schemas.Units = "standard",
1098        sortfield: parameter_schemas.DataSortField = "date",
1099        sortorder: parameter_schemas.Sortorder = "asc",
1100        limit: int = 25,
1101        offset: int = 0,
1102        includemetadata: bool = True,
1103    ) -> json_schemas.DataJSON | json_schemas.RateLimitJSON:
1104        """
1105        <span style="color:#4E97D8; font-weight:bold">Query actual climate data with various filtering options.</span>
1106        <span style="color:#3498DB">Endpoint: `/data`</span>
1107
1108        This is the primary endpoint for retrieving actual climate measurements and observations.
1109        Unlike the other endpoints which provide metadata, this endpoint returns the actual
1110        climate data values matching your specified criteria.
1111
1112        <span style="color:#E67E22; font-weight:bold">Required Parameters:</span>
1113        Note that datasetid, startdate, and enddate are all required parameters for this endpoint.
1114        This is different from other endpoints where all filter parameters are optional.
1115
1116        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
1117        List parameters are automatically formatted as ampersand-separated strings.
1118        Providing a string or list of strings of ampersand-separated values is also supported.
1119
1120        <span style="color:#2ECC71; font-weight:bold">Args:</span>
1121         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
1122           over `token` attribute. Defaults to None.
1123         - <span style="color:#9B59B6">datasetid</span> (str): **Required**. The dataset ID to query data from.
1124         - <span style="color:#9B59B6">startdate</span> (str): **Required**. Beginning of date range in 'YYYY-MM-DD' format.
1125         - <span style="color:#9B59B6">enddate</span> (str): **Required**. End of date range in 'YYYY-MM-DD' format.
1126         - <span style="color:#9B59B6">datatypeid</span> (str | list[str], optional): Filter by data type ID(s). Defaults to "".
1127         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
1128         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
1129         - <span style="color:#9B59B6">units</span> (parameter_schemas.Units, optional): Unit system for data values ("standard" or "metric"). Defaults to "standard".
1130         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.DataSortfield, optional): Field to sort results by. Defaults to "date".
1131         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
1132         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
1133         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
1134         - <span style="color:#9B59B6">includemetadata</span> (bool, optional): Whether to include metadata in the response. Defaults to True.
1135
1136        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
1137         - json_schemas.DataJSON | json_schemas.RateLimitJSON: Climate data or rate limit message.
1138
1139        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
1140         - ValueError: If 'limit' parameter exceeds 1000 or if required parameters are missing.
1141         - aiohttp.ClientResponseError: If the request fails.
1142         - MissingTokenError: If authentication is missing.
1143
1144        <span style="color:#E67E22; font-weight:bold">Data Volume Considerations:</span>
1145        Climate data queries can return large volumes of data, especially with broad date ranges
1146        or multiple stations/locations. To manage data volume:
1147
1148        1. Use narrow date ranges when possible
1149        2. Specify particular stations or locations instead of querying all
1150        3. Filter to only the data types you need
1151        4. Use pagination (limit and offset) for large result sets
1152        5. Consider setting includemetadata=False if you don't need the metadata
1153
1154        <span style="color:#E67E22; font-weight:bold">Performance Note:</span>
1155        This endpoint is often the most resource-intensive and may take longer to respond
1156        than metadata endpoints. When developing applications, implement appropriate timeout
1157        handling and consider caching frequently accessed data.
1158        """  # noqa: E501
1159
1160        return cast(
1161            json_schemas.DataJSON | json_schemas.RateLimitJSON,
1162            await self._make_request(
1163                f"{self.ENDPOINT}/data",
1164                parameters={
1165                    "datasetid": datasetid,
1166                    "startdate": startdate,
1167                    "enddate": enddate,
1168                    "datatypeid": "&".join(datatypeid)
1169                    if isinstance(datatypeid, list)
1170                    else datatypeid,
1171                    "locationid": "&".join(locationid)
1172                    if isinstance(locationid, list)
1173                    else locationid,
1174                    "stationid": "&".join(stationid)
1175                    if isinstance(stationid, list)
1176                    else stationid,
1177                    "units": units,
1178                    "sortfield": sortfield,
1179                    "sortorder": sortorder,
1180                    "limit": limit,
1181                    "offset": offset,
1182                    "includemetadata": "true" if includemetadata else "false",
1183                },
1184                token_parameter=token_parameter,
1185            ),
1186        )
1187
1188    def close(self) -> None:
1189        """
1190        <span style="color:#4E97D8; font-weight:bold">Close the aiohttp session and TCP connector.</span>
1191
1192        This method properly cleans up resources used by the client. It should be called
1193        when you're done using the client to ensure proper cleanup of network connections
1194        and resources.
1195
1196        <span style="color:#E67E22; font-weight:bold">Resource Management:</span>
1197        - Always call this method when you're finished with the client
1198        - Alternatively, use the client as an async context manager with the `async with` statement,
1199          which will automatically close resources on exit
1200        - If you provided your own aiohttp session with `provide_aiohttp_client_session()`,
1201          this method will not close that session
1202
1203        <span style="color:#E67E22; font-weight:bold">Implementation Note:</span>
1204        This is a synchronous method that doesn't properly close the aiohttp session, which
1205        should be closed using `await session.close()`. For proper async cleanup, use
1206        the client as an async context manager instead.
1207        """  # noqa: E501
1208
1209        if isinstance(self.aiohttp_session, aiohttp.ClientSession):
1210            try:
1211                loop = asyncio.get_event_loop()
1212                _ = loop.create_task(self.aiohttp_session.close())
1213
1214            except RuntimeError:
1215                asyncio.run(self.aiohttp_session.close())
1216
1217    def __del__(self):
1218        """
1219        Destructor that ensures the aiohttp session is closed when the object is garbage collected.
1220        """  # noqa: E501
1221        self.close()

Asynchronous client for accessing the NOAA NCEI Climate Data Online (CDO) Web API v2.

This client handles API authentication, rate limiting, connection management, and provides methods to query all available NOAA CDO endpoints.

Methods:

  • get_datasets: Query information about available datasets.
  • get_data_categories: Query information about data categories.
  • get_datatypes: Query information about data types.
  • get_location_categories: Query information about location categories.
  • get_locations: Query information about locations.
  • get_stations: Query information about weather stations.
  • get_data: Query actual climate data based on specified parameters.
  • close: Close the aiohttp session.

Important Implementation Notes:

  • Event Loop Consistency: Always make requests within the same event loop to take advantage of client-side rate limiting and TCP connection pooling. Using different event loops will reset rate limiters and require new connection establishment.

  • Rate Limiting: The client automatically enforces NOAA's API rate limits (5 req/sec, 10,000 req/day) through AsyncLimiter. This prevents API throttling or blacklisting while optimizing throughput.

  • Connection Management: Uses aiohttp's TCPConnector for connection pooling and reuse, significantly improving performance for multiple requests by avoiding the overhead of establishing new connections.

  • Context Manager Support: The client can be used as an async context manager (async with NOAAClient(...) as client:) to ensure proper resource cleanup.

Usage Notes:

  • All query methods are asynchronous and return parsed JSON responses.
  • For ID-based queries, pass the ID as the first parameter.
  • For broader queries, use the keyword parameters to filter results.
  • Always provide your NOAA API token (sign up at https://www.ncdc.noaa.gov/cdo-web/token)
NOAAClient( token: str | None, tcp_connector_limit: int = 10, keepalive_timeout: int = 60)
134    def __init__(
135        self,
136        token: str | None,
137        tcp_connector_limit: int = 10,
138        keepalive_timeout: int = 60,  # Seconds
139    ):
140        """
141        <span style="color:#4E97D8; font-weight:bold">Initialize the NOAA API client.</span>
142
143        <span style="color:#2ECC71; font-weight:bold">Args:</span>
144         - <span style="color:#9B59B6">token</span> (str): The API token for authentication with NOAA API.
145           Get a token at: https://www.ncdc.noaa.gov/cdo-web/token
146         - <span style="color:#9B59B6">tcp_connector_limit</span> (int, optional): Maximum number of connections.
147           Higher limits allow more concurrent requests but consume more resources. Defaults to 10.
148         - <span style="color:#9B59B6">keepalive_timeout</span> (int, optional): Timeout for keeping connections alive in seconds.
149           Higher values maintain connections longer, reducing overhead for frequent requests. Defaults to 60.
150
151        <span style="color:#2ECC71; font-weight:bold">Notes:</span>
152         - Using a higher connector limit is beneficial when making many parallel requests
153         - The keepalive timeout should be adjusted based on your request frequency pattern
154        """  # noqa: E501
155        self.token = token
156        self.tcp_connector_limit = tcp_connector_limit
157        self.keepalive_timeout = keepalive_timeout
158        self.tcp_connector = None
159        self.aiohttp_session = None
160        self.is_client_provided = False
161        self._seconds_request_limiter = aiolimiter.AsyncLimiter(
162            5,  # 5 requests per second
163            1,  # 1 second
164        )
165
166        self._daily_request_limiter = aiolimiter.AsyncLimiter(
167            10_000,  # 10_000 requests per day
168            60 * 60 * 24,  # 1 day
169        )
170
171        self._most_recent_loop = None

Initialize the NOAA API client.

Args:

  • token (str): The API token for authentication with NOAA API. Get a token at: https://www.ncdc.noaa.gov/cdo-web/token
  • tcp_connector_limit (int, optional): Maximum number of connections. Higher limits allow more concurrent requests but consume more resources. Defaults to 10.
  • keepalive_timeout (int, optional): Timeout for keeping connections alive in seconds. Higher values maintain connections longer, reducing overhead for frequent requests. Defaults to 60.

Notes:

  • Using a higher connector limit is beneficial when making many parallel requests
  • The keepalive timeout should be adjusted based on your request frequency pattern
token: str | None

The API token for authentication with NOAA API.

tcp_connector: aiohttp.connector.TCPConnector | None

TCP connector for managing HTTP connections. (Lazily initialized)

aiohttp_session: aiohttp.client.ClientSession | None

Aiohttp session for making HTTP requests. (Lazily initialized)

tcp_connector_limit: int

Maximum number of connections.

keepalive_timeout: int

Timeout for keeping connections alive in seconds.

is_client_provided: bool

Flag indicating if the client was provided by the user (using provide_aiohttp_client_session). In which case, context management will not close the client.

NOTE: If the token parameter is not set in the client headers, the token parameter will be used. If the token parameter is also none, a MissingTokenError will be raised.

ENDPOINT: ClassVar[str] = 'https://www.ncei.noaa.gov/cdo-web/api/v2'

Base URL for the NOAA CDO API v2.

async def provide_aiohttp_client_session(self, asyncio_client: aiohttp.client.ClientSession) -> Self:
198    async def provide_aiohttp_client_session(
199        self, asyncio_client: aiohttp.ClientSession
200    ) -> Self:
201        """
202        <span style="color:#4E97D8; font-weight:bold">Provide an existing aiohttp session for the client.</span>
203
204        <span style="color:#E67E22; font-weight:bold">Advanced Usage:</span>
205        This method allows integrating the NOAA client with an existing aiohttp session,
206        useful for applications that need to share connection pools or have complex
207        HTTP client requirements.
208
209        <span style="color:#2ECC71; font-weight:bold">Args:</span>
210         - <span style="color:#9B59B6">asyncio_client</span> (aiohttp.ClientSession): The existing aiohttp session.
211
212        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
213         - Self: The client instance for method chaining
214
215        <span style="color:#E67E22; font-weight:bold">Important:</span>
216        When using a provided session, you are responsible for closing it properly.
217        The client will not close it even when using async context management.
218        """  # noqa: E501
219        self.aiohttp_session = asyncio_client
220        self.is_client_provided = True
221
222        return self

Provide an existing aiohttp session for the client.

Advanced Usage: This method allows integrating the NOAA client with an existing aiohttp session, useful for applications that need to share connection pools or have complex HTTP client requirements.

Args:

  • asyncio_client (aiohttp.ClientSession): The existing aiohttp session.

Returns:

  • Self: The client instance for method chaining

Important: When using a provided session, you are responsible for closing it properly. The client will not close it even when using async context management.

async def get_dataset_by_id( self, id: str, token_parameter: str | None = None) -> noaa_api.json_schemas.DatasetIDJSON | noaa_api.json_schemas.RateLimitJSON:
403    async def get_dataset_by_id(
404        self, id: str, token_parameter: str | None = None
405    ) -> json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON:
406        """
407        <span style="color:#4E97D8; font-weight:bold">Query information about a specific dataset by ID.</span>
408        <span style="color:#3498DB">Endpoint: `/datasets/{id}`</span>
409
410        Retrieves detailed information about a single dataset identified by its unique ID.
411        This endpoint provides comprehensive metadata about the dataset's structure, time range,
412        coverage, and other attributes.
413
414        <span style="color:#2ECC71; font-weight:bold">Args:</span>
415         - <span style="color:#9B59B6">id</span> (str): The ID of the dataset to retrieve.
416         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
417           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
418           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
419
420        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
421         - json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
422           dataset information or rate limit message.
423
424        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
425         - aiohttp.ClientResponseError: If the request fails.
426         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
427
428        <span style="color:#E67E22; font-weight:bold">Performance Note:</span>
429        Individual ID lookups are generally faster than filtered queries against all datasets.
430        When you know the specific dataset ID, use this method for better performance.
431        """  # noqa: E501
432        return cast(
433            json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON,
434            await self._make_request(
435                f"{self.ENDPOINT}/datasets/{id}", token_parameter=token_parameter
436            ),
437        )

Query information about a specific dataset by ID. Endpoint: /datasets/{id}

Retrieves detailed information about a single dataset identified by its unique ID. This endpoint provides comprehensive metadata about the dataset's structure, time range, coverage, and other attributes.

Args:

  • id (str): The ID of the dataset to retrieve.
  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None. Can be provided if token attribute is not provided anywhere (client headers or attribute). Token parameter will not persist between calls.

Returns:

  • json_schemas.DatasetIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing dataset information or rate limit message.

Raises:

  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If the client header token, attribute token, and parameter token_parameter are all not provided.

Performance Note: Individual ID lookups are generally faster than filtered queries against all datasets. When you know the specific dataset ID, use this method for better performance.

async def get_datasets( self, *, token_parameter: str | None = None, datatypeid: str | list[str] = '', locationid: str | list[str] = '', stationid: str | list[str] = '', startdate: str = '0001-01-01', enddate: str = '0001-01-01', sortfield: Literal['id', 'name', 'mindate', 'maxdate', 'datacoverage', ''] = 'id', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0) -> noaa_api.json_schemas.DatasetsJSON | noaa_api.json_schemas.RateLimitJSON:
439    async def get_datasets(
440        self,
441        *,
442        token_parameter: str | None = None,
443        datatypeid: str | list[str] = "",
444        locationid: str | list[str] = "",
445        stationid: str | list[str] = "",
446        startdate: str = "0001-01-01",  # YYYY-MM-DD
447        enddate: str = "0001-01-01",  # YYYY-MM-DD
448        sortfield: parameter_schemas.Sortfield = "id",
449        sortorder: parameter_schemas.Sortorder = "asc",
450        limit: int = 25,
451        offset: int = 0,
452    ) -> json_schemas.DatasetsJSON | json_schemas.RateLimitJSON:
453        """
454        <span style="color:#4E97D8; font-weight:bold">Query information about available datasets.</span>
455        <span style="color:#3498DB">Endpoint: `/datasets`</span>
456
457        Retrieves a list of datasets matching the specified filter criteria. This endpoint
458        allows comprehensive filtering to find datasets containing specific data types,
459        locations, date ranges, and more.
460
461        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
462        List parameters are automatically formatted as ampersand-separated strings.
463        Providing a string or list of strings of ampersand-separated values is also supported.
464
465        <span style="color:#2ECC71; font-weight:bold">Args:</span>
466         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
467           over `token` attribute. Defaults to None.
468         - <span style="color:#9B59B6">datatypeid</span> (str | list[str], optional): Filter by data type ID(s). Defaults to "".
469         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
470         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
471         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
472         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
473         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
474         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
475         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
476         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
477
478        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
479         - json_schemas.DatasetsJSON | json_schemas.RateLimitJSON: Dataset information or rate limit message.
480
481        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
482         - ValueError: If 'limit' parameter exceeds 1000.
483         - aiohttp.ClientResponseError: If the request fails.
484         - MissingTokenError: If authentication is missing.
485
486        <span style="color:#E67E22; font-weight:bold">Performance Tips:</span>
487        - Use as many filter parameters as possible to reduce result size and improve response time
488        - For large result sets, use pagination (limit and offset) to retrieve data in manageable chunks
489        - Consider caching results for frequently accessed dataset information
490        """  # noqa: E501
491        return cast(
492            json_schemas.DatasetsJSON | json_schemas.RateLimitJSON,
493            await self._make_request(
494                f"{self.ENDPOINT}/datasets",
495                parameters={
496                    "datatypeid": "&".join(datatypeid)
497                    if isinstance(datatypeid, list)
498                    else datatypeid,
499                    "locationid": "&".join(locationid)
500                    if isinstance(locationid, list)
501                    else locationid,
502                    "stationid": "&".join(stationid)
503                    if isinstance(stationid, list)
504                    else stationid,
505                    "startdate": startdate,
506                    "enddate": enddate,
507                    "sortfield": sortfield,
508                    "sortorder": sortorder,
509                    "limit": limit,
510                    "offset": offset,
511                },
512                token_parameter=token_parameter,
513            ),
514        )

Query information about available datasets. Endpoint: /datasets

Retrieves a list of datasets matching the specified filter criteria. This endpoint allows comprehensive filtering to find datasets containing specific data types, locations, date ranges, and more.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datatypeid (str | list[str], optional): Filter by data type ID(s). Defaults to "".
  • locationid (str | list[str], optional): Filter by location ID(s). Defaults to "".
  • stationid (str | list[str], optional): Filter by station ID(s). Defaults to "".
  • startdate (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • enddate (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • sortfield (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.

Returns:

  • json_schemas.DatasetsJSON | json_schemas.RateLimitJSON: Dataset information or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Performance Tips:

  • Use as many filter parameters as possible to reduce result size and improve response time
  • For large result sets, use pagination (limit and offset) to retrieve data in manageable chunks
  • Consider caching results for frequently accessed dataset information
async def get_data_category_by_id( self, id: str, token_parameter: str | None = None) -> noaa_api.json_schemas.DatacategoryIDJSON | noaa_api.json_schemas.RateLimitJSON:
516    async def get_data_category_by_id(
517        self, id: str, token_parameter: str | None = None
518    ) -> json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON:
519        """
520        <span style="color:#4E97D8; font-weight:bold">Query information about a specific data category by ID.</span>
521        <span style="color:#3498DB">Endpoint: `/datacategories/{id}`</span>
522
523        Retrieves detailed information about a single data category identified by its unique ID.
524        Data categories represent broad classifications of the types of data available.
525
526        <span style="color:#2ECC71; font-weight:bold">Args:</span>
527         - <span style="color:#9B59B6">id</span> (str): The ID of the data category to retrieve.
528         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
529           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
530           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
531
532        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
533         - json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
534           data category information or rate limit message.
535
536        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
537         - aiohttp.ClientResponseError: If the request fails.
538         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
539
540        <span style="color:#E67E22; font-weight:bold">Note:</span>
541        Individual ID lookups are more efficient than querying all data categories when you know the specific ID.
542        """  # noqa: E501
543        return cast(
544            json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON,
545            await self._make_request(
546                f"{self.ENDPOINT}/datacategories/{id}", token_parameter=token_parameter
547            ),
548        )

Query information about a specific data category by ID. Endpoint: /datacategories/{id}

Retrieves detailed information about a single data category identified by its unique ID. Data categories represent broad classifications of the types of data available.

Args:

  • id (str): The ID of the data category to retrieve.
  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None. Can be provided if token attribute is not provided anywhere (client headers or attribute). Token parameter will not persist between calls.

Returns:

  • json_schemas.DatacategoryIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing data category information or rate limit message.

Raises:

  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If the client header token, attribute token, and parameter token_parameter are all not provided.

Note: Individual ID lookups are more efficient than querying all data categories when you know the specific ID.

async def get_data_categories( self, *, token_parameter: str | None = None, datasetid: str | list[str] = '', locationid: str | list[str] = '', stationid: str | list[str] = '', startdate: str = '0001-01-01', enddate: str = '0001-01-01', sortfield: Literal['id', 'name', 'mindate', 'maxdate', 'datacoverage', ''] = 'id', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0) -> noaa_api.json_schemas.DatacategoriesJSON | noaa_api.json_schemas.RateLimitJSON:
550    async def get_data_categories(
551        self,
552        *,
553        token_parameter: str | None = None,
554        datasetid: str | list[str] = "",
555        locationid: str | list[str] = "",
556        stationid: str | list[str] = "",
557        startdate: str = "0001-01-01",
558        enddate: str = "0001-01-01",
559        sortfield: parameter_schemas.Sortfield = "id",
560        sortorder: parameter_schemas.Sortorder = "asc",
561        limit: int = 25,
562        offset: int = 0,
563    ) -> json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON:
564        """
565        <span style="color:#4E97D8; font-weight:bold">Query information about available data categories.</span>
566        <span style="color:#3498DB">Endpoint: `/datacategories`</span>
567
568        Retrieves a list of data categories matching the specified filter criteria. Data categories
569        are high-level classifications for the types of data available through the NOAA API.
570
571        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
572        List parameters are automatically formatted as ampersand-separated strings.
573        Providing a string or list of strings of ampersand-separated values is also supported.
574
575        <span style="color:#2ECC71; font-weight:bold">Args:</span>
576         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
577           over `token` attribute. Defaults to None.
578         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
579         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
580         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
581         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
582         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
583         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
584         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
585         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
586         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
587
588        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
589         - json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON: Data categories information or rate limit message.
590
591        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
592         - ValueError: If 'limit' parameter exceeds 1000.
593         - aiohttp.ClientResponseError: If the request fails.
594         - MissingTokenError: If authentication is missing.
595
596        <span style="color:#E67E22; font-weight:bold">Usage Tip:</span>
597        Data categories are useful for exploratory navigation of the NOAA data. Use this endpoint to
598        discover broad categories before drilling down to specific data types within those categories.
599        """  # noqa: E501
600        return cast(
601            json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON,
602            await self._make_request(
603                f"{self.ENDPOINT}/datacategories",
604                parameters={
605                    "datasetid": "&".join(datasetid)
606                    if isinstance(datasetid, list)
607                    else datasetid,
608                    "locationid": "&".join(locationid)
609                    if isinstance(locationid, list)
610                    else locationid,
611                    "stationid": "&".join(stationid)
612                    if isinstance(stationid, list)
613                    else stationid,
614                    "startdate": startdate,
615                    "enddate": enddate,
616                    "sortfield": sortfield,
617                    "sortorder": sortorder,
618                    "limit": limit,
619                    "offset": offset,
620                },
621                token_parameter=token_parameter,
622            ),
623        )

Query information about available data categories. Endpoint: /datacategories

Retrieves a list of data categories matching the specified filter criteria. Data categories are high-level classifications for the types of data available through the NOAA API.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datasetid (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
  • locationid (str | list[str], optional): Filter by location ID(s). Defaults to "".
  • stationid (str | list[str], optional): Filter by station ID(s). Defaults to "".
  • startdate (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • enddate (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • sortfield (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.

Returns:

  • json_schemas.DatacategoriesJSON | json_schemas.RateLimitJSON: Data categories information or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Usage Tip: Data categories are useful for exploratory navigation of the NOAA data. Use this endpoint to discover broad categories before drilling down to specific data types within those categories.

async def get_datatype_by_id( self, id: str, token_parameter: str | None = None) -> noaa_api.json_schemas.DatatypeIDJSON | noaa_api.json_schemas.RateLimitJSON:
625    async def get_datatype_by_id(
626        self, id: str, token_parameter: str | None = None
627    ) -> json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON:
628        """
629        <span style="color:#4E97D8; font-weight:bold">Query information about a specific data type by ID.</span>
630        <span style="color:#3498DB">Endpoint: `/datatypes/{id}`</span>
631
632        Retrieves detailed information about a single data type identified by its unique ID.
633        Data types represent specific measurements or observations available in the NOAA datasets.
634
635        <span style="color:#2ECC71; font-weight:bold">Args:</span>
636         - <span style="color:#9B59B6">id</span> (str): The ID of the data type to retrieve.
637         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
638           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
639           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
640
641        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
642         - json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
643           data type information or rate limit message.
644
645        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
646         - aiohttp.ClientResponseError: If the request fails.
647         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
648
649        <span style="color:#E67E22; font-weight:bold">Data Type Details:</span>
650        Individual data type records include information about the measurement units, period,
651        and other important metadata that helps interpret the actual climate data.
652        """  # noqa: E501
653        return cast(
654            json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON,
655            await self._make_request(
656                f"{self.ENDPOINT}/datatypes/{id}", token_parameter=token_parameter
657            ),
658        )

Query information about a specific data type by ID. Endpoint: /datatypes/{id}

Retrieves detailed information about a single data type identified by its unique ID. Data types represent specific measurements or observations available in the NOAA datasets.

Args:

  • id (str): The ID of the data type to retrieve.
  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None. Can be provided if token attribute is not provided anywhere (client headers or attribute). Token parameter will not persist between calls.

Returns:

  • json_schemas.DatatypeIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing data type information or rate limit message.

Raises:

  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If the client header token, attribute token, and parameter token_parameter are all not provided.

Data Type Details: Individual data type records include information about the measurement units, period, and other important metadata that helps interpret the actual climate data.

async def get_datatypes( self, *, token_parameter: str | None = None, datasetid: str | list[str] = '', locationid: str | list[str] = '', stationid: str | list[str] = '', datacategoryid: str | list[str] = '', startdate: str = '0001-01-01', enddate: str = '0001-01-01', sortfield: Literal['id', 'name', 'mindate', 'maxdate', 'datacoverage', ''] = 'id', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0) -> noaa_api.json_schemas.DatatypesJSON | noaa_api.json_schemas.RateLimitJSON:
660    async def get_datatypes(
661        self,
662        *,
663        token_parameter: str | None = None,
664        datasetid: str | list[str] = "",
665        locationid: str | list[str] = "",
666        stationid: str | list[str] = "",
667        datacategoryid: str | list[str] = "",
668        startdate: str = "0001-01-01",
669        enddate: str = "0001-01-01",
670        sortfield: parameter_schemas.Sortfield = "id",
671        sortorder: parameter_schemas.Sortorder = "asc",
672        limit: int = 25,
673        offset: int = 0,
674    ) -> json_schemas.DatatypesJSON | json_schemas.RateLimitJSON:
675        """
676        <span style="color:#4E97D8; font-weight:bold">Query information about available data types.</span>
677        <span style="color:#3498DB">Endpoint: `/datatypes`</span>
678
679        Retrieves a list of data types matching the specified filter criteria. Data types
680        represent specific climate measurements or observations available in the NOAA datasets,
681        such as temperature, precipitation, wind speed, etc.
682
683        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
684        List parameters are automatically formatted as ampersand-separated strings.
685        Providing a string or list of strings of ampersand-separated values is also supported.
686
687        <span style="color:#2ECC71; font-weight:bold">Args:</span>
688         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
689           over `token` attribute. Defaults to None.
690         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
691         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
692         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
693         - <span style="color:#9B59B6">datacategoryid</span> (str | list[str], optional): Filter by data category ID(s). Defaults to "".
694         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
695         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
696         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
697         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
698         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
699         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
700
701        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
702         - json_schemas.DatatypesJSON | json_schemas.RateLimitJSON: Data types information or rate limit message.
703
704        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
705         - ValueError: If 'limit' parameter exceeds 1000.
706         - aiohttp.ClientResponseError: If the request fails.
707         - MissingTokenError: If authentication is missing.
708
709        <span style="color:#E67E22; font-weight:bold">Research Tip:</span>
710        When planning a climate data analysis project, first explore available data types to
711        determine which measurements are available for your region and time period of interest.
712        Use datacategoryid to narrow down to relevant measurement categories.
713        """  # noqa: E501
714        return cast(
715            json_schemas.DatatypesJSON | json_schemas.RateLimitJSON,
716            await self._make_request(
717                f"{self.ENDPOINT}/datatypes",
718                parameters={
719                    "datasetid": "&".join(datasetid)
720                    if isinstance(datasetid, list)
721                    else datasetid,
722                    "locationid": "&".join(locationid)
723                    if isinstance(locationid, list)
724                    else locationid,
725                    "stationid": "&".join(stationid)
726                    if isinstance(stationid, list)
727                    else stationid,
728                    "datacategoryid": "&".join(datacategoryid)
729                    if isinstance(datacategoryid, list)
730                    else datacategoryid,
731                    "startdate": startdate,
732                    "enddate": enddate,
733                    "sortfield": sortfield,
734                    "sortorder": sortorder,
735                    "limit": limit,
736                    "offset": offset,
737                },
738                token_parameter=token_parameter,
739            ),
740        )

Query information about available data types. Endpoint: /datatypes

Retrieves a list of data types matching the specified filter criteria. Data types represent specific climate measurements or observations available in the NOAA datasets, such as temperature, precipitation, wind speed, etc.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datasetid (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
  • locationid (str | list[str], optional): Filter by location ID(s). Defaults to "".
  • stationid (str | list[str], optional): Filter by station ID(s). Defaults to "".
  • datacategoryid (str | list[str], optional): Filter by data category ID(s). Defaults to "".
  • startdate (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • enddate (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • sortfield (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.

Returns:

  • json_schemas.DatatypesJSON | json_schemas.RateLimitJSON: Data types information or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Research Tip: When planning a climate data analysis project, first explore available data types to determine which measurements are available for your region and time period of interest. Use datacategoryid to narrow down to relevant measurement categories.

async def get_location_category_by_id( self, id: str, token_parameter: str | None = None) -> noaa_api.json_schemas.LocationcategoryIDJSON | noaa_api.json_schemas.RateLimitJSON:
742    async def get_location_category_by_id(
743        self, id: str, token_parameter: str | None = None
744    ) -> json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON:
745        """
746        <span style="color:#4E97D8; font-weight:bold">Query information about a specific location category by ID.</span>
747        <span style="color:#3498DB">Endpoint: `/locationcategories/{id}`</span>
748
749        Retrieves detailed information about a single location category identified by its unique ID.
750        Location categories classify the types of locations available in the NOAA data (e.g., cities, counties, states).
751
752        <span style="color:#2ECC71; font-weight:bold">Args:</span>
753         - <span style="color:#9B59B6">id</span> (str): The ID of the location category to retrieve.
754         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
755           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
756           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
757
758        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
759         - json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
760           location category information or rate limit message.
761
762        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
763         - aiohttp.ClientResponseError: If the request fails.
764         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
765
766        <span style="color:#E67E22; font-weight:bold">Usage Context:</span>
767        Location categories provide a way to understand the different geographical hierarchies
768        available in the NOAA climate data. This is particularly useful when designing
769        geospatial visualizations or analyses across different territorial divisions.
770        """  # noqa: E501
771        return cast(
772            json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON,
773            await self._make_request(
774                f"{self.ENDPOINT}/locationcategories/{id}",
775                token_parameter=token_parameter,
776            ),
777        )

Query information about a specific location category by ID. Endpoint: /locationcategories/{id}

Retrieves detailed information about a single location category identified by its unique ID. Location categories classify the types of locations available in the NOAA data (e.g., cities, counties, states).

Args:

  • id (str): The ID of the location category to retrieve.
  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None. Can be provided if token attribute is not provided anywhere (client headers or attribute). Token parameter will not persist between calls.

Returns:

  • json_schemas.LocationcategoryIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing location category information or rate limit message.

Raises:

  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If the client header token, attribute token, and parameter token_parameter are all not provided.

Usage Context: Location categories provide a way to understand the different geographical hierarchies available in the NOAA climate data. This is particularly useful when designing geospatial visualizations or analyses across different territorial divisions.

async def get_location_categories( self, *, token_parameter: str | None = None, datasetid: str | list[str] = '', locationid: str | list[str] = '', startdate: str = '0001-01-01', enddate: str = '0001-01-01', sortfield: Literal['id', 'name', 'mindate', 'maxdate', 'datacoverage', ''] = 'id', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0) -> noaa_api.json_schemas.LocationcategoriesJSON | noaa_api.json_schemas.RateLimitJSON:
779    async def get_location_categories(
780        self,
781        *,
782        token_parameter: str | None = None,
783        datasetid: str | list[str] = "",
784        locationid: str | list[str] = "",
785        startdate: str = "0001-01-01",
786        enddate: str = "0001-01-01",
787        sortfield: parameter_schemas.Sortfield = "id",
788        sortorder: parameter_schemas.Sortorder = "asc",
789        limit: int = 25,
790        offset: int = 0,
791    ) -> json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON:
792        """
793        <span style="color:#4E97D8; font-weight:bold">Query information about available location categories.</span>
794        <span style="color:#3498DB">Endpoint: `/locationcategories`</span>
795
796        Retrieves a list of location categories matching the specified filter criteria. Location categories
797        classify the geographical hierarchies available in the NOAA climate data, such as cities, counties,
798        states, countries, or other territorial divisions.
799
800        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
801        List parameters are automatically formatted as ampersand-separated strings.
802        Providing a string or list of strings of ampersand-separated values is also supported.
803
804        <span style="color:#2ECC71; font-weight:bold">Args:</span>
805         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
806           over `token` attribute. Defaults to None.
807         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
808         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
809         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
810         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
811         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
812         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
813         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
814         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
815
816        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
817         - json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON: Location categories information or rate limit message.
818
819        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
820         - ValueError: If 'limit' parameter exceeds 1000.
821         - aiohttp.ClientResponseError: If the request fails.
822         - MissingTokenError: If authentication is missing.
823
824        <span style="color:#E67E22; font-weight:bold">Geographical Analysis Tip:</span>
825        Location categories help organize spatial data into logical hierarchies. When designing
826        geographical analyses, first explore the available location categories to determine
827        the most appropriate spatial resolution for your research question.
828        """  # noqa: E501
829        return cast(
830            json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON,
831            await self._make_request(
832                f"{self.ENDPOINT}/locationcategories",
833                parameters={
834                    "datasetid": "&".join(datasetid)
835                    if isinstance(datasetid, list)
836                    else datasetid,
837                    "locationid": "&".join(locationid)
838                    if isinstance(locationid, list)
839                    else locationid,
840                    "startdate": startdate,
841                    "enddate": enddate,
842                    "sortfield": sortfield,
843                    "sortorder": sortorder,
844                    "limit": limit,
845                    "offset": offset,
846                },
847                token_parameter=token_parameter,
848            ),
849        )

Query information about available location categories. Endpoint: /locationcategories

Retrieves a list of location categories matching the specified filter criteria. Location categories classify the geographical hierarchies available in the NOAA climate data, such as cities, counties, states, countries, or other territorial divisions.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datasetid (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
  • locationid (str | list[str], optional): Filter by location ID(s). Defaults to "".
  • startdate (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • enddate (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • sortfield (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.

Returns:

  • json_schemas.LocationcategoriesJSON | json_schemas.RateLimitJSON: Location categories information or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Geographical Analysis Tip: Location categories help organize spatial data into logical hierarchies. When designing geographical analyses, first explore the available location categories to determine the most appropriate spatial resolution for your research question.

async def get_location_by_id( self, id: str, token_parameter: str | None = None) -> noaa_api.json_schemas.LocationIDJSON | noaa_api.json_schemas.RateLimitJSON:
851    async def get_location_by_id(
852        self, id: str, token_parameter: str | None = None
853    ) -> json_schemas.LocationIDJSON | json_schemas.RateLimitJSON:
854        """
855        <span style="color:#4E97D8; font-weight:bold">Query information about a specific location by ID.</span>
856        <span style="color:#3498DB">Endpoint: `/locations/{id}`</span>
857
858        Retrieves detailed information about a single location identified by its unique ID.
859        Locations represent geographical areas where climate data is collected.
860
861        <span style="color:#2ECC71; font-weight:bold">Args:</span>
862         - <span style="color:#9B59B6">id</span> (str): The ID of the location to retrieve.
863         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
864           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
865           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
866
867        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
868         - json_schemas.LocationIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
869           location information or rate limit message.
870
871        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
872         - aiohttp.ClientResponseError: If the request fails.
873         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
874
875        <span style="color:#E67E22; font-weight:bold">Location Details:</span>
876        Individual location records include important metadata such as coordinates, names,
877        and other geographical attributes that help interpret the climate data associated
878        with the location.
879        """  # noqa: E501
880        return cast(
881            json_schemas.LocationIDJSON | json_schemas.RateLimitJSON,
882            await self._make_request(
883                f"{self.ENDPOINT}/locations/{id}", token_parameter=token_parameter
884            ),
885        )

Query information about a specific location by ID. Endpoint: /locations/{id}

Retrieves detailed information about a single location identified by its unique ID. Locations represent geographical areas where climate data is collected.

Args:

  • id (str): The ID of the location to retrieve.
  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None. Can be provided if token attribute is not provided anywhere (client headers or attribute). Token parameter will not persist between calls.

Returns:

  • json_schemas.LocationIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing location information or rate limit message.

Raises:

  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If the client header token, attribute token, and parameter token_parameter are all not provided.

Location Details: Individual location records include important metadata such as coordinates, names, and other geographical attributes that help interpret the climate data associated with the location.

async def get_locations( self, *, token_parameter: str | None = None, datasetid: str | list[str] = '', locationcategoryid: str | list[str] = '', datacategoryid: str | list[str] = '', startdate: str = '0001-01-01', enddate: str = '0001-01-01', sortfield: Literal['id', 'name', 'mindate', 'maxdate', 'datacoverage', ''] = 'id', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0) -> noaa_api.json_schemas.LocationsJSON | noaa_api.json_schemas.RateLimitJSON:
887    async def get_locations(
888        self,
889        *,
890        token_parameter: str | None = None,
891        datasetid: str | list[str] = "",
892        locationcategoryid: str | list[str] = "",
893        datacategoryid: str | list[str] = "",
894        startdate: str = "0001-01-01",
895        enddate: str = "0001-01-01",
896        sortfield: parameter_schemas.Sortfield = "id",
897        sortorder: parameter_schemas.Sortorder = "asc",
898        limit: int = 25,
899        offset: int = 0,
900    ) -> json_schemas.LocationsJSON | json_schemas.RateLimitJSON:
901        """
902        <span style="color:#4E97D8; font-weight:bold">Query information about available locations.</span>
903        <span style="color:#3498DB">Endpoint: `/locations`</span>
904
905        Retrieves a list of locations matching the specified filter criteria. Locations represent
906        geographical areas where climate data is collected, such as cities, counties, states,
907        countries, or other territorial divisions.
908
909        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
910        List parameters are automatically formatted as ampersand-separated strings.
911        Providing a string or list of strings of ampersand-separated values is also supported.
912
913        <span style="color:#2ECC71; font-weight:bold">Args:</span>
914         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
915           over `token` attribute. Defaults to None.
916         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
917         - <span style="color:#9B59B6">locationcategoryid</span> (str | list[str], optional): Filter by location category ID(s). Defaults to "".
918         - <span style="color:#9B59B6">datacategoryid</span> (str | list[str], optional): Filter by data category ID(s). Defaults to "".
919         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
920         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
921         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
922         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
923         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
924         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
925
926        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
927         - json_schemas.LocationsJSON | json_schemas.RateLimitJSON: Locations information or rate limit message.
928
929        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
930         - ValueError: If 'limit' parameter exceeds 1000.
931         - aiohttp.ClientResponseError: If the request fails.
932         - MissingTokenError: If authentication is missing.
933
934        <span style="color:#E67E22; font-weight:bold">Spatial Analysis Tip:</span>
935        When working with climate data across geographical regions, use the locationcategoryid
936        parameter to narrow down locations to a specific category (e.g., states, countries)
937        for more consistent analysis. Combine with datacategoryid to find locations where
938        specific types of measurements are available.
939        """  # noqa: E501
940        return cast(
941            json_schemas.LocationsJSON | json_schemas.RateLimitJSON,
942            await self._make_request(
943                f"{self.ENDPOINT}/locations",
944                parameters={
945                    "datasetid": "&".join(datasetid)
946                    if isinstance(datasetid, list)
947                    else datasetid,
948                    "locationcategoryid": "&".join(locationcategoryid)
949                    if isinstance(locationcategoryid, list)
950                    else locationcategoryid,
951                    "datacategoryid": "&".join(datacategoryid)
952                    if isinstance(datacategoryid, list)
953                    else datacategoryid,
954                    "startdate": startdate,
955                    "enddate": enddate,
956                    "sortfield": sortfield,
957                    "sortorder": sortorder,
958                    "limit": limit,
959                    "offset": offset,
960                },
961                token_parameter=token_parameter,
962            ),
963        )

Query information about available locations. Endpoint: /locations

Retrieves a list of locations matching the specified filter criteria. Locations represent geographical areas where climate data is collected, such as cities, counties, states, countries, or other territorial divisions.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datasetid (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
  • locationcategoryid (str | list[str], optional): Filter by location category ID(s). Defaults to "".
  • datacategoryid (str | list[str], optional): Filter by data category ID(s). Defaults to "".
  • startdate (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • enddate (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • sortfield (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.

Returns:

  • json_schemas.LocationsJSON | json_schemas.RateLimitJSON: Locations information or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Spatial Analysis Tip: When working with climate data across geographical regions, use the locationcategoryid parameter to narrow down locations to a specific category (e.g., states, countries) for more consistent analysis. Combine with datacategoryid to find locations where specific types of measurements are available.

async def get_station_by_id( self, id: str, token_parameter: str | None = None) -> noaa_api.json_schemas.StationIDJSON | noaa_api.json_schemas.RateLimitJSON:
965    async def get_station_by_id(
966        self, id: str, token_parameter: str | None = None
967    ) -> json_schemas.StationIDJSON | json_schemas.RateLimitJSON:
968        """
969        <span style="color:#4E97D8; font-weight:bold">Query information about a specific weather station by ID.</span>
970        <span style="color:#3498DB">Endpoint: `/stations/{id}`</span>
971
972        Retrieves detailed information about a single weather station identified by its unique ID.
973        Stations are physical locations where weather and climate data measurements are collected.
974
975        <span style="color:#2ECC71; font-weight:bold">Args:</span>
976         - <span style="color:#9B59B6">id</span> (str): The ID of the station to retrieve.
977         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
978           over `token` attribute. Defaults to None. Can be provided if `token` attribute is not provided
979           anywhere (client headers or attribute). Token parameter will **not** persist between calls.
980
981        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
982         - json_schemas.StationIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing
983           station information or rate limit message.
984
985        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
986         - aiohttp.ClientResponseError: If the request fails.
987         - MissingTokenError: If the client header `token`, attribute `token`, and parameter `token_parameter` are all not provided.
988
989        <span style="color:#E67E22; font-weight:bold">Data Precision:</span>
990        Weather stations provide the most accurate and localized climate data since they
991        represent exact measurement points. Station-level data is particularly valuable
992        for precise local analyses and ground-truthing other data sources.
993        """  # noqa: E501
994        return cast(
995            json_schemas.StationIDJSON | json_schemas.RateLimitJSON,
996            await self._make_request(
997                f"{self.ENDPOINT}/stations/{id}", token_parameter=token_parameter
998            ),
999        )

Query information about a specific weather station by ID. Endpoint: /stations/{id}

Retrieves detailed information about a single weather station identified by its unique ID. Stations are physical locations where weather and climate data measurements are collected.

Args:

  • id (str): The ID of the station to retrieve.
  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None. Can be provided if token attribute is not provided anywhere (client headers or attribute). Token parameter will not persist between calls.

Returns:

  • json_schemas.StationIDJSON | json_schemas.RateLimitJSON: Parsed JSON response containing station information or rate limit message.

Raises:

  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If the client header token, attribute token, and parameter token_parameter are all not provided.

Data Precision: Weather stations provide the most accurate and localized climate data since they represent exact measurement points. Station-level data is particularly valuable for precise local analyses and ground-truthing other data sources.

async def get_stations( self, *, token_parameter: str | None = None, datasetid: str | list[str] = '', locationid: str | list[str] = '', datacategoryid: str | list[str] = '', datatypeid: str | list[str] = '', extent: str = '', startdate: str = '0001-01-01', enddate: str = '0001-01-01', sortfield: Literal['id', 'name', 'mindate', 'maxdate', 'datacoverage', ''] = 'id', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0) -> noaa_api.json_schemas.StationsJSON | noaa_api.json_schemas.RateLimitJSON:
1001    async def get_stations(
1002        self,
1003        *,
1004        token_parameter: str | None = None,
1005        datasetid: str | list[str] = "",
1006        locationid: str | list[str] = "",
1007        datacategoryid: str | list[str] = "",
1008        datatypeid: str | list[str] = "",
1009        extent: str = "",
1010        startdate: str = "0001-01-01",
1011        enddate: str = "0001-01-01",
1012        sortfield: parameter_schemas.Sortfield = "id",
1013        sortorder: parameter_schemas.Sortorder = "asc",
1014        limit: int = 25,
1015        offset: int = 0,
1016    ) -> json_schemas.StationsJSON | json_schemas.RateLimitJSON:
1017        """
1018        <span style="color:#4E97D8; font-weight:bold">Query information about available weather stations.</span>
1019        <span style="color:#3498DB">Endpoint: `/stations`</span>
1020
1021        Retrieves a list of weather stations matching the specified filter criteria. Weather stations
1022        are the physical locations where climate measurements are recorded, and typically provide
1023        the most precise and localized data available.
1024
1025        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
1026        List parameters are automatically formatted as ampersand-separated strings.
1027        Providing a string or list of strings of ampersand-separated values is also supported.
1028
1029        <span style="color:#2ECC71; font-weight:bold">Args:</span>
1030         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
1031           over `token` attribute. Defaults to None.
1032         - <span style="color:#9B59B6">datasetid</span> (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
1033         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
1034         - <span style="color:#9B59B6">datacategoryid</span> (str | list[str], optional): Filter by data category ID(s). Defaults to "".
1035         - <span style="color:#9B59B6">datatypeid</span> (str | list[str], optional): Filter by data type ID(s). Defaults to "".
1036         - <span style="color:#9B59B6">extent</span> (str, optional): Geospatial extent (bbox) filter in format "north,west,south,east". Defaults to "".
1037         - <span style="color:#9B59B6">startdate</span> (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
1038         - <span style="color:#9B59B6">enddate</span> (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
1039         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
1040         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
1041         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
1042         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
1043
1044        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
1045         - json_schemas.StationsJSON | json_schemas.RateLimitJSON: Stations information or rate limit message.
1046
1047        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
1048         - ValueError: If 'limit' parameter exceeds 1000.
1049         - aiohttp.ClientResponseError: If the request fails.
1050         - MissingTokenError: If authentication is missing.
1051
1052        <span style="color:#E67E22; font-weight:bold">Geospatial Filtering:</span>
1053        The stations endpoint is one of the few that supports the "extent" parameter for
1054        geographical bounding box filtering. This is particularly useful for finding all
1055        stations within a specific region defined by coordinates. For example:
1056        "extent=42.0,-90.0,40.0,-88.0" would find stations within that rectangle.
1057        """  # noqa: E501
1058        return cast(
1059            json_schemas.StationsJSON | json_schemas.RateLimitJSON,
1060            await self._make_request(
1061                f"{self.ENDPOINT}/stations",
1062                parameters={
1063                    "datasetid": "&".join(datasetid)
1064                    if isinstance(datasetid, list)
1065                    else datasetid,
1066                    "locationid": "&".join(locationid)
1067                    if isinstance(locationid, list)
1068                    else locationid,
1069                    "datacategoryid": "&".join(datacategoryid)
1070                    if isinstance(datacategoryid, list)
1071                    else datacategoryid,
1072                    "datatypeid": "&".join(datatypeid)
1073                    if isinstance(datatypeid, list)
1074                    else datatypeid,
1075                    "extent": extent,
1076                    "startdate": startdate,
1077                    "enddate": enddate,
1078                    "sortfield": sortfield,
1079                    "sortorder": sortorder,
1080                    "limit": limit,
1081                    "offset": offset,
1082                },
1083                token_parameter=token_parameter,
1084            ),
1085        )

Query information about available weather stations. Endpoint: /stations

Retrieves a list of weather stations matching the specified filter criteria. Weather stations are the physical locations where climate measurements are recorded, and typically provide the most precise and localized data available.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datasetid (str | list[str], optional): Filter by dataset ID(s). Defaults to "".
  • locationid (str | list[str], optional): Filter by location ID(s). Defaults to "".
  • datacategoryid (str | list[str], optional): Filter by data category ID(s). Defaults to "".
  • datatypeid (str | list[str], optional): Filter by data type ID(s). Defaults to "".
  • extent (str, optional): Geospatial extent (bbox) filter in format "north,west,south,east". Defaults to "".
  • startdate (str, optional): Beginning of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • enddate (str, optional): End of date range in 'YYYY-MM-DD' format. Defaults to "0001-01-01".
  • sortfield (parameter_schemas.Sortfield, optional): Field to sort results by. Defaults to "id".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.

Returns:

  • json_schemas.StationsJSON | json_schemas.RateLimitJSON: Stations information or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Geospatial Filtering: The stations endpoint is one of the few that supports the "extent" parameter for geographical bounding box filtering. This is particularly useful for finding all stations within a specific region defined by coordinates. For example: "extent=42.0,-90.0,40.0,-88.0" would find stations within that rectangle.

async def get_data( self, datasetid: str, startdate: str, enddate: str, *, token_parameter: str | None = None, datatypeid: str | list[str] = '', locationid: str | list[str] = '', stationid: str | list[str] = '', units: Literal['standard', 'metric', ''] = 'standard', sortfield: Literal['datatype', 'date', 'station'] = 'date', sortorder: Literal['asc', 'desc'] = 'asc', limit: int = 25, offset: int = 0, includemetadata: bool = True) -> noaa_api.json_schemas.DataJSON | noaa_api.json_schemas.RateLimitJSON:
1087    async def get_data(
1088        self,
1089        datasetid: str,
1090        startdate: str,  # YYYY-MM-DD
1091        enddate: str,  # YYYY-MM-DD
1092        *,
1093        token_parameter: str | None = None,
1094        datatypeid: str | list[str] = "",
1095        locationid: str | list[str] = "",
1096        stationid: str | list[str] = "",
1097        units: parameter_schemas.Units = "standard",
1098        sortfield: parameter_schemas.DataSortField = "date",
1099        sortorder: parameter_schemas.Sortorder = "asc",
1100        limit: int = 25,
1101        offset: int = 0,
1102        includemetadata: bool = True,
1103    ) -> json_schemas.DataJSON | json_schemas.RateLimitJSON:
1104        """
1105        <span style="color:#4E97D8; font-weight:bold">Query actual climate data with various filtering options.</span>
1106        <span style="color:#3498DB">Endpoint: `/data`</span>
1107
1108        This is the primary endpoint for retrieving actual climate measurements and observations.
1109        Unlike the other endpoints which provide metadata, this endpoint returns the actual
1110        climate data values matching your specified criteria.
1111
1112        <span style="color:#E67E22; font-weight:bold">Required Parameters:</span>
1113        Note that datasetid, startdate, and enddate are all required parameters for this endpoint.
1114        This is different from other endpoints where all filter parameters are optional.
1115
1116        <span style="color:#E67E22; font-weight:bold">Parameter Formatting:</span>
1117        List parameters are automatically formatted as ampersand-separated strings.
1118        Providing a string or list of strings of ampersand-separated values is also supported.
1119
1120        <span style="color:#2ECC71; font-weight:bold">Args:</span>
1121         - <span style="color:#9B59B6">token_parameter</span> (str | None, optional): Token parameter which takes precedence
1122           over `token` attribute. Defaults to None.
1123         - <span style="color:#9B59B6">datasetid</span> (str): **Required**. The dataset ID to query data from.
1124         - <span style="color:#9B59B6">startdate</span> (str): **Required**. Beginning of date range in 'YYYY-MM-DD' format.
1125         - <span style="color:#9B59B6">enddate</span> (str): **Required**. End of date range in 'YYYY-MM-DD' format.
1126         - <span style="color:#9B59B6">datatypeid</span> (str | list[str], optional): Filter by data type ID(s). Defaults to "".
1127         - <span style="color:#9B59B6">locationid</span> (str | list[str], optional): Filter by location ID(s). Defaults to "".
1128         - <span style="color:#9B59B6">stationid</span> (str | list[str], optional): Filter by station ID(s). Defaults to "".
1129         - <span style="color:#9B59B6">units</span> (parameter_schemas.Units, optional): Unit system for data values ("standard" or "metric"). Defaults to "standard".
1130         - <span style="color:#9B59B6">sortfield</span> (parameter_schemas.DataSortfield, optional): Field to sort results by. Defaults to "date".
1131         - <span style="color:#9B59B6">sortorder</span> (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
1132         - <span style="color:#9B59B6">limit</span> (int, optional): Maximum number of results to return. Defaults to 25.
1133         - <span style="color:#9B59B6">offset</span> (int, optional): Number of results to skip for pagination. Defaults to 0.
1134         - <span style="color:#9B59B6">includemetadata</span> (bool, optional): Whether to include metadata in the response. Defaults to True.
1135
1136        <span style="color:#2ECC71; font-weight:bold">Returns:</span>
1137         - json_schemas.DataJSON | json_schemas.RateLimitJSON: Climate data or rate limit message.
1138
1139        <span style="color:#E74C3C; font-weight:bold">Raises:</span>
1140         - ValueError: If 'limit' parameter exceeds 1000 or if required parameters are missing.
1141         - aiohttp.ClientResponseError: If the request fails.
1142         - MissingTokenError: If authentication is missing.
1143
1144        <span style="color:#E67E22; font-weight:bold">Data Volume Considerations:</span>
1145        Climate data queries can return large volumes of data, especially with broad date ranges
1146        or multiple stations/locations. To manage data volume:
1147
1148        1. Use narrow date ranges when possible
1149        2. Specify particular stations or locations instead of querying all
1150        3. Filter to only the data types you need
1151        4. Use pagination (limit and offset) for large result sets
1152        5. Consider setting includemetadata=False if you don't need the metadata
1153
1154        <span style="color:#E67E22; font-weight:bold">Performance Note:</span>
1155        This endpoint is often the most resource-intensive and may take longer to respond
1156        than metadata endpoints. When developing applications, implement appropriate timeout
1157        handling and consider caching frequently accessed data.
1158        """  # noqa: E501
1159
1160        return cast(
1161            json_schemas.DataJSON | json_schemas.RateLimitJSON,
1162            await self._make_request(
1163                f"{self.ENDPOINT}/data",
1164                parameters={
1165                    "datasetid": datasetid,
1166                    "startdate": startdate,
1167                    "enddate": enddate,
1168                    "datatypeid": "&".join(datatypeid)
1169                    if isinstance(datatypeid, list)
1170                    else datatypeid,
1171                    "locationid": "&".join(locationid)
1172                    if isinstance(locationid, list)
1173                    else locationid,
1174                    "stationid": "&".join(stationid)
1175                    if isinstance(stationid, list)
1176                    else stationid,
1177                    "units": units,
1178                    "sortfield": sortfield,
1179                    "sortorder": sortorder,
1180                    "limit": limit,
1181                    "offset": offset,
1182                    "includemetadata": "true" if includemetadata else "false",
1183                },
1184                token_parameter=token_parameter,
1185            ),
1186        )

Query actual climate data with various filtering options. Endpoint: /data

This is the primary endpoint for retrieving actual climate measurements and observations. Unlike the other endpoints which provide metadata, this endpoint returns the actual climate data values matching your specified criteria.

Required Parameters: Note that datasetid, startdate, and enddate are all required parameters for this endpoint. This is different from other endpoints where all filter parameters are optional.

Parameter Formatting: List parameters are automatically formatted as ampersand-separated strings. Providing a string or list of strings of ampersand-separated values is also supported.

Args:

  • token_parameter (str | None, optional): Token parameter which takes precedence over token attribute. Defaults to None.
  • datasetid (str): Required. The dataset ID to query data from.
  • startdate (str): Required. Beginning of date range in 'YYYY-MM-DD' format.
  • enddate (str): Required. End of date range in 'YYYY-MM-DD' format.
  • datatypeid (str | list[str], optional): Filter by data type ID(s). Defaults to "".
  • locationid (str | list[str], optional): Filter by location ID(s). Defaults to "".
  • stationid (str | list[str], optional): Filter by station ID(s). Defaults to "".
  • units (parameter_schemas.Units, optional): Unit system for data values ("standard" or "metric"). Defaults to "standard".
  • sortfield (parameter_schemas.DataSortfield, optional): Field to sort results by. Defaults to "date".
  • sortorder (parameter_schemas.Sortorder, optional): Direction of sort ("asc" or "desc"). Defaults to "asc".
  • limit (int, optional): Maximum number of results to return. Defaults to 25.
  • offset (int, optional): Number of results to skip for pagination. Defaults to 0.
  • includemetadata (bool, optional): Whether to include metadata in the response. Defaults to True.

Returns:

  • json_schemas.DataJSON | json_schemas.RateLimitJSON: Climate data or rate limit message.

Raises:

  • ValueError: If 'limit' parameter exceeds 1000 or if required parameters are missing.
  • aiohttp.ClientResponseError: If the request fails.
  • MissingTokenError: If authentication is missing.

Data Volume Considerations: Climate data queries can return large volumes of data, especially with broad date ranges or multiple stations/locations. To manage data volume:

  1. Use narrow date ranges when possible
  2. Specify particular stations or locations instead of querying all
  3. Filter to only the data types you need
  4. Use pagination (limit and offset) for large result sets
  5. Consider setting includemetadata=False if you don't need the metadata

Performance Note: This endpoint is often the most resource-intensive and may take longer to respond than metadata endpoints. When developing applications, implement appropriate timeout handling and consider caching frequently accessed data.

def close(self) -> None:
1188    def close(self) -> None:
1189        """
1190        <span style="color:#4E97D8; font-weight:bold">Close the aiohttp session and TCP connector.</span>
1191
1192        This method properly cleans up resources used by the client. It should be called
1193        when you're done using the client to ensure proper cleanup of network connections
1194        and resources.
1195
1196        <span style="color:#E67E22; font-weight:bold">Resource Management:</span>
1197        - Always call this method when you're finished with the client
1198        - Alternatively, use the client as an async context manager with the `async with` statement,
1199          which will automatically close resources on exit
1200        - If you provided your own aiohttp session with `provide_aiohttp_client_session()`,
1201          this method will not close that session
1202
1203        <span style="color:#E67E22; font-weight:bold">Implementation Note:</span>
1204        This is a synchronous method that doesn't properly close the aiohttp session, which
1205        should be closed using `await session.close()`. For proper async cleanup, use
1206        the client as an async context manager instead.
1207        """  # noqa: E501
1208
1209        if isinstance(self.aiohttp_session, aiohttp.ClientSession):
1210            try:
1211                loop = asyncio.get_event_loop()
1212                _ = loop.create_task(self.aiohttp_session.close())
1213
1214            except RuntimeError:
1215                asyncio.run(self.aiohttp_session.close())

Close the aiohttp session and TCP connector.

This method properly cleans up resources used by the client. It should be called when you're done using the client to ensure proper cleanup of network connections and resources.

Resource Management:

  • Always call this method when you're finished with the client
  • Alternatively, use the client as an async context manager with the async with statement, which will automatically close resources on exit
  • If you provided your own aiohttp session with provide_aiohttp_client_session(), this method will not close that session

Implementation Note: This is a synchronous method that doesn't properly close the aiohttp session, which should be closed using await session.close(). For proper async cleanup, use the client as an async context manager instead.