The structure of a tourism indicator, its fields, response models, and how to filter and sort indicator lists.
An indicator is the core resource in the service. It represents a named tourism performance metric — for example, “Hotel occupancy rate” or “Passenger arrivals by air” — organized under a domain and subdomain.
The governance boolean identifies indicators used for governance and policy reporting as distinct from general tourism statistics. Setting governance: true does not change how data is stored or queried — it only affects filtering.Use the governance_filter query parameter to show only governance indicators (true) or only non-governance indicators (false). Omitting the parameter returns all indicators regardless of the flag.
# List only governance indicatorscurl "https://api.example.com/indicators/?governance_filter=true"# List only non-governance indicatorscurl "https://api.example.com/indicators/?governance_filter=false"
The resources field holds a list of string IDs referencing objects in an external service (e.g., a resource management service). These IDs are used in two ways:
Data ingestion — When an external producer publishes data for a resource_id, the ingestor locates the indicator that owns that resource ID and attaches the data segment to it.
Resource cleanup — When a resource is deleted externally, the service receives a resource_deleted event and removes the resource ID from the indicator’s resources list along with all associated data segments.
Resources are added via a dedicated endpoint:
POST /indicators/{indicator_id}/resources/{resource_id}
This operation is idempotent — adding the same resource ID twice has no effect.
The service returns one of two shapes depending on the endpoint:
Indicator
Returned by single-resource endpoints (GET /indicators/{id}). The domain field is a fully populated domain object containing name, color, image, icon, and subdomains.
SimpleIndicator
Returned by list endpoints (GET /indicators/, GET /domains/{id}/indicators). The domain field is a bare ObjectId string to reduce payload size.
// Indicator (full){ "id": "64b2a1d3c9e5f23e4d7a0123", "name": "Hotel occupancy rate", "periodicity": "monthly", "favourites": 14, "governance": false, "description": "Percentage of available hotel rooms occupied in the reporting period.", "font": "Inter", "scale": null, "unit": "%", "carrying_capacity": "85", "domain": { "id": "64a1f3c2b5e4a12d3c8f9012", "name": "Accommodation", "color": "#3B82F6", "image": "https://kb.example.com/assets/accommodation.png", "icon": "https://kb.example.com/icons/bed.svg", "subdomains": ["Hotels", "Hostels", "Short-term rentals"] }, "subdomain": "Hotels", "resources": ["64c3b2e4d0f6a34f5e8b0456", "64c3b2e4d0f6a34f5e8b0789"]}// SimpleIndicator (list){ "id": "64b2a1d3c9e5f23e4d7a0123", "name": "Hotel occupancy rate", "periodicity": "monthly", "favourites": 14, "governance": false, "description": "Percentage of available hotel rooms occupied in the reporting period.", "font": "Inter", "scale": null, "unit": "%", "carrying_capacity": "85", "domain": "64a1f3c2b5e4a12d3c8f9012", "subdomain": "Hotels", "resources": ["64c3b2e4d0f6a34f5e8b0456", "64c3b2e4d0f6a34f5e8b0789"]}
The search endpoint (GET /indicators/search) accepts a query string and applies case-insensitive, word-based matching against name, description, and subdomain fields. Results are scored by relevance:
Match type
Score
Exact word match in name
+10 per word
Partial match in name
+5 per word
Exact word match in subdomain
+3 per word
Partial match in subdomain
+1.5 per word
Exact word match in description
+2 per word
Partial match in description
+1 per word
Multi-word bonus
+(matched/total) × 5
The governance_filter, domain_filter, and subdomain_filter parameters work on the search endpoint as well.
Search requires at least 2 characters. Queries shorter than 2 characters return an empty list.
Indicators use soft-delete semantics identical to domains. Deleted indicators have deleted: true and are excluded from all queries. Creating an indicator and then deleting it leaves the document in MongoDB with the flag set.