Skip to content

Api reference

components.hp_dataset.public.api

get_entities_by module-attribute

get_entities_by = get_entities_by

get_entity_by_identifier_fuzzy module-attribute

get_entity_by_identifier_fuzzy = (
    get_entity_by_identifier_fuzzy
)

get_organization_by_identifier module-attribute

get_organization_by_identifier = (
    get_organization_by_identifier
)

get_organization_by_internal_id module-attribute

get_organization_by_internal_id = (
    get_organization_by_internal_id
)

get_practitioner_by_identifier module-attribute

get_practitioner_by_identifier = (
    get_practitioner_by_identifier
)

get_practitioner_by_internal_id module-attribute

get_practitioner_by_internal_id = (
    get_practitioner_by_internal_id
)

get_practitioner_role_by_identifier module-attribute

get_practitioner_role_by_identifier = (
    get_practitioner_role_by_identifier
)

get_practitioner_role_by_internal_id module-attribute

get_practitioner_role_by_internal_id = (
    get_practitioner_role_by_internal_id
)

components.hp_dataset.public.controllers

api

GenericReferentialEndpoint

Bases: BaseController

Used to surface generic specialities (for instance) for the AlanMap search pages

get
get(country)

Get all referentials for a specific country, removing values that are not our own generic ones.

Source code in components/hp_dataset/public/controllers/api.py
@view_method(GlobalAuthorizationStrategies().authenticated())
@obs.api_call()
def get(self, country: str) -> Response:
    """
    Get all referentials for a specific country, removing values that are not our own generic ones.
    """
    from components.hp_dataset.internal.business_logic.queries.property_definitions import (
        get_all_referentials,
    )

    validated_country: Country = Country.validate(country)
    referentials = get_all_referentials(validated_country)

    generic_referentials: dict[str, Referential] = dict()
    for ref in referentials:
        filtered_values = [
            v
            for v in ref.values
            if v.code.startswith(ALAN_GENERIC_REFENTIAL_PREFIX)
        ]
        if filtered_values:
            generic_referentials[ref.name] = Referential(
                country=ref.country, name=ref.name, values=filtered_values
            )

    return make_json_response(
        generic_referentials,
        200,
    )

HpDatasetPublicEntityEndpoint

Bases: BaseController

Main controller for entity retrieval

get
get(entity_type, entity_id, query_args)

Get a single entity with related entities attached

Source code in components/hp_dataset/public/controllers/api.py
@view_method(GlobalAuthorizationStrategies().authenticated())
@obs.api_call()
@use_args(
    HpDatasetPublicEntityGetQuerySchema(),
    location="query",
    arg_name="query_args",
)
def get(
    self, entity_type: str, entity_id: UUID, query_args: dict[str, int]
) -> Response:
    """
    Get a single entity with related entities attached
    """
    validated_entity_type: EntityType = EntityType.validate(entity_type)

    if entity := get_dataclass_by_entity_type_and_internal_id(
        validated_entity_type,
        entity_id,
        max_related_entities=query_args.get("limit", 10),
    ):
        # Lets surface if this entity has manual edits
        from components.hp_dataset.internal.business_logic.queries.manual_entries import (
            has_manual_entries_by_entity_id,
        )

        has_manual_entries = has_manual_entries_by_entity_id(entity_id)
        entity_as_dict = entity.to_dict()

        # -------8<-----------------------------------------------------
        # Mitigating a bug in the mobile app: we'll forcibly return a fake
        # role in case we don't have one on a practitioner, so that the app
        # doesn't crash.
        # TODO cyril.chapellier 2026-03-20 REMOVE
        if (
            validated_entity_type == EntityType.PRACTITIONER
            and (entity.roles is None or len(entity.roles) == 0)  # type:ignore[union-attr] # temp fix
        ):
            from components.hp_dataset.public.entities.entities import (
                PractitionerRole,
            )

            entity_as_dict["roles"] = [
                PractitionerRole(
                    id=uuid4(),
                    country=Country.FRANCE,
                    displayable_name=None,
                    organization=None,
                    practitioner=None,
                    identifiers=dict(),
                    properties=dict(),
                ).to_dict()
            ]
        # ------->8-----------------------------------------------------

        return make_json_response(
            {
                "entity": entity_as_dict,
                "has_manual_entries": has_manual_entries,
            },
            200,
        )

    return make_json_response("Not Found", 404)

HpDatasetPublicEntityGetQuerySchema

Bases: Schema

Allows to limit the number of related entities when fetching a HP dataset entity

limit class-attribute instance-attribute
limit = Int(required=False)

HpDatasetPublicSearchEndpoint

Bases: BaseController

Main controller for public search

post
post(search_backend, search_mode, entity_type)

Search for entities based on filters

Expects a JSON body with SearchRequest structure: { "country": "france", "filters": [...], "text": "optional search text", "text_op": "stemmed", "geolocation": {lat: 48.85, lon: 2.35, radius: 1000}, "geolocation_op": "geo_within_radius", "limit": 10, "offset": 0 }

Source code in components/hp_dataset/public/controllers/api.py
@view_method(GlobalAuthorizationStrategies().authenticated())
@obs.api_call()
def post(
    self,
    # Flask passes URL params as strings
    search_backend: str,
    search_mode: str,
    entity_type: str,
) -> Response:
    """
    Search for entities based on filters

    Expects a JSON body with SearchRequest structure:
    {
        "country": "france",
        "filters": [...],
        "text": "optional search text",
        "text_op": "stemmed",
        "geolocation": {lat: 48.85, lon: 2.35, radius: 1000},
        "geolocation_op": "geo_within_radius",
        "limit": 10,
        "offset": 0
    }
    """
    # Validate URL parameters and convert to enums
    # EnumValidationError raised on invalid values is caught by Flask
    # and returns a clear error message
    validated_search_backend: SearchBackend = SearchBackend.validate(search_backend)
    validated_search_mode: SearchMode = SearchMode.validate(search_mode)
    validated_entity_type: EntityType = EntityType.validate(entity_type)

    search_request = SearchRequest(**request.json)  # type:ignore[arg-type]

    results = get_entities_by(
        search_backend=validated_search_backend,
        request=search_request,
        entrypoint=validated_entity_type,
        search_mode=validated_search_mode,
    )

    return make_json_response(
        {
            "results": [result.to_dict() for result in results],
        },
        200,
    )

hp_dataset_public_endpoint module-attribute

hp_dataset_public_endpoint = Endpoint('')

components.hp_dataset.public.entities

entities

Organization dataclass

Organization(
    id,
    country,
    displayable_name,
    identifiers,
    properties,
    total_roles=0,
    roles=None,
    parent_organization=None,
    children_organizations=list(),
)

Bases: DataClassJsonMixin

Represents an Organization — a legal entity — in the HP Dataset

__eq__
__eq__(other)

Compares two organizations. We need this to cater for dataclasses that don't contain all relationships (ie. roles) because they haven't been loaded.

Source code in components/hp_dataset/public/entities/entities.py
def __eq__(self, other: object) -> bool:
    """
    Compares two organizations.
    We need this to cater for dataclasses that don't contain
    all relationships (ie. roles) because they haven't been loaded.
    """
    if not isinstance(other, Organization):
        return NotImplemented
    return self.id == other.id
children_organizations class-attribute instance-attribute
children_organizations = field(default_factory=list)
country instance-attribute
country
displayable_name instance-attribute
displayable_name
id instance-attribute
id
identifiers instance-attribute
identifiers
parent_organization class-attribute instance-attribute
parent_organization = None
properties instance-attribute
properties
roles class-attribute instance-attribute
roles = None
total_roles class-attribute instance-attribute
total_roles = 0

Practitioner dataclass

Practitioner(
    id,
    country,
    displayable_name,
    identifiers,
    properties,
    total_roles=0,
    roles=None,
)

Bases: DataClassJsonMixin

Represents a Practitioner — an actual human being in the health system — in the HP Dataset

__eq__
__eq__(other)

Compares two practitioners. We need this to cater for dataclasses that don't contain all relationships (ie. roles) because they haven't been loaded.

Source code in components/hp_dataset/public/entities/entities.py
def __eq__(self, other: object) -> bool:
    """
    Compares two practitioners.
    We need this to cater for dataclasses that don't contain
    all relationships (ie. roles) because they haven't been loaded.
    """
    if not isinstance(other, Practitioner):
        return NotImplemented
    return self.id == other.id
country instance-attribute
country
displayable_name instance-attribute
displayable_name
id instance-attribute
id
identifiers instance-attribute
identifiers
properties instance-attribute
properties
roles class-attribute instance-attribute
roles = None
total_roles class-attribute instance-attribute
total_roles = 0

PractitionerRole dataclass

PractitionerRole(
    id,
    country,
    displayable_name,
    organization,
    practitioner,
    identifiers,
    properties,
)

Bases: DataClassJsonMixin

Represents a PractitionerRole — a link between a Practitioner and an Organization — in the HP Dataset

__eq__
__eq__(other)

Compares two roles. We need this to cater for dataclasses that don't contain all relationships (ie. the organization and the practitioner) because they haven't been loaded.

Source code in components/hp_dataset/public/entities/entities.py
def __eq__(self, other: object) -> bool:
    """
    Compares two roles.
    We need this to cater for dataclasses that don't contain
    all relationships (ie. the organization and the practitioner)
    because they haven't been loaded.
    """
    if not isinstance(other, PractitionerRole):
        return NotImplemented
    return self.id == other.id
country instance-attribute
country
displayable_name instance-attribute
displayable_name
id instance-attribute
id
identifiers instance-attribute
identifiers
organization instance-attribute
organization
practitioner instance-attribute
practitioner
properties instance-attribute
properties

Property dataclass

Property(
    id,
    value,
    definition_name,
    definition_value_type,
    description,
    source_names,
)

Bases: DataClassJsonMixin

Represents a Property — a value any Practitioner, PractitionerRole or Organization can hold — in the HP Dataset

definition_name instance-attribute
definition_name
definition_value_type instance-attribute
definition_value_type
description instance-attribute
description
id instance-attribute
id
source_names instance-attribute
source_names
value instance-attribute
value

search

BBoxValue

Bases: BaseModel

This represents a bounding box search (rectangular area)

max_lat class-attribute instance-attribute
max_lat = Field(..., ge=-90, le=90)
max_lon class-attribute instance-attribute
max_lon = Field(..., ge=-180, le=180)
min_lat class-attribute instance-attribute
min_lat = Field(..., ge=-90, le=90)
min_lon class-attribute instance-attribute
min_lon = Field(..., ge=-180, le=180)

Filter

Bases: BaseModel

A filter holds the needed information to filter a search request

on instance-attribute
on
op instance-attribute
op
property instance-attribute
property
value instance-attribute
value

FilterOp

Bases: AlanBaseEnum

Allowed filters in the search request

CONTAINS class-attribute instance-attribute
CONTAINS = 'contains'
EQ class-attribute instance-attribute
EQ = 'eq'
FUZZY class-attribute instance-attribute
FUZZY = 'fuzzy'
GEO_WITHIN_BBOX class-attribute instance-attribute
GEO_WITHIN_BBOX = 'geo_within_bbox'
GEO_WITHIN_RADIUS class-attribute instance-attribute
GEO_WITHIN_RADIUS = 'geo_within_radius'
GT class-attribute instance-attribute
GT = 'gt'
GTE class-attribute instance-attribute
GTE = 'gte'
IN class-attribute instance-attribute
IN = 'in'
LT class-attribute instance-attribute
LT = 'lt'
LTE class-attribute instance-attribute
LTE = 'lte'
NE class-attribute instance-attribute
NE = 'ne'
STEMMED class-attribute instance-attribute
STEMMED = 'stemmed'

RadiusValue

Bases: BaseModel

This represents a "circular radius" search around a given point, with a radius

lat class-attribute instance-attribute
lat = Field(..., ge=-90, le=90)
lon class-attribute instance-attribute
lon = Field(..., ge=-180, le=180)
radius class-attribute instance-attribute
radius = Field(default=1, ge=0)

SearchBackend

Bases: AlanBaseEnum

Lists all possible search backends

ALGOLIA class-attribute instance-attribute
ALGOLIA = 'algolia'
OPENSEARCH class-attribute instance-attribute
OPENSEARCH = 'opensearch'

SearchRequest

Bases: BaseModel

A search request to provide the API with filters to search on

country instance-attribute
country
filters instance-attribute
filters
geolocation class-attribute instance-attribute
geolocation = Field(default=None)
geolocation_limit class-attribute instance-attribute
geolocation_limit = Field(default=10)
geolocation_op class-attribute instance-attribute
geolocation_op = Field(default=None)
limit class-attribute instance-attribute
limit = Field(default=10, ge=1, le=100)
offset class-attribute instance-attribute
offset = Field(default=0, ge=0)
text class-attribute instance-attribute
text = Field(default=None)
text_op class-attribute instance-attribute
text_op = Field(default=None)

SearchResult dataclass

SearchResult(
    entity_id,
    entity,
    displayable_name,
    text_distance=None,
    geo_distance_meters=None,
)

Bases: DataClassJsonMixin

A search result as returned from an search API call

displayable_name instance-attribute
displayable_name
entity instance-attribute
entity
entity_id instance-attribute
entity_id
geo_distance_meters class-attribute instance-attribute
geo_distance_meters = None
text_distance class-attribute instance-attribute
text_distance = None

components.hp_dataset.public.enums

Country

Bases: AlanBaseEnum

Lists all supported countries by the dataset

BELGIUM class-attribute instance-attribute

BELGIUM = 'be'

CANADA class-attribute instance-attribute

CANADA = 'ca'

FRANCE class-attribute instance-attribute

FRANCE = 'fr'

SPAIN class-attribute instance-attribute

SPAIN = 'es'

DefinitionValueType

Bases: AlanBaseEnum

Lists all possible types of values we can have for a property.

The value_type is understood as an index or generic type, complementing the schema itself that validates the actual content and format of the value.

See https://www.notion.so/alaninsurance/Define-possible-value-types-to-accommodate-various-cases-2141426e8be7805c9ac9c16635abb1ee ⧉

ADDRESS class-attribute instance-attribute

ADDRESS = 'address'

ARRAY class-attribute instance-attribute

ARRAY = 'array'

BOOLEAN class-attribute instance-attribute

BOOLEAN = 'boolean'

CONTACT class-attribute instance-attribute

CONTACT = 'contact'

COSTS class-attribute instance-attribute

COSTS = 'costs'

DATE class-attribute instance-attribute

DATE = 'date'

DATETIME class-attribute instance-attribute

DATETIME = 'datetime'

ENUM class-attribute instance-attribute

ENUM = 'enum'

GEOLOCATION class-attribute instance-attribute

GEOLOCATION = 'geolocation'

HOURS class-attribute instance-attribute

HOURS = 'hours'

IDENTIFIER class-attribute instance-attribute

IDENTIFIER = 'identifier'

PSEUDO_IDENTIFIER class-attribute instance-attribute

PSEUDO_IDENTIFIER = 'pseudo-identifier'

SCORE class-attribute instance-attribute

SCORE = 'score'

TEXT class-attribute instance-attribute

TEXT = 'text'

URL class-attribute instance-attribute

URL = 'url'

UUID class-attribute instance-attribute

UUID = 'uuid'

EntityType

Bases: AlanBaseEnum

Lists all possible entities that a property can be linked to

ORGANIZATION class-attribute instance-attribute

ORGANIZATION = 'organization'

PRACTITIONER class-attribute instance-attribute

PRACTITIONER = 'practitioner'

PRACTITIONER_ROLE class-attribute instance-attribute

PRACTITIONER_ROLE = 'practitioner_role'

SearchIntent

Bases: AlanBaseEnum

Lists different intents on the usage of the API

  • search: standard intent, we want to search for full entities
  • autocomplete: we want a really fast autocomplete flavour, nothing more

AUTOCOMPLETE class-attribute instance-attribute

AUTOCOMPLETE = 'autocomplete'

SEARCH class-attribute instance-attribute

SEARCH = 'search'

SearchMode

Bases: AlanBaseEnum

Lists all possible ways we can retrieve results from an API search

  • full: will return the whole entity with its properties
  • id_and_name: will only return the id and the displayable name, which is faster since it'll directly come from the actual indexes we're searching in, not from a separate query.

FULL class-attribute instance-attribute

FULL = 'full'

ID_AND_NAME class-attribute instance-attribute

ID_AND_NAME = 'id_and_name'