--- title: "Western Water Datahub EDR with raw HTTP" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Western Water Datahub EDR with raw HTTP} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- This guide shows how to use the [Western Water Datahub](https://api.wwdh.internetofwater.app) EDR API with plain HTTP requests. It does not assume R, Python, JavaScript, or any other client library. If you can open a URL in a browser, use `curl`, or send an HTTP GET request from another tool, you can use these patterns. Use the [Swagger/OpenAPI page](https://api.wwdh.internetofwater.app/openapi) as the endpoint reference. Use this page when you want to understand which URL to call, which query parameters matter, and what kind of JSON to expect back. The examples below were checked against live WWDH metadata on June 4, 2026. Re-run the discovery requests before important work because collections and upstream source behavior can change. ## 1. Base URL and response formats The base URL is: ``` text https://api.wwdh.internetofwater.app ``` Most examples use `f=json` because WWDH is a pygeoapi service and serves collection metadata, GeoJSON, and CoverageJSON through JSON responses. ``` text GET https://api.wwdh.internetofwater.app/collections?f=json ``` You can often request a browser-readable HTML page with `f=html`: ``` text GET https://api.wwdh.internetofwater.app/collections?f=html ``` For command-line use, quote URLs that contain `?`, `&`, parentheses, or spaces: ``` sh curl -sS 'https://api.wwdh.internetofwater.app/collections?f=json' ``` Useful `f` values: | `f` value | Use | Common response | |---|---|---| | `json` | Programmatic access | JSON, GeoJSON, or CoverageJSON | | `html` | Browser inspection | HTML page generated by pygeoapi | | `csv` | Some feature/location endpoints | CSV table | | `jsonld` | Linked-data representation when advertised | JSON-LD | For EDR data queries, prefer `f=json`. The body will usually identify itself as either GeoJSON (`"type": "FeatureCollection"`) or CoverageJSON (`"type": "Coverage"` or `"type": "CoverageCollection"`). ## 2. Discovery first Start by asking what the service provides. ``` http GET /?f=json HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/json ``` Equivalent full URL: ``` text https://api.wwdh.internetofwater.app/?f=json ``` Then list collections: ``` http GET /collections?f=json HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/json ``` Equivalent `curl`: ``` sh curl -sS 'https://api.wwdh.internetofwater.app/collections?f=json' ``` The response has a top-level `collections` array. Each collection has an `id`, `title`, `extent`, `links`, and sometimes a `data_queries` object. The same document may also have a top-level `parameterGroups` array. Use `parameterGroups` when you want to translate a water-data concept across collections. For example, the `Lake/Reservoir Storage` group currently maps USBR RISE parameter `3` to USACE storage parameters such as `Flood Storage` and `Conservation Storage`. As of June 4, 2026, examples include: | Collection id | What it is | Advertised data queries | |---|---|---| | `rise-edr` | USBR RISE reservoir telemetry | `locations`, `cube`, `area`, `items` | | `snotel-edr` | USDA SNOTEL station data | `locations`, `cube`, `area`, `items` | | `awdb-forecasts-edr` | USDA AWDB forecasts | `locations`, `cube`, `area`, `items` | | `usace-edr` | USACE Access2Water API | `locations`, `cube`, `area`, `items` | | `usgs-prism` | PRISM monthly climate grids | `position`, `cube` | | `snotel-huc06-means` | HUC6 SWE summary features | Feature `/items`; no EDR data queries advertised | Inspect one collection before asking for data: ``` sh curl -sS 'https://api.wwdh.internetofwater.app/collections/snotel-edr?f=json' ``` Look for: - `parameter_names`: data variables you can request with `parameter-name`. - `parameterGroups`: cross-collection concept groups, when present. - `data_queries`: supported EDR query types for that collection. - `links`: HTML pages, JSON pages, `/items`, `/queryables`, and source documentation links. - `extent`: the rough spatial and temporal coverage. ## 3. Endpoint map These are the routes you will use most often. | Route | Purpose | Typical response | |---|---|---| | `/` | Landing page | JSON or HTML links | | `/conformance` | OGC conformance classes | JSON | | `/collections` | List collections | JSON collection list | | `/collections/{collectionId}` | Collection metadata | JSON collection document | | `/collections/{collectionId}/queryables` | Filterable feature properties | JSON Schema | | `/collections/{collectionId}/items` | Feature collection | GeoJSON, HTML, CSV | | `/collections/{collectionId}/items/{itemId}` | One feature | GeoJSON feature | | `/collections/{collectionId}/locations` | Station/location index | GeoJSON, HTML, CSV | | `/collections/{collectionId}/locations/{locId}` | Data for one known location | CoverageJSON | | `/collections/{collectionId}/position` | Data at one point | CoverageJSON | | `/collections/{collectionId}/cube` | Data inside a bounding box | CoverageJSON | | `/collections/{collectionId}/area` | Data inside a polygon | CoverageJSON | | `/collections/{collectionId}/radius` | Data within radius of a point | CoverageJSON when implemented | | `/collections/{collectionId}/trajectory` | Data along a line | CoverageJSON when implemented | | `/collections/{collectionId}/corridor` | Data along a line with width | CoverageJSON when implemented | Do not assume every collection supports every route. The collection document tells you what is advertised. A route that is valid for one collection may return 404 or 500 for another. ## 4. Common query parameters | Parameter | Used by | Meaning | Example | |---|---|---|---| | `f` | Almost all routes | Response format | `f=json` | | `bbox` | `locations`, `items`, `cube` | Bounding box as `minx,miny,maxx,maxy` | `bbox=-107,37,-105,40` | | `datetime` | EDR data queries, some feature queries | ISO-8601 instant or interval | `datetime=2024-02-01/2024-04-30` | | `parameter-name` | EDR data queries | Comma-separated data variable ids | `parameter-name=WTEQ` | | `coords` | `position`, `area`, `trajectory`, `corridor`, `radius` | WKT geometry | `coords=POINT(-112.4%2036.9)` | | `limit` | `locations`, `items`, some providers | Feature count limit | `limit=10` | | `crs` | Some EDR routes | Output coordinate reference system | Provider-specific URI | | `z` | 3D/profile-capable data | Vertical coordinate | `z=0` | | `within` | `radius` | Radius distance | `within=25` | | `within-units` | `radius` | Radius units | `within-units=km` | | `corridor-width` | `corridor` | Width around line | `corridor-width=10` | | `width-units` | `corridor` | Corridor width units | `width-units=km` | | `{queryable}` | `items` | Feature property filter advertised by `/queryables` | `provider=SPL` | Coordinates are longitude, latitude. A bbox is always: ``` text min_lon,min_lat,max_lon,max_lat ``` Multiple parameters are comma-separated: ``` text parameter-name=ppt,tmx ``` Some parameter ids contain spaces. Encode them in a hand-built URL: ``` text parameter-name=Flood%20Storage ``` or let `curl` encode them: ``` sh curl -sS -G 'https://api.wwdh.internetofwater.app/collections/usace-edr/locations/157145' \ --data-urlencode 'f=json' \ --data-urlencode 'datetime=2024-01-01/2024-12-31' \ --data-urlencode 'parameter-name=Flood Storage' ``` Intervals use a slash: ``` text datetime=2024-01-01/2024-03-31 ``` Open intervals may be supported by some providers: ``` text datetime=2024-01-01/.. ``` ## 5. URL encoding rules HTTP URLs cannot contain every character literally. Encode reserved characters in query values. For WKT point coordinates, encode the space between lon and lat as `%20`: ``` text coords=POINT(-112.4%2036.9) ``` A polygon must be URL-encoded if it contains spaces or parentheses. This readable WKT: ``` text POLYGON((-106 39,-105.8 39,-105.8 39.2,-106 39.2,-106 39)) ``` becomes a query value like: ``` text coords=POLYGON((-106%2039,-105.8%2039,-105.8%2039.2,-106%2039.2,-106%2039)) ``` Most HTTP clients can encode query parameters for you. If you build URLs by hand, be especially careful with spaces, `#`, `&`, `+`, and literal slashes inside path ids. ## 6. Finding parameters Collection metadata is where EDR data variables live. ``` sh curl -sS 'https://api.wwdh.internetofwater.app/collections/usgs-prism?f=json' ``` In the response, inspect `parameter_names`. Example `usgs-prism` parameter ids: | Parameter id | Meaning | Unit | |---|---|---| | `ppt` | Mean monthly precipitation | mm/month | | `tmn` | Minimum monthly temperature | deg C | | `tmx` | Maximum monthly temperature | deg C | Example `snotel-edr` parameter ids: | Parameter id | Meaning | Unit | |---|---|---| | `WTEQ` | Snow water equivalent | in | | `SNWD` | Snow depth | in | | `PREC` | Precipitation accumulation | in | | `TAVG` | Average air temperature | deg F | Example reservoir/stage parameter ids: | Collection | Parameter id | Meaning | Unit | |---|---|---|---| | `rise-edr` | `3` | Daily lake/reservoir storage | acre-ft | | `rise-edr` | `1830` | Lake/reservoir release - total | cfs | | `usace-edr` | `Flood Storage` | Flood storage | acre-ft | | `usace-edr` | `Conservation Storage` | Conservation storage | acre-ft | | `usace-edr` | `Outflow` | Outflow | cfs | | `resviz-edr` | `raw` | Daily lake/reservoir storage | provider-defined | Use the exact `parameter_names` keys in the URL. Labels are for humans; keys are for requests. For cross-collection work, use the top-level `parameterGroups` block from `/collections?f=json` to find conceptually equivalent parameters. For example: ``` sh curl -sS 'https://api.wwdh.internetofwater.app/collections?f=json' | jq '.parameterGroups[] | select(.name == "Lake/Reservoir Storage") | {name, members}' ``` Live response summary on June 4, 2026: ``` json { "name": "Lake/Reservoir Storage", "members": { "rise-edr": ["1470", "56", "51", "47", "3"], "usace-edr": [ "Flood Storage", "Conservation Storage", "Percent Flood Pool", "Percent Conservation Pool" ], "resviz-edr": ["avg", "p10", "p90", "raw"], "teacup-edr": ["avg", "p10", "p90", "raw"] } } ``` ## 7. Finding stations or locations Station-style collections advertise `locations`. Use a bbox first. ``` http GET /collections/snotel-edr/locations?f=json&bbox=-107,37,-105,40 HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/geo+json, application/json ``` Full URL: ``` text https://api.wwdh.internetofwater.app/collections/snotel-edr/locations?f=json&bbox=-107,37,-105,40 ``` Equivalent `curl`: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/snotel-edr/locations?f=json&bbox=-107,37,-105,40' ``` Expected response shape: ``` json { "type": "FeatureCollection", "features": [ { "type": "Feature", "id": "303", "geometry": { "type": "Point", "coordinates": [-105.0, 37.3] }, "properties": { "stationTriplet": "303:CO:SNTL", "name": "Apishapa", "stateCode": "CO", "networkCode": "SNTL" } } ] } ``` The exact fields vary by provider. For RISE reservoirs you may see properties such as `_id`, `locationName`, `timezone`, `elevation`, and `projectNames`. For SNOTEL you may see `stationTriplet`, `stationId`, `stateCode`, `networkCode`, `name`, and `huc`. ## 8. One known station: `/locations/{locId}` When you already know a provider's location id, request data through the location endpoint. This example asks RISE for Lake Mead daily storage for January 2023. ``` http GET /collections/rise-edr/locations/3514?f=json&datetime=2023-01-01/2023-01-31¶meter-name=3 HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/prs.coverage+json, application/json ``` Full URL: ``` text https://api.wwdh.internetofwater.app/collections/rise-edr/locations/3514?f=json&datetime=2023-01-01/2023-01-31¶meter-name=3 ``` Equivalent `curl`: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/rise-edr/locations/3514?f=json&datetime=2023-01-01/2023-01-31¶meter-name=3' ``` Expected response shape: ``` json { "type": "Coverage", "domain": { "domainType": "PointSeries", "axes": { "x": {"values": [-114.7]}, "y": {"values": [36.0]}, "t": {"values": ["2023-01-01T07:00:00Z"]} } }, "ranges": { "3": { "type": "NdArray", "axisNames": ["t"], "values": [25000000] } } } ``` CoverageJSON is compact and array-oriented. To make a table, pair the axis values in `domain.axes` with the values in each `ranges` parameter. ## 9. Many stations or grid cells: `/cube` Use `cube` for bbox-based bulk retrieval when the collection advertises it. This is usually the best route for multiple stations or a small grid. SNOTEL SWE example: ``` http GET /collections/snotel-edr/cube?f=json&bbox=-106.2,39.6,-105.8,40.0&datetime=2024-02-01/2024-04-30¶meter-name=WTEQ HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/prs.coverage+json, application/json ``` Full URL: ``` text https://api.wwdh.internetofwater.app/collections/snotel-edr/cube?f=json&bbox=-106.2,39.6,-105.8,40.0&datetime=2024-02-01/2024-04-30¶meter-name=WTEQ ``` PRISM grid example with two parameters: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/usgs-prism/cube?f=json&bbox=-112.6,36.7,-112.2,37.1&datetime=2023-01-01/2023-02-28¶meter-name=ppt,tmx' ``` Expected CoverageJSON shape: ``` json { "type": "CoverageCollection", "parameters": { "ppt": { "type": "Parameter", "description": {"en": "Mean monthly precipitation"} } }, "coverages": [ { "type": "Coverage", "domain": { "domainType": "Grid", "axes": { "x": {"values": [-112.56, -112.52]}, "y": {"values": [37.06, 37.02]}, "t": {"values": ["2023-01-01"]} } }, "ranges": { "ppt": { "axisNames": ["t", "y", "x"], "values": [116.0, 120.0] } } } ] } ``` Station collections may also return `CoverageCollection`, but each coverage is often a `PointSeries` rather than a `Grid`. ## 10. One point from a grid: `/position` PRISM advertises `position`, which is useful when you want the time series at one longitude/latitude rather than a full grid. ``` http GET /collections/usgs-prism/position?f=json&coords=POINT(-112.4%2036.9)&datetime=2023-01-01/2023-02-28¶meter-name=ppt HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/prs.coverage+json, application/json ``` Full URL: ``` text https://api.wwdh.internetofwater.app/collections/usgs-prism/position?f=json&coords=POINT(-112.4%2036.9)&datetime=2023-01-01/2023-02-28¶meter-name=ppt ``` Equivalent `curl`: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/usgs-prism/position?f=json&coords=POINT(-112.4%2036.9)&datetime=2023-01-01/2023-02-28¶meter-name=ppt' ``` Expected response: ``` json { "type": "Coverage", "domain": { "domainType": "PointSeries", "axes": { "x": {"values": [-112.4]}, "y": {"values": [36.9]}, "t": {"values": ["2023-01-01", "2023-02-01"]} } }, "ranges": { "ppt": { "axisNames": ["t"], "values": [116.0, 42.0] } } } ``` ## 11. Polygon queries: `/area` When a collection advertises `area`, send a WKT polygon in `coords`. Use this for a watershed, district, or management boundary after you have simplified it enough for a URL. Readable polygon: ``` text POLYGON((-106 39,-105.8 39,-105.8 39.2,-106 39.2,-106 39)) ``` Raw request shape: ``` http GET /collections/snotel-edr/area?f=json&coords=POLYGON((-106%2039,-105.8%2039,-105.8%2039.2,-106%2039.2,-106%2039))&datetime=2024-02-01/2024-04-30¶meter-name=WTEQ HTTP/1.1 Host: api.wwdh.internetofwater.app Accept: application/prs.coverage+json, application/json ``` For complex polygons, prefer an HTTP client that builds and encodes query parameters for you. Long URLs can hit browser, proxy, or server limits. ## 12. Feature layers: `/queryables` and `/items` Collections without EDR `data_queries` are often feature layers. Use `queryables` to inspect attributes and `items` to retrieve features. EDR collections may also expose `/items`; in that case, treat `/items` as the feature catalog you use to discover stations, reservoirs, dams, and other locations before making a data query. Queryables example: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/snotel-huc06-means/queryables?f=json' ``` Expected response shape: ``` json { "type": "object", "properties": { "geometry": {"$ref": "https://geojson.org/schema/Geometry.json"}, "name": {"type": "string"}, "geoconnex_url": {"type": "string"}, "id": {"type": "string"}, "basin_index": {"type": "number"} } } ``` Items example: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/snotel-huc06-means/items?f=json&limit=3' ``` Expected response shape: ``` json { "type": "FeatureCollection", "features": [ { "type": "Feature", "id": "090400", "geometry": {"type": "MultiPolygon"}, "properties": { "name": "Upper South Saskatchewan River", "basin_index": 75.4, "current_snow_water_equivalent_relative_to_thirty_year_avg": 75.4, "latest_full_day_of_data": "06-03" } } ] } ``` Feature/catalog layers are not time-series sampling endpoints. Treat them as GIS feature downloads with attributes. ### Filtering `/items` with queryables The property names advertised by `/queryables` can usually be sent as ordinary query parameters on `/items`. Combine them with `bbox` and `limit` to find a manageable set of features. RISE example: find lake/reservoir features in a Lower Colorado / Arizona bbox. ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/rise-edr/items?f=json&bbox=-115,33,-111,35&locationTypeName=Lake%2FReservoir&limit=20' ``` Verified response summary on June 4, 2026: ``` json { "type": "FeatureCollection", "count": 7, "sample": [ { "id": 3515, "locationName": "Lake Havasu Parker Dam and Powerplant", "locationTypeName": "Lake/Reservoir", "coords": [-114.1385, 34.2964] } ] } ``` USACE example: find South Pacific Division features in the same bbox. ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/usace-edr/items?f=json&bbox=-115,33,-111,35&provider=SPL&limit=5' ``` Verified response summary on June 4, 2026: ``` json { "type": "FeatureCollection", "count": 4, "sample": [ { "id": 157145, "name": "Alamo Dam", "code": "Alamo", "state": "AZ", "provider": "SPL", "coords": [-113.6017, 34.23167] } ] } ``` Provider behavior can vary. In the RISE example above, `limit=5` with the same bbox and property filter returned no lake/reservoir features, while `limit=20` returned seven. When using a queryable property filter for discovery, start with a large enough `limit`, inspect the returned features, and then narrow the request. ## 13. Cross-provider storage workflow This workflow shows a complete verified pattern: 1. Find equivalent storage parameters. 2. Find a bbox that has both USBR RISE and USACE features. 3. Ask each provider for all available 2024 storage observations. The shared bbox used here is a small area containing one matching RISE feature and one matching USACE feature: ``` text -114.3,34.1,-113.5,34.4 ``` It contains USBR RISE lake/reservoir features such as Lake Havasu Parker Dam and Powerplant (`3515`) and USACE features such as Alamo Dam (`157145`). ### Step 1: choose equivalent parameters From `parameterGroups`, `Lake/Reservoir Storage` includes: | Collection | Parameter to request | Notes | |---|---|---| | `rise-edr` | `3` | Daily lake/reservoir storage, acre-ft | | `usace-edr` | `Flood Storage` | Flood storage, acre-ft | | `usace-edr` | `Conservation Storage` | Conservation storage, acre-ft; not every location has data | For the verified USACE 2024 example below, `Flood Storage` has data in the selected bbox. `Conservation Storage` returned HTTP 204 No Content for the tested Hoover and Alamo examples on June 4, 2026. ### Step 2: request USBR RISE storage in the bbox for 2024 Ask for all matching RISE storage series in the bbox with `cube`: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/rise-edr/cube?f=json&bbox=-114.3,34.1,-113.5,34.4&datetime=2024-01-01/2024-12-31¶meter-name=3' ``` Verified response summary: ``` json { "type": "CoverageCollection", "parameterKeys": ["3"], "coverageCount": 1, "sample": [ { "x": -114.1385, "y": 34.2964, "t_count": 365, "t_first": "2024-01-01T07:00:00+00:00", "t_last": "2024-12-30T07:00:00+00:00", "value_count": 365, "first_values": [578564.0, 579452.0, 579225.0] } ] } ``` This narrow bbox returned one matching RISE storage series. If a broad bbox fails or is too slow, discover candidate locations with `/items` first and use `/locations/{locId}` for one location at a time. ### Step 3: request USACE storage in the bbox for 2024 Ask USACE for all matching `Flood Storage` series in the same bbox: ``` sh curl -sS \ 'https://api.wwdh.internetofwater.app/collections/usace-edr/cube?f=json&bbox=-114.3,34.1,-113.5,34.4&datetime=2024-01-01/2024-12-31¶meter-name=Flood%20Storage' ``` Verified response summary: ``` json { "type": "CoverageCollection", "parameterKeys": ["Flood Storage"], "coverageCount": 1, "sample": [ { "x": -113.6017, "y": 34.23167, "t_count": 8300, "t_first": "2024-01-01T00:00:00+00:00", "t_last": "2024-12-31T00:00:00+00:00", "value_count": 8300, "first_values": [136286.17, 136286.17, 136286.17] } ] } ``` USACE observations in this response are not daily; they are the available observations returned by Access2Water for the 2024 interval. The practical pattern is: ``` text /collections?f=json -> parameterGroups for concept mapping /collections/{id}/queryables?f=json -> feature property names /collections/{id}/items?f=json&bbox=...&{queryable}=... -> candidate location ids /collections/{id}/locations/{locId}?f=json&datetime=2024-01-01/2024-12-31¶meter-name=... -> full 2024 series for one location /collections/{id}/cube?f=json&bbox=...&datetime=2024-01-01/2024-12-31¶meter-name=... -> all matching series in a bbox, when the provider can satisfy it ``` ## 14. Response types in practice You will usually see one of these JSON shapes. GeoJSON feature collection: ``` json { "type": "FeatureCollection", "features": [] } ``` GeoJSON single feature: ``` json { "type": "Feature", "geometry": {}, "properties": {} } ``` CoverageJSON single coverage: ``` json { "type": "Coverage", "domain": { "domainType": "PointSeries", "axes": {} }, "ranges": {} } ``` CoverageJSON collection: ``` json { "type": "CoverageCollection", "parameters": {}, "coverages": [] } ``` A simple tabular interpretation of CoverageJSON is: ``` text coverage id + parameter id + datetime + x + y + z + value ``` The hard part is axis ordering. `ranges.{parameter}.axisNames` tells you the order of dimensions for the flat `values` array. ## 15. A language-agnostic workflow Use this sequence in any tool: 1. `GET /collections?f=json` 2. Pick `collection.id`. 3. `GET /collections/{id}?f=json` 4. If `parameter_names` exists, choose exact parameter keys. 5. If `data_queries.locations` exists, inspect `/collections/{id}/locations?f=json&bbox=...`. 6. If `data_queries.cube` exists, retrieve data with `/collections/{id}/cube?f=json&bbox=...&datetime=...¶meter-name=...`. 7. If you need to discover feature ids or filter a feature catalog, use `/collections/{id}/queryables?f=json` and `/collections/{id}/items?f=json&{queryable}=...`. 8. Parse GeoJSON as features or CoverageJSON as axis/range arrays. 9. Expand the spatial or temporal scope only after the small request works. ## 16. Troubleshooting raw requests | Symptom | Likely cause | Fix | |---|---|---| | 404 on `/cube`, `/area`, or `/position` | Collection does not advertise that route | Re-check `/collections/{id}?f=json` | | 400 on a WKT request | `coords` is not URL-encoded or WKT is invalid | Encode spaces as `%20`; close polygon rings | | 204 with an empty body | The request is valid, but no data matched the location, time, or parameter | Try another parameter from `parameterGroups`, another location, or a shorter date range | | 500 on a broad request | Upstream provider or wrapper could not satisfy the query | Reduce bbox, time range, and parameter count | | Empty `features` | No matching features, or filter combination is too narrow | Try HTML page, known active bbox, or fewer filters | | `NoApplicableCode` query error on `/items` | Provider could not apply that feature-property filter | Try a different queryable, use only `bbox` and `limit`, or inspect the HTML view | | No `parameter_names` | It may be a feature layer | Use `/queryables` and `/items` | | Unexpected content type | Server returns GeoJSON/CoverageJSON under JSON | Inspect the body `type` field | | Shell error before request is sent | URL was not quoted | Wrap URL in single quotes | Keep requests small while exploring. A good first request has one bbox, one parameter, and a short date range. Once it succeeds, widen only one dimension at a time.