{"openapi":"3.1.0","info":{"title":"KOSAVA v7 OpenData","description":"Read-only public data portal for environmental measurement data. All data is served from a pre-computed, immutable Redis snapshot. One portal instance is pinned to a single organization via the KEY_PREFIX environment variable. No writes are accepted.\n\n**Supported languages:** `sr-Latn`, `sr-Cyrl`, `en`\n\n**Supported measurement windows:** `1h`, `1d`, `7d`, `14d`, `30d`\n\n**Export formats:** `csv`, `xlsx`, `ods`","contact":{"name":"KOSAVA OpenData"},"license":{"name":"Public Data Portal"},"version":"1.2.0"},"paths":{"/":{"get":{"tags":["portal"],"summary":"Main portal page","description":"Returns the server-rendered HTML portal page. All display state (selected station, component, window, language) is driven by query parameters; no session or cookies are used.\n\n**language** — display language. Accepted values: `sr-Latn`, `sr-Cyrl`, `en`. Defaults to the value of the DEFAULT_LANGUAGE environment variable.\n\n**station_id** — pre-selects a station and opens the detail panel.\n\n**component_id** — pre-selects a measurement component within the station panel.\n\n**window** — pre-selects a time window for chart rendering. One of: `1h`, `1d`, `7d`, `14d`, `30d`. Defaults to `1d`.\n\nInvalid or unknown parameter values are silently ignored and replaced with portal defaults. This endpoint always returns 200.","operationId":"portal_root__get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Display language. One of: `sr-Latn`, `sr-Cyrl`, `en`.","title":"Language"},"description":"Display language. One of: `sr-Latn`, `sr-Cyrl`, `en`."},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pre-select a station by ID.","title":"Station Id"},"description":"Pre-select a station by ID."},{"name":"component_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pre-select a measurement component by ID.","title":"Component Id"},"description":"Pre-select a measurement component by ID."},{"name":"window","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pre-select a time window. One of: `1h`, `1d`, `7d`, `14d`, `30d`.","title":"Window"},"description":"Pre-select a time window. One of: `1h`, `1d`, `7d`, `14d`, `30d`."}],"responses":{"200":{"description":"Full server-rendered portal HTML page.","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/portal/station-modal":{"get":{"tags":["portal"],"summary":"Station detail modal fragment","description":"Returns an HTML fragment containing the station detail modal content. This endpoint is called via AJAX from the portal frontend when a station is selected; it renders the same server-side context pipeline as `GET /` but returns only the `partials/station_modal_content.html` template fragment rather than the full page.\n\nAccepts the same query parameters as the root portal page: `language`, `station_id`, `component_id`, and `window`. If `station_id` is absent or invalid the fragment renders in an empty/closed state. This endpoint always returns 200.","operationId":"portal_station_modal_content_portal_station_modal_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Display language. One of: `sr-Latn`, `sr-Cyrl`, `en`.","title":"Language"},"description":"Display language. One of: `sr-Latn`, `sr-Cyrl`, `en`."},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Station ID to render detail for.","title":"Station Id"},"description":"Station ID to render detail for."},{"name":"component_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pre-select a measurement component by ID.","title":"Component Id"},"description":"Pre-select a measurement component by ID."},{"name":"window","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pre-select a time window. One of: `1h`, `1d`, `7d`, `14d`, `30d`.","title":"Window"},"description":"Pre-select a time window. One of: `1h`, `1d`, `7d`, `14d`, `30d`."}],"responses":{"200":{"description":"Server-rendered HTML fragment for the station detail modal.","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api-docs":{"get":{"tags":["portal"],"summary":"API documentation page","description":"Returns the human-readable, interactive API documentation page for this portal. Documents every endpoint with parameter tables, response examples, and multi-language code samples (curl, Python, JavaScript). Accepts optional `language` and `theme` query parameters to match the portal's display preferences.","operationId":"api_docs_page_api_docs_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Display language. One of: `sr-Latn`, `sr-Cyrl`, `en`.","title":"Language"},"description":"Display language. One of: `sr-Latn`, `sr-Cyrl`, `en`."},{"name":"theme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"UI theme. One of: `light`, `dark`.","title":"Theme"},"description":"UI theme. One of: `light`, `dark`."}],"responses":{"200":{"description":"Full server-rendered API documentation HTML page.","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/meta":{"get":{"tags":["metadata"],"summary":"Snapshot manifest","description":"Returns the manifest of the currently active Redis snapshot. The manifest contains the snapshot generation timestamp, the list of supported measurement windows (`1h`, `1d`, `7d`, `14d`, `30d`), and aggregate counts for organizations, networks, stations, components, and measurement rows.","operationId":"get_meta_meta_get","responses":{"200":{"description":"Active snapshot manifest.","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Meta Meta Get"},"example":{"schema_version":"1.2.0","generated_at":"2024-01-01T12:00:00Z","supported_windows":["1h","1d","7d","14d","30d"],"counts":{"organizations":1,"networks":3,"stations":12,"components":48,"measurement_rows":172800}}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/organizations":{"get":{"tags":["metadata"],"summary":"List all organizations","description":"Returns the list of all organizations in the active snapshot. Because one portal instance is pinned to a single organization via the KEY_PREFIX environment variable, this list will typically contain exactly one entry. Each object includes `organization_id`, `name`, `short_name`, and optional contact or description fields stored in the snapshot.","operationId":"get_organizations_organizations_get","responses":{"200":{"description":"Array of organization objects.","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Organizations Organizations Get"},"example":[{"organization_id":1,"name":"Environmental Protection Agency","short_name":"EPA"}]}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/networks":{"get":{"tags":["metadata"],"summary":"List all monitoring networks","description":"Returns all monitoring networks defined in the active snapshot. Networks group stations under a named measurement programme or geographic area. Each object includes `network_id`, `network_code`, `name`, and `short_name`.","operationId":"get_networks_networks_get","responses":{"200":{"description":"Array of network objects.","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Networks Networks Get"},"example":[{"network_id":10,"network_code":"AQ-CITY","name":"City Air Quality Network","short_name":"AQ-CITY"}]}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/stations":{"get":{"tags":["metadata"],"summary":"List all stations","description":"Returns all public monitoring stations across all organizations and networks in the active snapshot. Each object includes `station_id`, `station_name`, `station_code`, `organization_id`, `network_id`, `network_code`, and geographic fields such as `city`, `municipality`, and coordinates where available. Use `/{organization_id}/stations` to narrow results to a single organization.","operationId":"get_stations_stations_get","responses":{"200":{"description":"Array of station objects.","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Stations Stations Get"},"example":[{"station_id":101,"station_name":"Central Station","station_code":"CTR-01","organization_id":1,"network_id":10,"network_code":"AQ-CITY","city":"Belgrade"}]}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/components":{"get":{"tags":["metadata"],"summary":"List all measurement components","description":"Returns all measurement components (pollutants and meteorological parameters) defined in the active snapshot. Each object includes `component_id`, `short_name`, and `unit`. Components marked as public are exposed through per-station measurement endpoints. Meteorological components include wind speed, temperature, humidity, and precipitation; pollutant components include particulate matter and gaseous pollutants.","operationId":"get_components_components_get","responses":{"200":{"description":"Array of component objects.","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Get Components Components Get"},"example":[{"component_id":1001,"short_name":"PM10","unit":"ug/m3"},{"component_id":10054,"short_name":"T","unit":"degC"}]}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/{organization_id}/stations":{"get":{"tags":["metadata"],"summary":"List stations for an organization","description":"Returns all public monitoring stations that belong to the specified organization. The response shape is identical to `GET /stations` but filtered to the given `organization_id`. Returns 404 if the organization does not exist or has no public stations in the active snapshot.","operationId":"get_organization_stations__organization_id__stations_get","parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"integer","title":"Organization Id"}}],"responses":{"200":{"description":"Array of station objects for the requested organization.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Organization Stations  Organization Id  Stations Get"},"example":[{"station_id":101,"station_name":"Central Station","station_code":"CTR-01","organization_id":1,"network_id":10,"network_code":"AQ-CITY","city":"Belgrade"}]}}},"404":{"description":"No public data exists for the requested organization or station.","content":{"application/json":{"example":{"detail":"No public data found for the requested resource."}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/{organization_id}/stations/{station_id}/meta":{"get":{"tags":["metadata"],"summary":"Station metadata and public components","description":"Returns detailed metadata for a single station, including the list of public measurement components (`public_components`) available for that station. Each component entry in `public_components` includes `component_id`, `short_name`, and `unit`. This endpoint is the starting point for discovering which components can be queried via the measurements endpoints. Returns 404 if the organization or station does not exist in the active snapshot.","operationId":"get_station_meta__organization_id__stations__station_id__meta_get","parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"integer","title":"Organization Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}}],"responses":{"200":{"description":"Station metadata object with embedded public components.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Station Meta  Organization Id  Stations  Station Id  Meta Get"},"example":{"station_id":101,"station_name":"Central Station","station_code":"CTR-01","organization_id":1,"network_id":10,"network_code":"AQ-CITY","city":"Belgrade","public_components":[{"component_id":1001,"short_name":"PM10","unit":"ug/m3"},{"component_id":10054,"short_name":"T","unit":"degC"}]}}}},"404":{"description":"No public data exists for the requested organization or station.","content":{"application/json":{"example":{"detail":"No public data found for the requested resource."}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/{organization_id}/stations/{station_id}/measurements/last_hour":{"get":{"tags":["measurements"],"summary":"Last-hour measurements for a station","description":"Returns all component measurements recorded in the most recent hour for the specified station. The payload contains a `hours` array where each entry has a `date` (ISO-8601 date string), `time` (HH:MM), and a `components` list. Each component entry includes `component_id` and `value` (numeric). Returns 404 if the station does not exist or no last-hour data is available in the active snapshot.","operationId":"get_station_last_hour__organization_id__stations__station_id__measurements_last_hour_get","parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"integer","title":"Organization Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}}],"responses":{"200":{"description":"Last-hour measurement payload for the station.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Station Last Hour  Organization Id  Stations  Station Id  Measurements Last Hour Get"},"example":{"hours":[{"date":"2024-01-01","time":"11:00","components":[{"component_id":1001,"value":42.5},{"component_id":10054,"value":7.3}]}]}}}},"404":{"description":"The organization, station, or component does not exist in the active snapshot, or no measurement data is available for the requested combination.","content":{"application/json":{"example":{"detail":"No public data found for the requested resource."}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/{organization_id}/stations/{station_id}/measurements/last_24h":{"get":{"tags":["measurements"],"summary":"Last-24-hour measurements for a station","description":"Returns all component measurements recorded across the last 24 hours for the specified station. The payload structure is identical to the `last_hour` endpoint: a `hours` array where each entry has `date`, `time`, and `components`. All components that are publicly exposed for this station are included in each hour entry where data exists. Returns 404 if the station does not exist or no last-24h data is available.","operationId":"get_station_last_24h__organization_id__stations__station_id__measurements_last_24h_get","parameters":[{"name":"organization_id","in":"path","required":true,"schema":{"type":"integer","title":"Organization Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}}],"responses":{"200":{"description":"Last-24-hour measurement payload for the station.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Station Last 24H  Organization Id  Stations  Station Id  Measurements Last 24H Get"},"example":{"hours":[{"date":"2023-12-31","time":"13:00","components":[{"component_id":1001,"value":38.0},{"component_id":10054,"value":6.8}]},{"date":"2024-01-01","time":"11:00","components":[{"component_id":1001,"value":42.5},{"component_id":10054,"value":7.3}]}]}}}},"404":{"description":"The organization, station, or component does not exist in the active snapshot, or no measurement data is available for the requested combination.","content":{"application/json":{"example":{"detail":"No public data found for the requested resource."}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/measurements":{"get":{"tags":["measurements"],"summary":"Time-series measurements for a station component","description":"Returns normalized time-series measurement data for a single component at a single station over the requested time window. All four query parameters are required.\n\n**window** must be one of: `1h`, `1d`, `7d`, `14d`, `30d`.\n\n- `1h` reads from the station's last-hour snapshot key.\n- `1d` reads from the station's last-24h snapshot key.\n- `7d`, `14d`, `30d` aggregate daily snapshot keys anchored to the snapshot generation timestamp.\n\nThe response includes station name, component short name, unit, window used, and a `points` array sorted ascending by `date` + `time`. Each point has `date` (YYYY-MM-DD), `time` (HH:MM), and numeric `value`.\n\nReturns 400 if any parameter is missing, blank, not an integer (for IDs), or if `window` is not one of the supported values or is not present in the active snapshot manifest. Returns 404 if the station or component is not found or has no data for the window.","operationId":"get_measurements_measurements_get","parameters":[{"name":"organization_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Organization ID (integer).","title":"Organization Id"},"description":"Organization ID (integer)."},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Station ID (integer).","title":"Station Id"},"description":"Station ID (integer)."},{"name":"component_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Component ID (integer).","title":"Component Id"},"description":"Component ID (integer)."},{"name":"window","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Measurement window. One of: `1h`, `1d`, `7d`, `14d`, `30d`.","title":"Window"},"description":"Measurement window. One of: `1h`, `1d`, `7d`, `14d`, `30d`."}],"responses":{"200":{"description":"Normalized time-series payload for the component.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Measurements Measurements Get"},"example":{"organization_id":1,"station_id":101,"station_name":"Central Station","component_id":1001,"component_short_name":"PM10","unit":"ug/m3","window":"1d","points":[{"date":"2023-12-31","time":"13:00","value":38.0},{"date":"2024-01-01","time":"11:00","value":42.5}]}}}},"400":{"description":"One or more required query parameters are missing, blank, or not a valid integer.","content":{"application/json":{"example":{"detail":"Invalid request parameters."}}}},"404":{"description":"The organization, station, or component does not exist in the active snapshot, or no measurement data is available for the requested combination.","content":{"application/json":{"example":{"detail":"No public data found for the requested resource."}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/portal/export":{"get":{"tags":["portal-export"],"summary":"Download measurement data as a file","description":"Builds and streams a downloadable spreadsheet file containing time-series measurement data for a single component at a single station. All five query parameters are required.\n\n**window** must be one of: `1d`, `7d`, `14d`, `30d` (the 1h window is not supported for export).\n\n**format** must be one of: `csv`, `xlsx`, `ods`.\n\nThe exported file contains one row per measurement point with columns: `organization_id`, `organization_name`, `station_id`, `station_name`, `station_code`, `network_id`, `network_code`, `date`, `time`, `component_id`, `component_short_name`, `unit`, `value`. Numeric values are formatted to two decimal places. The filename follows the pattern `{prefix}_{organization_id}_{station_id}_{component_id}_{window}.{format}`.\n\nReturns 400 if any parameter is missing, blank, not an integer (for IDs), or if `window` or `format` is not one of the accepted values. Returns 404 if the station or component is not found or has no data. Returns 503 if the snapshot is not available.","operationId":"portal_export_portal_export_get","parameters":[{"name":"organization_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Organization ID (integer).","title":"Organization Id"},"description":"Organization ID (integer)."},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Station ID (integer).","title":"Station Id"},"description":"Station ID (integer)."},{"name":"component_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Component ID (integer).","title":"Component Id"},"description":"Component ID (integer)."},{"name":"window","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Measurement window. One of: `1d`, `7d`, `14d`, `30d`.","title":"Window"},"description":"Measurement window. One of: `1d`, `7d`, `14d`, `30d`."},{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"File format. One of: `csv`, `xlsx`, `ods`.","title":"Format"},"description":"File format. One of: `csv`, `xlsx`, `ods`."}],"responses":{"200":{"description":"File download. Content-Type depends on format: `text/csv; charset=utf-8` for csv, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` for xlsx, `application/vnd.oasis.opendocument.spreadsheet` for ods.","content":{"application/json":{"schema":{}},"text/csv":{"example":"organization_id,organization_name,station_id,station_name,station_code,network_id,network_code,date,time,component_id,component_short_name,unit,value\r\n1,EPA,101,Central Station,CTR-01,10,AQ-CITY,2024-01-01,11:00,1001,PM10,ug/m3,42.50\r\n"}}},"400":{"description":"One or more required query parameters are missing, blank, not a valid integer, or `window` / `format` is not an accepted value.","content":{"application/json":{"example":{"detail":"Invalid request parameters."}}}},"404":{"description":"The station or component does not exist in the active snapshot, or no measurement data is available for the requested window.","content":{"application/json":{"example":{"detail":"No public data found for the requested resource."}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, or the snapshot schema version is incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health/live":{"get":{"tags":["health"],"summary":"Process liveness check","description":"Confirms the process is alive and the HTTP server is accepting requests. This endpoint performs no I/O and always returns 200 OK while the process is running. Intended for container liveness probes.","operationId":"health_live_health_live_get","responses":{"200":{"description":"Process is alive.","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Live Health Live Get"},"example":{"status":"ok","check":"live"}}}}}}},"/health/ready":{"get":{"tags":["health"],"summary":"Snapshot readiness check","description":"Validates that the Redis connection is healthy and that the active snapshot schema version matches the value configured in EXPECTED_SCHEMA_VERSION. Returns 200 with the current `snapshot_id` when ready. Returns 503 when Redis is unreachable, the active snapshot pointer is missing, or the schema version is incompatible. Intended for container readiness probes and load-balancer health gates.\n\nPass `?deep=1` to additionally verify that the HVD bulk bundle can be built and that all bundle resources have non-zero size. A 503 is returned if the bundle build fails or any resource is empty, with `bulk_status: \"error\"` and a `detail` field in the response body.","operationId":"health_ready_health_ready_get","parameters":[{"name":"deep","in":"query","required":false,"schema":{"type":"boolean","description":"Also verify the HVD bulk bundle is buildable.","default":false,"title":"Deep"},"description":"Also verify the HVD bulk bundle is buildable."}],"responses":{"200":{"description":"Redis is reachable and the active snapshot is compatible.","content":{"application/json":{"schema":{},"example":{"status":"ok","check":"ready","snapshot_id":"snap_20240101_120000","bulk_status":"ok"}}}},"503":{"description":"Redis is unreachable, the active snapshot pointer is absent, the snapshot schema version does not match EXPECTED_SCHEMA_VERSION, or (when deep=1) the HVD bulk bundle failed to build.","content":{"application/json":{"example":{"status":"error","check":"ready","detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/metadata":{"get":{"tags":["hvd"],"summary":"HVD dataset metadata","description":"Returns the full HVD dataset descriptor for this portal instance. Includes schema and dataset versions, retention policy, declared data status, supported windows, license placeholder, links to legal pages, and pointers to API documentation. This endpoint is the machine-readable counterpart of the human license/terms/QoS pages and is suitable for catalog harvesters.","operationId":"get_hvd_metadata_api_v1_metadata_get","responses":{"200":{"description":"HVD dataset metadata document.","content":{"application/json":{"schema":{},"example":{"snapshot_schema_version":"1.2.0","hvd_schema_version":"1.0","schema_version":"1.2.0","dataset_version":"1.0","snapshot_id":"20260403121000","generated_at_utc":"2026-04-03T12:10:00Z","retention_days":30,"data_status":"preliminary","aggregation_type":"hourly_mean","averaging_period":"1h","supported_windows":["1h","1d","7d","14d","30d"],"applicable_legislation":"http://data.europa.eu/eli/reg_impl/2023/138/oj","license":{"name":"Otvoreni podaci po Zakonu o e-upravi (CC BY-equivalent)","url":"/legal/license"}}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/api/v1/stations":{"get":{"tags":["hvd"],"summary":"HVD stations","description":"Returns the list of monitoring stations in HVD shape. Each station includes `station_id`, `station_name`, geographic coordinates, `municipality`, `station_type`, `operator`, `active`, and `last_updated_utc`. Optional filters: `active`, `municipality`, `station_type`, `bbox`. This is HVD Component A from the Standard.","operationId":"get_hvd_stations_api_v1_stations_get","parameters":[{"name":"active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If set, return only active stations (`true`) or inactive (`false`).","title":"Active"},"description":"If set, return only active stations (`true`) or inactive (`false`)."},{"name":"municipality","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Case-insensitive exact match on municipality name.","title":"Municipality"},"description":"Case-insensitive exact match on municipality name."},{"name":"station_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter on station type. One of: `traffic`, `urban`, `background`, `industrial`, `rural`, `other`.","title":"Station Type"},"description":"Filter on station type. One of: `traffic`, `urban`, `background`, `industrial`, `rural`, `other`."},{"name":"bbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bounding box `min_lon,min_lat,max_lon,max_lat` (WGS84). Returns stations inside the box.","title":"Bbox"},"description":"Bounding box `min_lon,min_lat,max_lon,max_lat` (WGS84). Returns stations inside the box."}],"responses":{"200":{"description":"Array of HVD station records.","content":{"application/json":{"schema":{},"example":[{"station_id":"1","station_name":"Kikinda Centar","station_code":"RS1002A","latitude":45.821483,"longitude":20.454008,"municipality":"Kikinda","operator":"Nacionalna mreza za kvalitet vazduha","active":true,"last_updated_utc":"2026-04-03T12:10:00Z","network_id":1,"network_code":"RS100A"}]}}},"400":{"description":"Invalid `bbox` parameter format.","content":{"application/json":{"example":{"detail":"Invalid bbox format. Expected min_lon,min_lat,max_lon,max_lat."}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/parameters":{"get":{"tags":["hvd"],"summary":"HVD parameter dictionary","description":"Returns the controlled vocabulary of measurement parameters. Each entry includes `parameter_code` (canonical short identifier such as `PM10`, `NO2`, `O3`), `parameter_name`, `unit`, and the fixed `averaging_period` of `1h`. This is HVD Component B from the Standard.","operationId":"get_hvd_parameters_api_v1_parameters_get","responses":{"200":{"description":"Array of HVD parameter records.","content":{"application/json":{"schema":{},"example":[{"parameter_code":"PM2.5","parameter_name":"Particulate matter <= 2.5 um","unit":"ug.m-3","averaging_period":"1h"}]}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/api/v1/observations/stream":{"get":{"tags":["hvd"],"summary":"HVD hourly observations — NDJSON stream","description":"Streams HVD hourly preliminary observations as **newline-delimited JSON** (NDJSON, `application/x-ndjson`).  Each line is a complete JSON object followed by `\\n`.\n\n**Line 1** is always a `{\"meta\": {...}}` block that describes the snapshot context and the effective time window.  Every subsequent line is an individual observation record with the same fields as the `/api/v1/observations` JSON response.\n\n**Motivation:** the full observations dataset is ~105 k records / ~33 MB. The non-streaming endpoint serialises everything in memory before sending the first byte (~13 s wall time, blocks the entire worker). This endpoint starts emitting data within milliseconds and never buffers the full dataset.\n\n**Record ordering:** records are emitted in MGET insertion order — **not** sorted by `(station_id, parameter_code, time_start_utc)`. Sort client-side if required.\n\n**Filters and parameters** are identical to `/api/v1/observations`. Use `station_id` and/or `parameter_code` to narrow the stream.\n\n**ETag:** based on `snapshot_id`; identical to the non-streaming endpoint ETag so proxy caches stay consistent across both endpoints.","operationId":"stream_hvd_observations_api_v1_observations_stream_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at - retention_days`.","title":"From"},"description":"Start of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at - retention_days`."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at`.","title":"To"},"description":"End of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at`."},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter on a single station. Accepts the HVD `station_id` string (matches `str(internal_station_id)`).","title":"Station Id"},"description":"Filter on a single station. Accepts the HVD `station_id` string (matches `str(internal_station_id)`)."},{"name":"parameter_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter on a single parameter code (e.g. `PM10`, `PM2.5`, `NO2`).","title":"Parameter Code"},"description":"Filter on a single parameter code (e.g. `PM10`, `PM2.5`, `NO2`)."}],"responses":{"200":{"description":"NDJSON stream.  First line is a `{\"meta\": {...}}` block; subsequent lines are observation records.  Empty result: only the meta line is emitted with `meta.out_of_retention_window: true`.","content":{"application/x-ndjson":{"example":"{\"meta\": {\"snapshot_id\": \"20260403121000\", \"generated_at_utc\": \"2026-04-03T12:10:00Z\", \"retention_days\": 30, \"data_status\": \"preliminary\", \"aggregation_type\": \"hourly_mean\", \"requested_window\": {\"from\": null, \"to\": null}, \"actual_window\": {\"from\": \"2026-04-03T12:10:00Z\", \"to\": \"2026-04-03T12:10:00Z\"}, \"out_of_retention_window\": false, \"streaming\": true, \"record_order\": \"mget_insertion_order\"}}\n{\"station_id\": \"51\", \"parameter_code\": \"PM10\", \"time_start_utc\": \"2026-04-03T03:00:00Z\", \"time_end_utc\": \"2026-04-03T04:00:00Z\", \"value\": 12.5, \"unit\": \"ug.m-3\", \"data_status\": \"preliminary\", \"aggregation_type\": \"hourly_mean\", \"published_at_utc\": \"2026-04-03T12:10:00Z\", \"updated_at_utc\": \"2026-04-03T12:10:00Z\", \"coverage\": null}\n"}},"headers":{"Content-Disposition":{"description":"Suggested filename for download clients.","schema":{"type":"string"},"example":"inline; filename=\"observations.ndjson\""},"ETag":{"description":"Snapshot-id-based cache token.","schema":{"type":"string"}},"Cache-Control":{"description":"Cache directive.","schema":{"type":"string"}}}},"400":{"description":"Invalid query parameter format.","content":{"application/json":{"example":{"detail":"Invalid `from` parameter. Expected ISO 8601 datetime."}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/observations":{"get":{"tags":["hvd"],"summary":"HVD hourly preliminary observations","description":"Returns hourly-averaged measurement records in HVD shape for the requested time window. Each record includes `station_id`, `parameter_code`, `time_start_utc`, `time_end_utc`, `value`, `unit`, `data_status` (always `preliminary`), `aggregation_type` (always `hourly_mean`), `published_at_utc`, `updated_at_utc`, and `coverage` (always `null` in v1.0).\n\n**Retention:** the dataset is rolling 30 days. The window is automatically clipped to `[generated_at - retention_days, generated_at]`. The `meta` block reports both the requested and the actual window. If the clipped window is empty, the response carries `data: []` and `meta.out_of_retention_window: true`.\n\n**Filters:** `station_id` and `parameter_code` are optional. Without them, the endpoint returns all stations and all parameters in the window. `from` and `to` accept ISO 8601 datetimes with or without timezone (missing TZ is treated as UTC). If `from`/`to` are omitted, the full retention window is returned. This is HVD Component C from the Standard.","operationId":"get_hvd_observations_api_v1_observations_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at - retention_days`.","title":"From"},"description":"Start of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at - retention_days`."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at`.","title":"To"},"description":"End of the requested window, ISO 8601 datetime. Missing TZ is treated as UTC. If omitted, defaults to `generated_at`."},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter on a single station. Accepts the HVD `station_id` string (matches `str(internal_station_id)`).","title":"Station Id"},"description":"Filter on a single station. Accepts the HVD `station_id` string (matches `str(internal_station_id)`)."},{"name":"parameter_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter on a single parameter code (e.g. `PM10`, `PM2.5`, `NO2`).","title":"Parameter Code"},"description":"Filter on a single parameter code (e.g. `PM10`, `PM2.5`, `NO2`)."}],"responses":{"200":{"description":"HVD observation records and window metadata.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Hvd Observations Api V1 Observations Get"},"example":{"data":[{"station_id":"51","parameter_code":"NO","time_start_utc":"2026-04-03T03:00:00Z","time_end_utc":"2026-04-03T04:00:00Z","value":0.46592,"unit":"ug.m-3","data_status":"preliminary","aggregation_type":"hourly_mean","published_at_utc":"2026-04-03T12:10:00Z","updated_at_utc":"2026-04-03T12:10:00Z"}],"meta":{"snapshot_id":"20260403121000","generated_at_utc":"2026-04-03T12:10:00Z","retention_days":30,"data_status":"preliminary","aggregation_type":"hourly_mean","requested_window":{"from":"2026-04-01T00:00:00Z","to":"2026-04-04T00:00:00Z"},"actual_window":{"from":"2026-04-01T00:00:00Z","to":"2026-04-03T12:10:00Z"},"out_of_retention_window":false,"count":1}}}}},"400":{"description":"Invalid query parameter format.","content":{"application/json":{"example":{"detail":"Invalid `from` parameter. Expected ISO 8601 datetime."}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bulk":{"get":{"tags":["hvd"],"summary":"HVD bulk download index","description":"Returns the index of bulk download resources for the active snapshot. Each entry includes resource name, content type, size, SHA256 checksum, and a download URL. The bundle covers the rolling 30-day retention window in machine-readable formats. This is HVD Sekcija 6 from the Standard.","operationId":"get_hvd_bulk_index_api_v1_bulk_get","responses":{"200":{"description":"Bulk download index for the active snapshot.","content":{"application/json":{"schema":{},"example":{"snapshot_id":"20260403121000","generated_at_utc":"2026-04-03T12:10:00Z","resources":[{"name":"stations.csv","format":"csv","content_type":"text/csv; charset=utf-8","size_bytes":1234,"sha256":"0123abc...","download_url":"/api/v1/bulk/stations.csv"}]}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/api/v1/bulk/{filename}":{"get":{"tags":["hvd"],"summary":"Download a single HVD bulk resource","description":"Streams one of the bulk resources (CSV, README, or checksums) as a file download. The exact content matches the SHA256 checksum advertised in `GET /api/v1/bulk`.","operationId":"get_hvd_bulk_resource_api_v1_bulk__filename__get","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Bulk resource file content with attachment Content-Disposition.","content":{"application/json":{"schema":{}}}},"404":{"description":"Bulk resource not found.","content":{"application/json":{"example":{"detail":"Bulk resource not found."}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dcat":{"get":{"tags":["hvd"],"summary":"DCAT-AP HVD catalog (JSON-LD)","description":"Returns the machine-readable dataset catalog in DCAT-AP HVD JSON-LD format. The document describes:\n\n- a `dcat:Catalog` rooted at this URL,\n- three `dcat:Dataset` resources for stations, parameters, and hourly preliminary observations,\n- one `dcat:DataService` for the public REST API,\n- one `dcat:Distribution` per format and per dataset (CSV, GeoJSON, JSON, Parquet, plus the API itself),\n- `dcatap:applicableLegislation` linking to ELI 2023/138,\n- `dcatap:hvdCategory` set to Earth observation and environment.\n\nConforms to DCAT-AP HVD profile 2.2.0 and is suitable for harvesting by EU and national open-data portals.","operationId":"get_hvd_dcat_api_v1_dcat_get","responses":{"200":{"description":"DCAT-AP HVD catalog as JSON-LD.","content":{"application/json":{"schema":{}},"application/ld+json":{"example":{"@context":{"dcat":"http://www.w3.org/ns/dcat#"},"@graph":[{"@id":"https://example.com/api/v1/dcat","@type":"dcat:Catalog"}]}}}},"503":{"description":"Active snapshot is unavailable or schema-incompatible.","content":{"application/json":{"example":{"detail":"Active snapshot is not available or incompatible."}}}}}}},"/.well-known/dcat-catalog.jsonld":{"get":{"tags":["hvd"],"summary":"DCAT-AP HVD catalog (well-known alias)","description":"Permanent redirect (308) to `/api/v1/dcat` following the .well-known URI convention (RFC 8615) for catalog discovery. EU SEMIC harvesters discover catalogs primarily through this well-known location. The redirect is permanent so that harvesters can cache the target URL.","operationId":"dcat_well_known__well_known_dcat_catalog_jsonld_get","responses":{"307":{"description":"Successful Response"},"308":{"description":"Permanent redirect to /api/v1/dcat.","headers":{"Location":{"description":"The canonical DCAT catalog URL.","schema":{"type":"string"}}}}}}},"/api/v1/data-dictionary":{"get":{"tags":["hvd"],"summary":"HVD data dictionary","description":"Returns the structured data dictionary defined by HVD Sekcija 11. Each of the three components (stations, parameters, observations) is described with field name, type, required flag, constant value (if any), cross-reference, and a multilingual definition. Also lists `forbidden_fields` per HVD Sekcija 5.3.2 — fields that must NOT appear in any distribution to avoid implying regulatory validation. Use the `language` query parameter to select the definition locale.","operationId":"get_hvd_data_dictionary_api_v1_data_dictionary_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Language for definitions. One of: `sr-Latn`, `sr-Cyrl`, `en`. Defaults to `sr-Latn`.","title":"Language"},"description":"Language for definitions. One of: `sr-Latn`, `sr-Cyrl`, `en`. Defaults to `sr-Latn`."}],"responses":{"200":{"description":"Structured data dictionary for all three components.","content":{"application/json":{"schema":{},"example":{"language":"en","supported_languages":["sr-Latn","sr-Cyrl","en"],"standard_reference":"Standard za High-Value Dataset (HVD) OpenData SEPA, Sekcija 11","forbidden_fields":["validated","qa_flag","compliance","exceedance"],"components":[{"name":"observations","title":"Hourly preliminary observations (HVD Component C)","description":"...","standard_section":"5.3","fields":[{"name":"data_status","type":"string","required":true,"constant":"preliminary","definition":"..."}]}]}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/legal/license":{"get":{"tags":["legal"],"summary":"Open data license","description":"Returns the open data license page describing the licensing terms for this dataset. By default, the dataset is published under the open data license established by the Serbian E-Government Act (Zakon o elektronskoj upravi, clan 26), which is functionally equivalent to Creative Commons Attribution (CC BY): free reuse and modification with attribution.","operationId":"legal_license_legal_license_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},{"name":"theme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/legal/terms":{"get":{"tags":["legal"],"summary":"Terms of use","description":"Returns the terms of use page covering the open data license, preliminary data status disclaimer, 30-day rolling retention policy, regulatory use disclaimer, and contact pointer. Required by HVD Standard Sekcija 8.2.","operationId":"legal_terms_legal_terms_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},{"name":"theme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/legal/qos":{"get":{"tags":["legal"],"summary":"Quality of service","description":"Returns the quality-of-service page declaring target availability, rate limits, planned maintenance windows, and expected publication latency. Required by HVD Standard Sekcija 8.3 and EU 2023/138.","operationId":"legal_qos_legal_qos_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},{"name":"theme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/legal/contact":{"get":{"tags":["legal"],"summary":"Dataset contact","description":"Returns the contact information for this dataset. Required by HVD Standard Sekcija 7.1.","operationId":"legal_contact_legal_contact_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},{"name":"theme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/legal/dataset":{"get":{"tags":["legal"],"summary":"Dataset description","description":"Returns the human-readable HVD dataset description page including the dataset title, summary, retention policy, and links to all distributions (API, bulk). Required by HVD Standard Sekcija 9.2.","operationId":"legal_dataset_legal_dataset_get","parameters":[{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},{"name":"theme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}