1. Overview
The WIS2 Downloader exposes a REST API for managing subscriptions and monitoring the system.
-
Base URL:
http://localhost:5002 -
OpenAPI Spec:
http://localhost:5002/openapi -
Swagger UI:
http://localhost:5002/swagger
Replace localhost:5002 with your server’s address if deployed remotely. The base URL is configured via WIS2DOWNLOADER_SUBSCRIPTION_MANAGER_URL in .env.
|
2. Authentication
The API does not require authentication. In production, place it behind a reverse proxy with authentication (see the Access Control section of the Admin Guide).
3. Subscriptions API
Each subscription is identified by a UUID and binds together an MQTT topic, a save path, an optional filter, optional credentials, and a queue. Multiple subscriptions can share the same topic — the MQTT connection is opened once and messages are routed to all matching subscriptions.
3.1. List Subscriptions
Returns all active subscriptions grouped by topic.
GET /subscriptions
3.1.1. Response
| Status | Description |
|---|---|
200 |
Success — map of topic → map of subscription UUID → subscription detail |
503 |
Redis unavailable |
3.1.2. Example
curl http://localhost:5002/subscriptions
{
"cache/a/wis2/+/data/core/weather/surface-based-observations/#": {
"550e8400-e29b-41d4-a716-446655440000": {
"save_path": "surface-obs",
"filter": {}
},
"661f9511-f30c-52e5-b827-557766551111": {
"save_path": "surface-obs-bufr",
"filter": {
"name": "bufr-only",
"rules": [
{ "id": "accept-bufr", "order": 1, "match": { "media_type": { "equals": "application/bufr" } }, "action": "accept" }
]
}
}
}
}
3.2. Create Subscription
Creates a new subscription. Assigns a UUID and returns the full subscription record.
If this is the first subscription for the given topic, an MQTT connection is opened. Additional subscriptions for the same topic reuse the existing connection.
POST /subscriptions
Content-Type: application/json
3.2.1. Request Body
| Field | Type | Required | Description |
|---|---|---|---|
|
string |
Yes |
WIS2 MQTT topic pattern. Supports |
|
string |
No |
Subdirectory under the data root where files are saved. |
|
object |
No |
Rule-based filter. See Filter Schema. |
|
object |
No |
HTTP credentials for access-controlled datasets. See Credentials Schema. |
|
string |
No |
Download queue: |
3.2.2. Response
| Status | Description |
|---|---|
201 |
Created — returns the full subscription record |
400 |
Bad request — missing or invalid fields |
503 |
Service unavailable — Redis connection failed |
3.2.3. Response Headers
| Header | Description |
|---|---|
|
URL to retrieve the created subscription ( |
3.2.4. Examples
# Simple subscription
curl -X POST http://localhost:5002/subscriptions \
-H "Content-Type: application/json" \
-d '{
"topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
"target": "surface-obs"
}'
# Subscription with a filter
curl -X POST http://localhost:5002/subscriptions \
-H "Content-Type: application/json" \
-d '{
"topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
"target": "surface-obs-bufr",
"filter": {
"name": "bufr-only",
"rules": [
{ "id": "accept-bufr", "order": 1, "match": { "media_type": { "equals": "application/bufr" } }, "action": "accept" },
{ "id": "default-reject", "order": 999, "match": { "always": true }, "action": "reject" }
]
}
}'
# Subscription to an access-controlled dataset using basic auth
curl -X POST http://localhost:5002/subscriptions \
-H "Content-Type: application/json" \
-d '{
"topic": "cache/a/wis2/+/data/recommended/weather/surface-based-observations/#",
"target": "restricted-obs",
"credentials": { "type": "basic", "username": "myuser", "password": "s3cr3t" }
}'
# Route large downloads to the large-files queue
curl -X POST http://localhost:5002/subscriptions \
-H "Content-Type: application/json" \
-d '{
"topic": "cache/a/wis2/fr-meteofrance/data/core/weather/space-based-observations/noaa-21/cris",
"target": "space-obs",
"queue": "large_files"
}'
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
"save_path": "surface-obs",
"filter": {},
"credentials": null,
"queue": "small_files"
}
3.3. Get Subscription
Returns the full record for a specific subscription.
GET /subscriptions/{id}
3.3.1. Path Parameters
| Parameter | Type | Description |
|---|---|---|
|
string (UUID) |
Subscription UUID returned when the subscription was created |
3.3.2. Response
| Status | Description |
|---|---|
200 |
Success |
404 |
Subscription not found |
3.3.3. Example
curl http://localhost:5002/subscriptions/550e8400-e29b-41d4-a716-446655440000
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
"save_path": "surface-obs",
"filter": {},
"credentials": null,
"queue": "small_files"
}
Credential secrets (password, token) are never returned. Only type and username (for basic auth) are included in responses.
|
3.4. Update Subscription
Updates the save path, filter, credentials, or queue of an existing subscription. The topic cannot be changed — delete and recreate to change the topic.
PUT /subscriptions/{id}
Content-Type: application/json
3.4.1. Request Body
All fields are optional. Only provided fields are updated.
| Field | Type | Description |
|---|---|---|
|
string |
New subdirectory under the data root |
|
object |
New rule-based filter (replaces existing filter) |
|
object |
New credentials (replaces existing credentials) |
|
string |
New queue: |
3.4.2. Response
| Status | Description |
|---|---|
200 |
Updated subscription record |
400 |
Invalid field value |
404 |
Subscription not found |
503 |
Redis unavailable |
3.4.3. Example
curl -X PUT http://localhost:5002/subscriptions/550e8400-e29b-41d4-a716-446655440000 \
-H "Content-Type: application/json" \
-d '{ "target": "surface-obs-v2", "queue": "high_priority" }'
3.5. Delete Subscription
Removes a subscription. If it is the last subscription for its topic, the MQTT connection for that topic is closed.
DELETE /subscriptions/{id}
3.5.1. Response
| Status | Description |
|---|---|
200 |
Successfully deleted |
404 |
Subscription not found |
503 |
Redis unavailable |
3.5.2. Example
curl -X DELETE http://localhost:5002/subscriptions/550e8400-e29b-41d4-a716-446655440000
{ "status": "deleted", "id": "550e8400-e29b-41d4-a716-446655440000" }
4. Monitoring API
4.1. Health Check
GET /health
Always returns 200. Check the status field for actual health.
curl http://localhost:5002/health
{ "status": "healthy" }
4.2. Prometheus Metrics
Returns metrics in Prometheus text format.
GET /metrics
4.2.1. Available Metrics
| Metric | Type | Labels | Description |
|---|---|---|---|
|
Counter |
status |
Total notifications processed by Celery |
|
Counter |
cache, media_type |
Successfully downloaded files |
|
Counter |
cache, media_type |
Total bytes downloaded |
|
Counter |
reason |
Skipped notifications by reason |
|
Counter |
cache, reason |
Failed downloads |
|
Gauge |
queue_name |
Current tasks across all Celery queues |
4.2.2. Example
curl http://localhost:5002/metrics
4.3. OpenAPI Specification
GET /openapi
4.4. Swagger UI
Interactive API documentation available at:
GET /
GET /swagger
5. Error Responses
All error responses follow this format:
{ "error": "Error message describing the problem" }
5.1. Common Error Messages
| Status | Error | Cause |
|---|---|---|
400 |
"No topic provided" |
POST /subscriptions without a |
400 |
"credentials.type must be 'basic' or 'bearer'" |
Invalid credentials type |
400 |
"queue must be one of: high_priority, large_files, small_files" |
Unknown queue name |
404 |
"Subscription '{id}' not found" |
UUID does not exist |
503 |
"Failed to connect to Redis: …" |
Redis unavailable |
503 |
"Failed to queue subscription command…" |
Redis pub/sub failed |
6. Data Schemas
6.1. Subscription
Full subscription record as stored and returned by the API.
| Field | Type | Description |
|---|---|---|
|
string (UUID) |
Unique identifier assigned on creation |
|
string |
WIS2 MQTT topic pattern |
|
string | null |
Subdirectory under the data root where files are saved |
|
object |
Rule-based filter (empty object |
|
object | null |
Credentials used for downloading. Secrets are redacted in responses. |
|
string |
Download queue: |
6.2. Filter Schema
Filters use an ordered list of rules. Rules are evaluated in order; the first matching rule’s action is applied. If no rule matches, the file is accepted.
| Field | Type | Description |
|---|---|---|
|
string |
Filter name for identification |
|
array |
Ordered list of filter rules |
6.2.1. Filter Rule Schema
| Field | Type | Description |
|---|---|---|
|
string |
Unique rule identifier |
|
integer |
Execution order — lower values run first |
|
object |
Condition to match against. See Match Conditions. |
|
string |
|
6.2.2. Match Conditions
| Condition | Description |
|---|---|
|
Match on the file’s MIME type |
|
Match on file size in bytes |
|
Match on the originating centre ID (e.g., |
|
Match on the WIS2 data ID |
|
Match on the download URL |
|
Unconditionally match (use as a catch-all default rule) |
String operators: equals, not_equals, in, not_in, pattern (glob), regex
Size/numeric operators: gt_bytes, lt_bytes, gte_bytes, lte_bytes, between_bytes
Logical combinators: all (AND), any (OR), not
6.2.3. Filter Example
Accept only BUFR files smaller than 10 MB; reject everything else:
{
"name": "bufr-small",
"rules": [
{
"id": "accept-small-bufr",
"order": 1,
"match": {
"all": [
{ "media_type": { "equals": "application/bufr" } },
{ "size": { "lt_bytes": 10485760 } }
]
},
"action": "accept"
},
{
"id": "default-reject",
"order": 999,
"match": { "always": true },
"action": "reject"
}
]
}
6.3. Credentials Schema
Used to authenticate HTTP downloads from access-controlled datasets.
password and token are write-only — they are accepted in requests but never returned in responses.
|
| Field | Type | Description |
|---|---|---|
|
string |
|
|
string |
Required when |
|
string (write-only) |
Required when |
|
string (write-only) |
Required when |
7. Topic Pattern Reference
7.1. WIS2 Topic Structure
{origin|cache}/a/wis2/{centre-id}/data/{data-policy}/{earth-system-domain}/{category}/...
-
origin— Original data from the data provider -
cache— Cached copy from a Global Cache (recommended for reliability) -
{centre-id}— Centre identifier. The first field is the ISO2C country code and the second is a descriptive name for the centre (e.g.,de-dwdfor Deutscher Wetterdienst,fr-meteofrancefor Météo-France) -
{data-policy}— WMO Unified Data Policy:core(freely available) orrecommended(may require credentials) -
{earth-system-domain}— Earth system domain from the WMO Unified Data Policy
7.2. Wildcards
| Pattern | Symbol | Description |
|---|---|---|
Single-level |
|
Matches exactly one level |
Multi-level |
|
Matches zero or more levels (must be at end) |
7.3. Examples
| Pattern | Matches |
|---|---|
|
All data from Deutscher Wetterdienst |
|
Surface observations from all centres |
|
All core data from any centre |
|
All weather data (any policy) from any centre |