Skip to main content
This guide walks you through cloning the repository, configuring your environment, and making your first API calls against a fully running stack.
1

Prerequisites

Make sure the following tools are installed before you begin:Verify Docker Compose is available:
docker compose version
2

Clone the repository

git clone https://github.com/your-org/indicator-service.git
cd indicator-service
3

Create your environment file

Copy the example environment file and edit it if needed:
cp .env.example .env
The default .env.example contains:
.env.example
ORIGINS=http://localhost,http://localhost:5173
ORIGINS is a comma-separated list of allowed CORS origins. Add any additional frontend URLs here. All other service URLs (MongoDB, Redis, RabbitMQ) are wired together automatically through Docker Compose.
The docker-compose.override.yml file automatically injects RABBITMQ_URL, port bindings, and the RabbitMQ service when you run docker compose up, so no extra configuration is needed for local development.
4

Start all services

docker compose up
Docker Compose builds the application image and starts four services:
ServiceContainer namePurpose
indicator-serviceindicator-serviceFastAPI application on port 8080
indicators-mongoindicators-mongoMongoDB data store
indicators-redisindicators-redisRedis cache
rabbitmqindicator-rabbitmqMessage broker (AMQP on 5672, management UI on 15674)
The service waits for MongoDB to pass its health check before starting, so first-boot may take 15–30 seconds.
Run docker compose up --build after modifying requirements.txt to rebuild the application image. For code changes alone, the develop.watch configuration in docker-compose.yml syncs ./app into the container automatically without a rebuild.
5

Verify the service is running

Once the container is healthy, ping the health endpoint:
curl http://localhost:8080/health/
Expected response:
{"message": "Hello from indicator service!"}
The Docker health check (curl -f http://localhost:8080/health/) runs every 10 seconds with a 5-second timeout. Wait for indicator-service to show healthy in docker ps before proceeding.
6

Create a domain

Indicators are organized under domains and subdomains. Create a domain first:
curl -s -X POST http://localhost:8080/domains/ \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Environment",
    "color": "#22c55e",
    "subdomains": ["Air Quality", "Water", "Biodiversity"]
  }'
The response includes the new domain’s id. Copy it — you need it in the next step.
{
  "id": "6657a1f3e4b0c2a1d3f8e901",
  "name": "Environment",
  "color": "#22c55e",
  "image": "",
  "icon": "",
  "subdomains": ["Air Quality", "Water", "Biodiversity"]
}
7

Create an indicator

Create an indicator under the domain and one of its subdomains. Replace <domain_id> with the id from the previous step:
curl -s -X POST http://localhost:8080/indicators/<domain_id>/Air%20Quality/ \
  -H "Content-Type: application/json" \
  -d '{
    "name": "PM2.5 Concentration",
    "periodicity": "daily",
    "favourites": 0,
    "governance": false,
    "description": "Daily average particulate matter 2.5 µg/m³",
    "unit": "µg/m³"
  }'
A successful response returns the full indicator object with a nested domain object:
{
  "id": "6657a2b4e4b0c2a1d3f8e902",
  "name": "PM2.5 Concentration",
  "periodicity": "daily",
  "favourites": 0,
  "governance": false,
  "description": "Daily average particulate matter 2.5 µg/m³",
  "unit": "µg/m³",
  "font": null,
  "scale": null,
  "carrying_capacity": null,
  "domain": {
    "id": "6657a1f3e4b0c2a1d3f8e901",
    "name": "Environment",
    "color": "#22c55e",
    "image": "",
    "icon": "",
    "subdomains": ["Air Quality", "Water", "Biodiversity"]
  },
  "subdomain": "Air Quality",
  "resources": []
}
8

Verify data ingestion via RabbitMQ

The service listens on the resource_data queue for time-series data published by external producers. When a message arrives, the data ingestor stores it as a raw segment in MongoDB, updates the merged_indicators collection, and clears the related Redis cache entries.To test ingestion, publish a message to the resource_data queue using the RabbitMQ management UI at http://localhost:15674 (credentials: guest / guest):
{
  "resource_id": "<your-resource-id>",
  "data": [
    {"x": "2024-01-15T00:00:00Z", "y": 12.4},
    {"x": "2024-01-16T00:00:00Z", "y": 15.1},
    {"x": "2024-01-17T00:00:00Z", "y": 9.8}
  ]
}
A resource_id must be linked to an indicator via POST /indicators/{indicator_id}/resources before messages for that resource are processed. Messages with no matching indicator are acknowledged and discarded.
The service also consumes the resource_deleted queue — when a resource is deleted, the service removes the associated data segments, re-merges remaining data, and invalidates the cache.

Build docs developers (and LLMs) love