Skip to main content

Endpoint

GET /indicators/search
Searches indicators by matching the query string against the name, description, and subdomain fields using case-insensitive word-based matching. Results are scored by relevance and can be further narrowed with domain, subdomain, and governance filters.

Relevance scoring

Each match is assigned a score based on where the query terms appear:
Match typeScore per word
Exact word match in name10.0
Partial match in name5.0
Exact word match in subdomain3.0
Exact word match in description2.0
Partial match in subdomain1.5
Partial match in description1.0
Matching multiple query words adds a bonus proportional to the fraction of words matched. When sort_by is relevance or an unrecognised field, results are sorted by score descending. For recognised fields (name, periodicity, favourites), results are sorted by the specified field.
The query string must be at least 2 characters long. An empty or single-character query returns an empty array.

Query parameters

q
string
required
Search query text. Minimum 2 characters. Multiple words are matched independently — indicators matching any word are returned.
skip
integer
default:"0"
Number of results to skip. Minimum: 0.
limit
integer
default:"10"
Maximum number of results to return. Minimum: 1. Maximum: 20.
sort_by
string
default:"name"
Field to sort by. Accepted values: name, periodicity, favourites, relevance. Use relevance to order by best match score.
sort_order
string
default:"asc"
Sort direction for field-based sorting. Accepted values: asc, desc. Ignored when sort_by is relevance.
governance_filter
boolean
When provided, filters results to indicators where governance matches the given value.
domain_filter
string
ObjectId string of a domain. When provided, limits results to indicators belonging to that domain.
subdomain_filter
string
Subdomain name. When provided, limits results to indicators within that subdomain.

Response

Returns an array of full Indicator objects. Each object has the domain field populated as a complete domain object (not just an ID).
[]
object[]

Examples

Basic text search:
curl --request GET \
  --url 'http://localhost:8080/indicators/search?q=tourist+arrivals'
Search filtered by domain and governance, sorted by relevance:
curl --request GET \
  --url 'http://localhost:8080/indicators/search?q=carbon+emissions&domain_filter=64a1f2b3c4d5e6f7a8b9c0a2&governance_filter=true&sort_by=relevance&limit=5'
Search within a subdomain with pagination:
curl --request GET \
  --url 'http://localhost:8080/indicators/search?q=visitor&subdomain_filter=Visitor%20volume&skip=0&limit=10&sort_by=favourites&sort_order=desc'

Sample response

200
[
  {
    "id": "64a1f2b3c4d5e6f7a8b9c0d1",
    "name": "Annual tourist arrivals",
    "periodicity": "annual",
    "favourites": 42,
    "governance": false,
    "description": "Total number of tourist arrivals recorded each year.",
    "font": "National Tourism Board",
    "scale": "national",
    "unit": "persons",
    "carrying_capacity": null,
    "domain": {
      "id": "64a1f2b3c4d5e6f7a8b9c0a1",
      "name": "Tourism flows",
      "color": "#3B82F6",
      "image": "",
      "icon": "",
      "subdomains": ["Visitor volume", "Visitor spending", "Visitor origin"]
    },
    "subdomain": "Visitor volume",
    "resources": [
      "64a1f2b3c4d5e6f7a8b9c0b2"
    ]
  },
  {
    "id": "64a1f2b3c4d5e6f7a8b9c0d3",
    "name": "Monthly tourist departures",
    "periodicity": "monthly",
    "favourites": 8,
    "governance": false,
    "description": null,
    "font": null,
    "scale": null,
    "unit": "persons",
    "carrying_capacity": null,
    "domain": {
      "id": "64a1f2b3c4d5e6f7a8b9c0a1",
      "name": "Tourism flows",
      "color": "#3B82F6",
      "image": "",
      "icon": "",
      "subdomains": ["Visitor volume", "Visitor spending", "Visitor origin"]
    },
    "subdomain": "Visitor volume",
    "resources": []
  }
]

Build docs developers (and LLMs) love