Base path: /api/v1.
This is the supported public API contract for the current alpha. The API is cache-backed: data comes from public IMGW-PIB sources fetched server-side, normalized by MeteoLens, and returned with attribution, retrieval timestamps, missing-field metadata, and processed-data notices.
/api/v1is the stable alpha surface. Additive response fields and additive optional query parameters may appear inv1.- Removing fields, changing field meaning, changing default filter behavior, or
changing export column names requires a new API version or an explicit
migration note in
CHANGELOG.md. - Clients should ignore unknown JSON fields and should not treat collection ordering as stable unless an endpoint documents it.
- Error bodies use FastAPI's
{"detail": {"error": ...}}envelope for application errors. GET /openapi.jsonis the machine-readable source of truth. The lightweight TypeScript client metadata inpackages/meteolens-api-client/src/generated.tsis generated from this OpenAPI schema withpython scripts/api/generate_ts_client.py.
- Route categories are deliberately small and deployment-visible: public (read-only health/data/map/export/product-metadata routes), expensive (product rendering), and administrative (archive backfill).
- Production nginx limits public API traffic to 60 requests/minute/IP (burst 30) and product renders to 10 requests/minute/IP (burst 2).
- Public users should call MeteoLens, not IMGW archive/product files directly. Product rendering has a configurable one-render default concurrency bound and coalesces simultaneous identical requests. Archive import is single-concurrent and suppresses recently completed duplicate date ranges.
- MeteoLens local alerts, dashboards, and warning/station comparisons are not official IMGW-PIB warnings and must keep the disclaimer visible in UI and downstream integrations.
All data responses should include source metadata:
{
"source": {
"provider": "IMGW-PIB",
"source_key": "synop",
"url": "https://danepubliczne.imgw.pl/api/data/synop",
"retrieved_at": "2026-06-29T21:10:00Z",
"attribution": "Źródło danych: IMGW-PIB.",
"processed_notice": "Dane IMGW-PIB zostały przetworzone przez MeteoLens."
}
}Common object fields:
id: stable MeteoLens ID.source_id: source-provided ID.observed_at: measurement timestamp if applicable.published_at: warning publication timestamp if applicable.retrieved_at: backend fetch timestamp.data_delay_seconds: computed where possible.missing_fields: source fields absent or explicitlynull.raw_available: whether expert raw JSON can be requested.
Collection responses include:
generated_at: response generation timestamp.cache: per-source cache status with freshness, record count, parser warnings, and error metadata.empty_state: present when no normalized cached records are available or no records match a narrow filter.
When normalized cache is empty, collection endpoints return an explicit
empty_state instead of mock data. Detail endpoints return 503 with
cache_empty if no relevant cache exists, or 404 with not_found when cache
exists but the requested object is absent.
GET /health
Backward-compatible liveness endpoint. GET /health/live has the same
response and is the explicit liveness probe.
{
"status": "ok",
"service": "meteolens-backend",
"version": "0.1.0-alpha"
}GET /health/ready
Checks completed startup, SQLite access, and write access to /data. It returns
200 with status: "ready" or "degraded"; degraded IMGW cache never makes
the cached application unavailable. It returns 503 with "not_ready" only
when a core dependency cannot serve data. The checks object exposes safe
status codes for startup, database, data, and sources.
GET /metrics
Prometheus/OpenMetrics endpoint for the private Compose network. It is disabled
unless METEOLENS_METRICS_ENABLED=true, excluded from OpenAPI, and deliberately
not proxied by the public nginx service.
GET /api/v1/sources
Returns supported source descriptors, cache status, and parser status.
Public refresh endpoints are not exposed. Cache refresh remains an internal
backend concern so public API consumers cannot mutate cache state; deployments
can enable startup refresh with METEOLENS_SYNC_ON_STARTUP=true.
GET /api/v1/map/layers
Query parameters:
layers: comma-separated layer keys.bbox: optionalminLon,minLat,maxLon,maxLat.time: optional ISO timestamp for time-aware layers.expert: optional boolean for extra metadata.
Implemented layer keys:
synop_stationshydro_stationsmeteo_stationswarnings_meteowarnings_hydro
Returns GeoJSON FeatureCollections grouped by layer. Hydro and meteo stations
are point features when coordinates exist. Synop records are emitted as point
features from the reviewed Stage 18 synop_stations WMO OSCAR/Surface dataset;
future station IDs not present in that dataset are listed in missing_geometry
with missing_lat_lon. Warning areas are emitted as polygon features when
their TERYT/basin codes resolve against reviewed geometry datasets (Stage 13
ships PRG voivodeship and county polygons; Stage 22 ships II aPGW-derived
hydro_basins). Unresolved codes stay visible in records and
missing_geometry with geometry_not_found (dataset loaded, code unmatched)
or missing_area_geometry_dataset (required dataset not installed).
{
"generated_at": "2026-06-30T07:30:00Z",
"cache": [],
"empty_state": null,
"layers": [
{
"key": "hydro_stations",
"title": "Stacje hydrologiczne",
"source_keys": ["hydro"],
"sources": [],
"geojson": {
"type": "FeatureCollection",
"features": []
},
"records": [],
"missing_geometry": []
}
]
}GET /api/v1/stations
Query parameters:
type:synop,hydro,meteo.q: text search.bbox: optional bounding box.limit: default 200.
Returns:
{
"generated_at": "2026-06-30T07:30:00Z",
"cache": [],
"empty_state": null,
"stations": [
{
"id": "hydro:151140030",
"source_id": "151140030",
"source_key": "hydro",
"station_type": "hydro",
"name": "Przewoźniki",
"lat": 51.5253,
"lon": 14.8217,
"coordinate_source": null,
"latest_observed_at": "2026-06-30T07:00:00+02:00",
"data_delay_seconds": 1800,
"missing_fields": ["temperatura_wody"],
"source": {},
"raw_available": true
}
]
}coordinate_source names the reviewed geometry dataset attribution when a
synop station's coordinates were filled from the synop_stations dataset
(IMGW's synop API publishes none); it is null when coordinates come directly
from the IMGW payload or are missing.
GET /api/v1/stations/{id}
Returns station metadata, latest observations, source metadata, and raw metadata
availability. IDs use the normalized stable form, for example
synop:12295, hydro:151140030, or meteo:252210290.
GET /api/v1/stations/{id}/observations
Query parameters:
metric: optional metric key.from: optional ISO timestamp.to: optional ISO timestamp.interval: aggregation interval such asraw,10m,1h, or1d.limit: maximum number of returned points.
Returns observation values for charts and exports. The implementation reads
persisted observation history when available and falls back to the latest cache
snapshot when history is empty. Responses include series_kind (history or
snapshot), series_origin (live_refresh, archive_import, or mixed),
origin_counts, and the requested interval. If the current station cache is
empty but archive history exists for the requested stable station ID, this
endpoint may return archive history with source metadata pointing at the archive
directory; map/list station discovery still depends on current cache data and
reviewed geometry.
mixed means both origins exist under the same normalized station ID. Daily
SYNOP archive rows may use a current synop:<id_stacji> only when their source
NSP has a mapped entry in the reviewed versioned IMGW mapping artifact.
Unmapped rows use synop-archive:<NSP> and never contribute to a current
station's mixed series.
Each observation preserves null values and includes missing,
raw_field, observed_at, retrieved_at, data_delay_seconds, and
unit metadata where available. Historical observations may also include
origin, import_run_id, import_source_url, source_station_id (the
original archive NSP, or the source id_stacji for persisted live history),
station_mapping_status, station_mapping_version,
station_mapping_source_url, station_mapping_retrieved_at, archive_kind,
quality_status, missing_reason, temporal_resolution,
source_file_sha256, and source_file_last_modified. Mapping status is
mapped, unmapped_not_current_synop, or
unmapped_not_in_mapping_source; the mapping-specific fields are null for
live-only points. CODZ points use temporal_resolution="1d" and midnight UTC
only as a calendar-day marker, not a measurement hour.
POST /api/v1/archive/backfill/synop-daily
POST /api/v1/archive/backfill/hydro-daily
Administrative route. It is disabled unless METEOLENS_ADMIN_TOKEN is set.
When enabled, clients must send the matching value in the
X-MeteoLens-Admin-Token header. Missing configuration returns 403; missing
or invalid credentials return 401 with WWW-Authenticate: MeteoLensAdmin.
This deployment-local token is not an end-user account system.
Query parameters:
from: required date (YYYY-MM-DD), inclusive.to: required date (YYYY-MM-DD), inclusive.
The first route imports reviewed daily SYNOP archives. The second imports only
the verified IMGW daily hydrological CODZ family: water level, flow, and
water temperature. CODZ discovery converts the requested calendar dates into
hydrological years (November and December belong to the next year), accepts
codz_RRRR.zip and codz_RRRR_WW.zip, and fails explicitly when no matching
file is published. ZJAW, monthly, semi-annual, and annual summary families
are not accepted.
Both routes write into the existing observation-history schema and are bounded by
METEOLENS_ARCHIVE_BACKFILL_MAX_DAYS and
METEOLENS_ARCHIVE_BACKFILL_MAX_FILES, wait
METEOLENS_ARCHIVE_BACKFILL_RATE_LIMIT_SECONDS between files, and never asks
the browser to fetch IMGW archive files directly. Download bytes, ZIP entries,
expanded entry/total size, and CSV rows also have hard configured limits.
Duplicate records are handled
by upsert on station_id + metric + observed_at + origin; repeated runs refresh
archive-import metadata without creating duplicate archive observations, while
an equal-time live observation remains a separate point. Import fails if the reviewed
mapping artifact cannot be loaded or validated. An unmapped NSP does not fail
the whole bounded run: it is retained under synop-archive:<NSP> and reported
in parser_warnings.
CODZ identity is exact hydro:<PSKDSZS>; station/river names are never mapping
keys. Each source file is parsed completely before one atomic synchronization
updates corrected values and removes source-withdrawn rows for that file's
selected date slice. Identical source duplicates are collapsed and counted;
conflicting duplicates fail the file. A parse or persistence error performs no
withdrawal deletion.
Only one archive import may run per backend process. A successfully completed
date range enters the configured duplicate cooldown; repeating it during that
window returns 429 with Retry-After.
Response shape:
{
"id": "uuid",
"source_key": "synop",
"archive_kind": "synop_daily",
"status": "completed",
"started_at": "2026-07-05T12:00:00+00:00",
"finished_at": "2026-07-05T12:00:02+00:00",
"observed_from": "2026-05-01",
"observed_to": "2026-05-07",
"files_total": 1,
"files_processed": 1,
"rows_seen": 62,
"observations_seen": 620,
"observations_inserted": 620,
"observations_updated": 0,
"observations_unchanged": 0,
"observations_deleted": 0,
"duplicate_rows": 0,
"parser_warnings": [],
"errors": [],
"attribution": "Źródło danych: IMGW-PIB.",
"processed_notice": "Dane IMGW-PIB zostały przetworzone przez MeteoLens."
}Errors use the standard error envelope with codes such as
archive_range_too_large, archive_file_limit_exceeded,
archive_download_too_large, archive_zip_invalid, archive_zip_too_many_entries,
archive_zip_central_directory_too_large, archive_zip_entry_too_large, archive_zip_uncompressed_too_large,
archive_row_limit_exceeded, invalid_time_range, or
archive_backfill_failed. CODZ also returns archive_files_not_found,
archive_row_invalid, archive_zip_missing_csv, or
archive_conflicting_duplicate where applicable.
GET /api/v1/archive/backfill/runs
Administrative route with optional exact filters source_key, archive_kind,
and status, plus limit (1-100). It returns newest runs first, including
current counters and statuses running, completed,
completed_with_warnings, failed, or interrupted.
GET /api/v1/archive/backfill/runs/{id}
Administrative route returning the run plus each source file's URL,
hydrological year, status, start/finish time, SHA-256, source
Last-Modified, row/observation counters, duplicate count, warnings and
errors. Runs and running files left after process restart become
interrupted; retrying the same range creates a new idempotent run.
METEOLENS_OBSERVATION_RETENTION_DAYS prunes only origin=live_refresh.
Archive history has no automatic expiry. Operators can count or remove a
selected kind/date range with:
python -m app.operations.archive_history prune \
--archive-kind hydro_daily --from 2024-01-01 --to 2024-01-31The command is dry-run unless --confirm is present. A verified backup is
required before confirmed cleanup.
GET /api/v1/stations/compare
GET /api/v1/rankings
GET /api/v1/export/station/{id}/observations.csv
GET /api/v1/export/station/{id}/observations.json
Station comparison parameters:
station_ids: comma-separated stable station IDs.metric: required metric key.from: optional ISO timestamp.to: optional ISO timestamp.interval: optional aggregation interval.limit: optional point limit.
Ranking parameters:
metric: one of supported ranking metrics, for example temperature, wind speed, precipitation, or water level.direction:highestorlowestwhere applicable.from: optional ISO timestamp.to: optional ISO timestamp.station_type: optional station type filter.limit: optional result limit.
Ranking responses preserve source metadata, missing-field metadata, processed- Ranking logic omits missing values and does not replace them with zero. Comparisons and rankings accept stable station IDs present only in persisted history. Archive-only stations remain available through these APIs and exports without being placed on the map unless reviewed coordinates exist.
GET /api/v1/warnings
Query parameters:
type:meteo,hydro.active_at: optional ISO timestamp.level: optional warning level.phenomenon: optional text/enum filter.teryt: optional administrative area code.basin: optional hydrological basin code.province: two-digit TERYT voivodeship filter; resolves against warning area codes and reviewed geometry metadata.county: four-digit TERYT county filter.
GET /api/v1/geometry/datasets
Returns reviewed geometry dataset status from the local data/geometry/ cache.
Since Stage 13 each dataset entry also exposes the review metadata recorded at
import time: provider, canonical_url, license_url, attribution,
public_use, commercial_use, redistribution_note, update_cadence,
known_limitations, dataset_version, review_status, and reviewed_at,
next to loaded, feature_count, and error. Datasets without an approved
review are never loaded and report a dataset_not_reviewed error; datasets
failing validation report invalid_dataset.
GET /api/v1/warnings/{id}
Returns warning detail, affected areas, geometry references, source metadata, and raw JSON availability.
Both current-warning endpoints retain their existing fields and add:
history_id: stable local history identifier when the current warning has a persisted identity,history_available: whether retained history detail can be opened,history_started_at: first local observation time for that history.
These fields do not claim that history exists before the local deployment started recording successful refreshes.
Warnings expose area_codes from IMGW TERYT/basin/province metadata. When
reviewed geometry datasets are cached under METEOLENS_GEOMETRY_DIR, map layers
and warning detail responses include resolved polygon GeoJSON plus
unresolved_areas for codes that cannot be mapped.
Resolved basin areas may include mapping_precision
(standard / refined / coarse / coastal) and optional mapping_method
from the reviewed hydro_basins feature properties. The same fields are copied
onto warning map-layer and export GeoJSON feature properties when present.
Non-standard precision values mark approximate IMGW forecasting-area
mappings, not official IMGW warning polygons.
Stage 9 added reviewed geometry references or GeoJSON features for warning areas where code mapping is reliable. Responses continue to expose unresolved codes and missing geometry reasons instead of hiding partial data.
GET /api/v1/warning-events
Returns a prospective, newest-first feed ordered by detected_at DESC and then
stable event_id DESC. Supported filters are:
type: exactmeteoorhydro,level: exact normalized warning level,area: exact source area code,change_kind: exact event category,fromandto: inclusive ISO timestamps applied todetected_at,phenomenonandoffice: case-insensitive text filters,limit: 1-200, default 100,cursor: opaque continuation token returned asnext_cursor.
Events expose change_kinds, changed_fields, detected_at, effective_at,
classification_basis, confidence, source metadata, identity completeness,
the retained normalized/raw version, missing fields, and
history_started_at. Snapshot metadata uses an opaque stable snapshot_id;
SQLite row numbers are not part of the public contract. Supported categories
are first_observed, created,
appeared_in_source, updated, extended, escalated, downgraded,
expired, removed_from_source, reappeared, cancelled, correction, and
duplicate_conflict. Categories that require an explicit source signal are
not inferred from free text.
GET /api/v1/warning-histories/{history_id}
Returns the exact local identity, identity status, lifecycle status, all
deduplicated versions, and the chronological event timeline. It remains
available after a warning disappears from the current cache. A missing
history_id returns 404. Pruning never reassigns a deleted public history ID.
If conflicting source records prevent selection of a current version,
current_version_id remains null; consumers must present the conflict rather
than choose one version as representative.
Both responses include IMGW-PIB attribution, the MeteoLens processed-data
notice, the official-warning disclaimer, and an explicit prospective-history
boundary. Empty filtered feeds return the standard empty_state. Partial
snapshots and ambiguous identities remain visible; fetch/parser errors and
404 source responses do not manufacture empty snapshots.
GET /api/v1/location/summary
Query parameters:
lat: required.lon: required.radius_km: optional, default 50.
Returns nearest stations, latest observations, and active warnings relevant to the location. Station matching uses distance from cached point coordinates. Warnings are returned as active cached warning records, with a note that exact location matching is not available until area geometry datasets are cached.
The response includes generated_at, cache, and empty_state metadata like
other collection endpoints.
Stage 9 added spatial warning matching for this endpoint when reviewed
TERYT or basin geometries exist. The response distinguishes exact polygon
matches (match_type: "polygon"), fallback active-warning summaries, and
unresolved geometry via notes.
GET /api/v1/export/station/{id}.csv
GET /api/v1/export/station/{id}.json
GET /api/v1/export/station/{id}/observations.csv
GET /api/v1/export/station/{id}/observations.json
GET /api/v1/export/map.geojson
GET /api/v1/export/warnings.geojson
GET /api/v1/export/warning-events.csv
GET /api/v1/export/warning-events.json
GET /api/v1/export/map-state.json
Export query parameters mirror the related station, observations, warning, and map filters. Every export includes attribution, processed-data notice when relevant, generated timestamp, retrieval timestamp where applicable, and missing-field or missing-geometry metadata.
Warning-event exports accept the same type, level, area, change_kind,
from, to, phenomenon, and office filters as the feed. Their bounded
export limit is 1-5000, default 1000. They include uncertain and ambiguous
events rather than silently omitting them. change_kind uses the same closed
category enumeration as the paginated feed and invalid values return 422.
JSON retains the structured event
payload; CSV includes stable event/history ids, change categories, changed
fields, classification basis, confidence, source identity, affected area
codes, history_started_at, attribution, processed notice, and disclaimer.
Station CSV columns:
station_idstation_namemetricvalueunitobserved_atretrieved_atdata_delay_secondsmissingraw_fieldsource_keyattributionprocessed_noticemissing_fields
Station observation range exports support:
metricfromtointerval:raw,10m,1h, or1dlimit: maximum 5000
Observation CSV columns:
station_idstation_namemetricvalueunitobserved_atretrieved_atdata_delay_secondsmissingraw_fieldoriginimport_run_idimport_source_urlsource_station_idstation_mapping_statusstation_mapping_versionstation_mapping_source_urlstation_mapping_retrieved_atarchive_kindquality_statusmissing_reasontemporal_resolutionsource_file_sha256source_file_last_modifiedsource_keyattributionprocessed_noticeseries_kindinterval
Map GeoJSON includes point station features plus foreign members for
non_spatial_records, missing_geometry, cache, attribution,
geometry_attributions, processed_notice, and generated_at.
geometry_attributions lists reviewed geometry dataset attribution strings
used by exported features, for example PRG/GUGiK attribution for warning
polygons or reviewed station-coordinate sources.
Warning GeoJSON supports the same warning filters as /api/v1/warnings, plus
bbox. It returns polygon features when reviewed geometry exists and keeps
warnings with unresolved geometry in non_spatial_records and
missing_geometry; absence of polygons is not treated as absence of warnings.
Map state JSON records the visible layer keys, optional map center/zoom/bbox, mode, theme, current selection, warning filters, timeline selection, cache state, and per-layer feature/record/missing-geometry counts. It is intended for automation, troubleshooting, and reproducible power-user views, not as a replacement for GeoJSON data exports.
Report-like PDF exports are not implemented. The optional future plan is in
docs/power-user/PDF_EXPORT_PLAN.md.
No raw expert-data endpoint is currently supported. Raw source snippets are
included inside station and warning detail payloads where feasible. A future
/api/v1/raw/... endpoint may be added only if it preserves attribution,
missing-field metadata, and clear cache provenance.
Stage 10 exposed product classification and frame metadata; Stage 14 added the
first real rendering path (COSMO *_00 2 m temperature as a PNG map overlay).
Radar composites stay metadata-only (rendering_status: download_blocked)
because IMGW does not currently serve their files publicly.
Returns IMGW product manifest entries enriched with research classification:
category,availability,rendering_status,high_value,format_notesrendering_statusvalues includerenderable(COSMO*_00),parser_not_implemented,download_blocked(radar composites),unsupported_format,unavailableresearch_date(currently2026-07-05)missing_fields(source fields IMGW omitted, e.g.id/url/opis)- per-product
sourcemetadata and attribution/processed notice at collection level retrieved_atisnullwhen the product manifest cache is empty (never synthesized)
Query parameters: limit (1-500, default 120), offset (default 0).
Returns cached product detail manifest slices with parsed frame metadata:
frame_time,run_time(model run for GRIB products),frame_kind(forecast_lead,observation,preview,metadata,constant),missing,rendering_status- aggregate
frame_count,missing_frames,stale,retrieved_at renderable— descriptor object for renderable products, otherwisenull:variables(key/title/unit/legend),default_variable,bounds(west/south/east/north),image_coordinates(MapLibre TL/TR/BR/BL corners),render_url_template,max_lead_hours,lead_step_hours,grid_note,attribution,processed_notice- per-frame render state on renderable products:
renderable(bool),renderable_reason(constant_field_file,not_a_forecast_frame,lead_beyond_render_window,lead_not_on_render_step), and — for renderable frames —render_urlandrender_ready(PNG already cached) empty_state.codemay becache_empty,product_unavailable, orframe_missing
Serves the rendered PNG overlay for one renderable frame (image/png). The
first request downloads the source GRIB server-side (can take seconds to tens
of seconds; downloads are serialized), then the cached PNG is served.
Public deployment note: this endpoint is expensive. Production nginx applies a route-specific rate limit, while the backend bounds concurrent renders and coalesces identical in-flight work so anonymous traffic cannot multiply large downloads or CPU-heavy renders.
- Response headers:
X-MeteoLens-Frame-Time,X-MeteoLens-Run-Time,X-MeteoLens-Retrieved-At,X-MeteoLens-Rendered-At,X-MeteoLens-Variable - The PNG embeds attribution, the processed-data notice, and timing metadata
as iTXt chunks; a JSON metadata sidecar backs
render_ready - Errors (
detail.error.code):not_renderable(404),frame_not_renderable(404),cache_empty(503),frame_missing(404 — also used when IMGW returns an HTML page instead of a GRIB file),download_blocked(502),download_failed(502),file_too_large(502),grid_mismatch(502 — the file stopped matching the reviewed COSMO grid; rendering is refused rather than drawn at a wrong position),variable_missing(502)
Returns time-aware layers derived from cached product detail manifests. Each layer includes:
first_frame_time,last_frame_time,source_timeframes_renderable—trueonly when frames actually render as a map layerrenderable— same descriptor as on the frames endpoint (ornull)stale,missing_frames, attribution, processed notice, and explanatorynotes
Tile pyramids are not implemented. A future contract may add:
GET /api/v1/tiles/{product_id}/{z}/{x}/{y}
Product and frame responses must label source time, frame time, missing frames,
stale frames, parser/rendering status, attribution, and processed-data notice.
Stable, unstable, missing, or risky product IDs must be visible in source
metadata. See docs/products/PRODUCT_RESEARCH.md.
Stage 11 added operational dashboards and comparison helpers. Saved locations, views, dashboards, and local alert rules remain browser-local unless a future authenticated backend is introduced.
Returns aggregate cache freshness for all configured IMGW sources:
overall_status:healthy,stale,degraded, orempty- per-source
cache_status,age_seconds,ttl_seconds,stale, parser warnings alerting_disclaimerclarifying MeteoLens is not an official alerting system
Compares cached station observations with active warnings matched to the station
coordinates (when available). Includes notes, attribution, processed notice, and
the same alerting disclaimer.
Local alert evaluation in the UI uses live API data plus browser-stored rules; it does not call a separate alerting endpoint.
See also:
The Stage 16 TypeScript client lives in
packages/meteolens-api-client/. It provides typed helpers for common
integration workflows:
- list stations,
- fetch station observations,
- build station range export URLs,
- check source freshness,
- fetch active warnings for a location,
- build warning GeoJSON export URLs.
The generated OpenAPI metadata file is committed so docs and tests can detect drift from backend routes. Regenerate it after API changes:
backend/.venv/bin/python scripts/api/generate_ts_client.pyRunnable Node examples live under examples/api/ and use
METEOLENS_API_BASE_URL to target local or deployed instances.
Future authenticated deployments may add server-side persistence for saved views and alert delivery audit logs. Local alert endpoints must state that MeteoLens is not an official alerting system and must not obscure IMGW-PIB warning responsibility.
{
"error": {
"code": "source_unavailable",
"message": "IMGW-PIB source could not be fetched.",
"source_key": "hydro",
"retrieved_at": "2026-06-29T21:10:00Z",
"retry_after_seconds": 300
}
}Planned error codes:
source_unavailable,source_timeout,parser_failed,cache_empty,cache_invalid,not_found,unsupported_layer,invalid_filter.geometry_unavailable,product_unavailable,frame_missing,alert_rule_invalid.
Empty-state codes for collection responses:
no_matching_records,no_observations,no_location_data.