Skip to main content
Every indicator belongs to exactly one domain and one subdomain. Domains are top-level categories (e.g., Accommodation, Transport), and subdomains are string labels nested inside a domain. There is no separate subdomain collection — a subdomain is simply an entry in a domain’s subdomains array.

Domain schema

A domain document contains the following fields:
FieldTypeRequiredDescription
idstring (ObjectId)YesMongoDB ObjectId, auto-generated
namestringYesHuman-readable label, e.g. "Accommodation"
colorstringYesHex colour code used for UI theming, e.g. "#3B82F6"
imagestringNoURL of a background or thumbnail image (default "")
iconstringNoURL or identifier of an icon asset (default "")
subdomainsstring[]YesOrdered list of subdomain labels, e.g. ["Hotels", "Hostels"]
{
  "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"]
}

Domain/subdomain hierarchy

The hierarchy is intentionally flat — there is no subdomain document or collection. Subdomains live entirely as string values in the parent domain’s subdomains array.
Domain: Accommodation
  └── subdomain: "Hotels"
  └── subdomain: "Hostels"
  └── subdomain: "Short-term rentals"

Domain: Transport
  └── subdomain: "Airlines"
  └── subdomain: "Rail"
  └── subdomain: "Ferry"
When you create an indicator, you reference both the domain ObjectId and the subdomain string. The service validates that the subdomain string exists in the domain’s subdomains array before saving the indicator.
Deleting a domain performs a cascade soft-delete: all indicators whose domain field matches the deleted domain are also marked as deleted: true. This operation is irreversible through the API.

Soft deletes

Domains use soft-delete semantics. A deleted domain has deleted: true set in MongoDB and is excluded from all read queries. The domain document itself is retained in the database.

Creating a domain

curl -X POST https://api.example.com/domains/ \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Accommodation",
    "color": "#3B82F6",
    "image": "",
    "icon": "",
    "subdomains": ["Hotels", "Hostels", "Short-term rentals"]
  }'
The response is the full Domain object including the generated id.

Updating subdomains

Use a PUT request to replace the entire domain (including its subdomains list) or a PATCH request to update only specific fields:
# Add a new subdomain via PATCH
curl -X PATCH https://api.example.com/domains/64a1f3c2b5e4a12d3c8f9012 \
  -H "Content-Type: application/json" \
  -d '{
    "subdomains": ["Hotels", "Hostels", "Short-term rentals", "Camping"]
  }'
Removing a subdomain string from the subdomains array does not automatically delete indicators that reference that subdomain. The indicators will continue to exist with their subdomain field pointing to the removed string. Update or delete those indicators separately before removing the subdomain.

Icon and image uploads

The service exposes a dedicated endpoint that proxies upload requests to the external knowledge-base service:
POST /domains/{domain_id}/icon
POST /domains/{domain_id}/image
Uploads are sent as multipart/form-data. The knowledge-base service stores the asset and returns a URL, which is then saved to the domain’s icon or image field.
curl -X POST https://api.example.com/domains/64a1f3c2b5e4a12d3c8f9012/icon \
  -F "file=@./accommodation-icon.svg"
You can pre-populate icon and image with any publicly accessible URL when creating the domain. The upload endpoint is only needed when you want the service to manage the asset lifecycle through the knowledge-base service.

Filtering indicators by domain and subdomain

Indicators can be listed scoped to a domain or a specific subdomain:
GET /domains/{domain_id}/indicators
GET /domains/{domain_id}/subdomains/{subdomain_name}/indicators
Both endpoints support the same governance_filter, sort_by, sort_order, skip, and limit query parameters as the top-level indicators endpoint.

Build docs developers (and LLMs) love