Source code for pygleif.v2.api.models

"""Pydantic v2-bound models for the full GLEIF API v1.0 surface.

Covers the resources exposed by https://api.gleif.org/api/v1:

- ``lei-records``      -> :class:`GLEIFResponse`, :class:`SearchResponse`
- ``lei-records/{lei}/isins`` -> :class:`IsinResponse`
- ``lei-records/{lei}/*-relationship(s)`` -> :class:`RelationshipResponse`,
  :class:`RelationshipListResponse`
- ``lei-records/{lei}/*-reporting-exception`` ->
  :class:`ReportingExceptionResponse`
- ``lei-records/{lei}/field-modifications`` ->
  :class:`FieldModificationResponse`
- ``fuzzycompletions`` -> :class:`FuzzyCompletionResponse`
- ``autocompletions``  -> :class:`AutocompletionResponse`
- ``fields``           -> :class:`FieldsResponse`, :class:`FieldResponse`
- ``lei-issuers``      -> :class:`LeiIssuersResponse`, :class:`LeiIssuerResponse`
- ``vlei-issuers``     -> :class:`VLeiIssuersResponse`, :class:`VLeiIssuerResponse`
- reference data (``countries``, ``entity-legal-forms``,
  ``official-organizational-roles``, ``jurisdictions``, ``regions``,
  ``registration-authorities``, ``registration-agents``) -> typed
  ``*Response`` / list envelopes built on :class:`ResourceData`

The JSON API responses use camelCase keys; models accept both camelCase
(via the alias generator) and snake_case (``populate_by_name``). Keys the
API serves in kebab-case (e.g. ``managing-lou``) carry explicit aliases.
"""

from __future__ import annotations

from datetime import datetime  # noqa: TC003 - needed at runtime by pydantic
from typing import Any, Generic, TypeVar

from pygleif.v2.pydantic_shim import BaseModel, ConfigDict, Field, to_camel

DESCRIPTION_VALUES: dict[str, str] = {
    "lei": (
        "The LEI code is a 20-character, alpha-numeric code that defines the ISO "
        "17442 compatible identifier for the legal entity."
    ),
}


[docs] class BaseSchema(BaseModel): """Base schema with camelCase aliasing for GLEIF JSON API payloads.""" model_config = ConfigDict( alias_generator=to_camel, populate_by_name=True, )
# --------------------------------------------------------------------------- # LEI record (Level 1) models # ---------------------------------------------------------------------------
[docs] class ValidatedAt(BaseSchema): """Represent validated-at information.""" id: str other: str | None
[docs] class Registration(BaseSchema): """Represent registration information.""" corroboration_level: str initial_registration_date: datetime last_update_date: datetime managing_lou: str next_renewal_date: datetime other_validation_authorities: list[Any] status: str validated_as: str | None = None validated_at: ValidatedAt
[docs] class GeneralEntity(BaseSchema): """Represent a general entity.""" lei: str | None = Field(..., description=DESCRIPTION_VALUES["lei"]) name: str | None
[docs] class Address(BaseSchema): """Represent an address.""" language: str | None address_lines: list[str] address_number: str | None address_number_within_building: str | None mail_routing: str | None city: str region: str | None country: str postal_code: str | None
[docs] class Expiration(BaseSchema): """Represent expiration data.""" date: str | None reason: str | None
[docs] class LegalForm(BaseSchema): """Represent the legal form.""" id: str | None other: str | None
[docs] class Name(BaseSchema): """Represent a name.""" name: str | None language: str | None = None type: str | None = None
[docs] class RegisteredAt(BaseSchema): """Represent registered-at information.""" id: str other: str | None
[docs] class Entity(BaseSchema): """Represent entity information.""" associated_entity: GeneralEntity category: str creation_date: str | None event_groups: list[Any] expiration: Expiration headquarters_address: Address jurisdiction: str legal_address: Address legal_form: LegalForm legal_name: Name other_addresses: list[Any] other_names: list[Name] registered_as: str | None = None registered_at: RegisteredAt status: str successor_entities: list[Any] sub_category: str | None = None successor_entity: GeneralEntity transliteraded_other_names: list[Any] | None = None
[docs] class Attributes(BaseSchema): """Represent attribute information.""" bic: list[str] | None lei: str = Field(..., description=DESCRIPTION_VALUES["lei"]) entity: Entity registration: Registration
[docs] class LinkData(BaseSchema): """Represent a link.""" self: str | None = None related: str | None = None relationship_record: str | None = Field(None, alias="relationship-record") relationship_records: str | None = Field(None, alias="relationship-records") lei_record: str | None = Field(None, alias="lei-record") reporting_exception: str | None = Field(None, alias="reporting-exception")
[docs] class ResourceIdentifier(BaseSchema): """A JSON:API resource identifier (``type`` + ``id``).""" type: str | None = None id: str | None = None
[docs] class Relationships(BaseSchema): """Represent relationships between records. The API serves these keys in kebab-case (``managing-lou`` etc.), hence the explicit aliases. """ managing_lou: Links | None = Field(None, alias="managing-lou") lei_issuer: Links | None = Field(None, alias="lei-issuer") field_modifications: Links | None = Field(None, alias="field-modifications") direct_parent: Links | None = Field(None, alias="direct-parent") ultimate_parent: Links | None = Field(None, alias="ultimate-parent") direct_children: Links | None = Field(None, alias="direct-children") ultimate_children: Links | None = Field(None, alias="ultimate-children") isins: Links | None = None
[docs] class Data(BaseSchema): """Represent an LEI record data object.""" id: str type: str attributes: Attributes links: LinkData relationships: Relationships
#: Preferred v2 name for a single LEI record. LeiRecord = Data # --------------------------------------------------------------------------- # Meta / pagination # ---------------------------------------------------------------------------
[docs] class GoldenCopy(BaseSchema): """Represent golden copy information.""" publish_date: datetime
[docs] class Meta(BaseSchema): """Represent meta information.""" golden_copy: GoldenCopy | None = None pagination: Pagination | None = None
# --------------------------------------------------------------------------- # Response envelopes # ---------------------------------------------------------------------------
[docs] class GLEIFResponse(BaseSchema): """Single LEI record response (``/lei-records/{lei}``).""" meta: Meta data: Data
[docs] class SearchResponse(BaseSchema): """Search / list response (``/lei-records``).""" meta: Meta data: list[Data]
# --------------------------------------------------------------------------- # ISIN resource (``/lei-records/{lei}/isins``) # ---------------------------------------------------------------------------
[docs] class IsinAttributes(BaseSchema): """Attributes of an ISIN-LEI mapping.""" lei: str isin: str
[docs] class IsinData(BaseSchema): """A single ISIN-LEI mapping record.""" type: str id: str attributes: IsinAttributes
[docs] class IsinResponse(BaseSchema): """ISIN mapping list response.""" meta: Meta data: list[IsinData]
# --------------------------------------------------------------------------- # Fuzzy completions (``/fuzzycompletions``) and autocompletions # ---------------------------------------------------------------------------
[docs] class CompletionRelationships(BaseSchema): """Relationships of a completion result (link to the LEI record).""" lei_records: Links | None = Field(None, alias="lei-records")
[docs] class FuzzyCompletionAttributes(BaseSchema): """Attributes of a fuzzy completion result.""" value: str | None = None
[docs] class FuzzyCompletion(BaseSchema): """A single fuzzy completion match.""" type: str attributes: FuzzyCompletionAttributes relationships: CompletionRelationships | None = None
[docs] class FuzzyCompletionResponse(BaseSchema): """Fuzzy completion list response.""" data: list[FuzzyCompletion]
[docs] class AutocompletionAttributes(BaseSchema): """Attributes of an autocompletion suggestion.""" value: str | None = None highlighting: str | None = None
[docs] class Autocompletion(BaseSchema): """A single autocompletion suggestion.""" type: str attributes: AutocompletionAttributes relationships: CompletionRelationships | None = None
[docs] class AutocompletionResponse(BaseSchema): """Autocompletion list response.""" data: list[Autocompletion]
# --------------------------------------------------------------------------- # Fields metadata (``/fields``) # ---------------------------------------------------------------------------
[docs] class FieldAttributes(BaseSchema): """Metadata describing a single LEI data field.""" key: str | None = None field: str | None = None label: str | None = None data_type: str | None = None enum: list[Any] | None = None resource: str | None = None sortable: bool | None = None operators: list[str] | None = None contexts: list[Any] | None = None xpath: str | None = None
[docs] class FieldDescriptor(BaseSchema): """A single field descriptor from the ``/fields`` endpoint.""" type: str id: str attributes: FieldAttributes
[docs] class FieldsResponse(BaseSchema): """Fields metadata list response.""" meta: Meta | None = None data: list[FieldDescriptor]
[docs] class FieldResponse(BaseSchema): """Single field metadata response (``/fields/{id}``).""" data: FieldDescriptor
# --------------------------------------------------------------------------- # Generic JSON:API envelopes for typed resources # --------------------------------------------------------------------------- AttributesT = TypeVar("AttributesT", bound=BaseSchema)
[docs] class ResourceData(BaseSchema, Generic[AttributesT]): """A JSON:API data object with resource-specific typed attributes.""" type: str id: str attributes: AttributesT links: LinkData | None = None
[docs] class ResourceResponse(BaseSchema, Generic[AttributesT]): """Single-resource response envelope.""" meta: Meta | None = None data: ResourceData[AttributesT]
[docs] class ResourceListResponse(BaseSchema, Generic[AttributesT]): """Resource list response envelope.""" meta: Meta | None = None data: list[ResourceData[AttributesT]]
# --------------------------------------------------------------------------- # Relationship records (Level 2, ``/lei-records/{lei}/*-relationship(s)``) # ---------------------------------------------------------------------------
[docs] class RelationshipNode(BaseSchema): """Start or end node of a relationship record.""" id: str | None = None type: str | None = None
[docs] class RelationshipPeriod(BaseSchema): """Validity period reported for a relationship.""" start_date: datetime | None = None end_date: datetime | None = None type: str | None = None
[docs] class RelationshipDetail(BaseSchema): """The reported relationship between two LEI records.""" start_node: RelationshipNode | None = None end_node: RelationshipNode | None = None type: str | None = None status: str | None = None periods: list[RelationshipPeriod] = Field(default_factory=list)
[docs] class RelationshipRegistration(BaseSchema): """Registration details of a relationship record.""" initial_registration_date: datetime | None = None last_update_date: datetime | None = None status: str | None = None next_renewal_date: datetime | None = None managing_lou: str | None = None corroboration_level: str | None = None corroboration_documents: str | None = None corroboration_reference: str | None = None
[docs] class RelationshipAttributes(BaseSchema): """Attributes of a relationship record.""" valid_from: datetime | None = None valid_to: datetime | None = None relationship: RelationshipDetail | None = None registration: RelationshipRegistration | None = None
[docs] class RelationshipData(ResourceData[RelationshipAttributes]): """A single relationship record."""
[docs] class RelationshipResponse(ResourceResponse[RelationshipAttributes]): """Single relationship record response."""
[docs] class RelationshipListResponse(ResourceListResponse[RelationshipAttributes]): """Relationship record list response."""
# --------------------------------------------------------------------------- # Reporting exceptions (``/lei-records/{lei}/*-reporting-exception``) # ---------------------------------------------------------------------------
[docs] class ReportingExceptionAttributes(BaseSchema): """Attributes of a Level 2 reporting exception.""" valid_from: datetime | None = None valid_to: datetime | None = None lei: str | None = None category: str | None = None reason: str | None = None reference: str | None = None
[docs] class ReportingExceptionData(ResourceData[ReportingExceptionAttributes]): """A single reporting exception record."""
[docs] class ReportingExceptionResponse(ResourceResponse[ReportingExceptionAttributes]): """Reporting exception response."""
# --------------------------------------------------------------------------- # Field modifications (``/lei-records/{lei}/field-modifications``) # ---------------------------------------------------------------------------
[docs] class FieldModificationAttributes(BaseSchema): """A single historical change to an LEI record field.""" lei: str | None = None record_type: str | None = None modification_type: str | None = None field: str | None = None date: datetime | None = None value_old: Any = None value_new: Any = None context: Any = None
[docs] class FieldModificationData(ResourceData[FieldModificationAttributes]): """A single field modification record."""
[docs] class FieldModificationResponse(ResourceListResponse[FieldModificationAttributes]): """Field modification list response."""
# --------------------------------------------------------------------------- # LEI issuers (``/lei-issuers``) and vLEI issuers (``/vlei-issuers``) # ---------------------------------------------------------------------------
[docs] class LeiIssuerAttributes(BaseSchema): """Attributes of an LEI issuer (Local Operating Unit).""" lei: str | None = None name: str | None = None marketing_name: str | None = None reporting_name: str | None = None website: str | None = None organization_type: str | None = None short_description: str | None = None legal_domicile: str | None = None accreditation_date: str | None = None
[docs] class LeiIssuerData(ResourceData[LeiIssuerAttributes]): """A single LEI issuer record."""
[docs] class LeiIssuerResponse(ResourceResponse[LeiIssuerAttributes]): """Single LEI issuer response."""
[docs] class LeiIssuersResponse(ResourceListResponse[LeiIssuerAttributes]): """LEI issuer list response."""
[docs] class LeiIssuerJurisdictionAttributes(BaseSchema): """Jurisdiction an LEI issuer is accredited for.""" country_code: str | None = None accredited_as: str | None = None start_date: str | None = None end_date: str | None = None
[docs] class LeiIssuerJurisdictionsResponse( ResourceListResponse[LeiIssuerJurisdictionAttributes], ): """LEI issuer accredited jurisdiction list response."""
[docs] class VLeiIssuerAttributes(BaseSchema): """Attributes of a qualified vLEI issuing organization.""" lei: str | None = None name: str | None = None website: str | None = None marketing_name: str | None = None qualification_date: str | None = None
[docs] class VLeiIssuerData(ResourceData[VLeiIssuerAttributes]): """A single vLEI issuer record."""
[docs] class VLeiIssuerResponse(ResourceResponse[VLeiIssuerAttributes]): """Single vLEI issuer response."""
[docs] class VLeiIssuersResponse(ResourceListResponse[VLeiIssuerAttributes]): """vLEI issuer list response."""
# --------------------------------------------------------------------------- # Reference data code lists # ---------------------------------------------------------------------------
[docs] class CountryAttributes(BaseSchema): """ISO 3166 country code entry.""" code: str | None = None name: str | None = None
[docs] class CountryData(ResourceData[CountryAttributes]): """A single country record."""
[docs] class CountryResponse(ResourceResponse[CountryAttributes]): """Single country response."""
[docs] class CountriesResponse(ResourceListResponse[CountryAttributes]): """Country list response."""
[docs] class JurisdictionAttributes(BaseSchema): """Legal jurisdiction entry (ISO 3166 country / sub-region codes).""" code: str | None = None name: str | None = None
[docs] class JurisdictionData(ResourceData[JurisdictionAttributes]): """A single jurisdiction record."""
[docs] class JurisdictionResponse(ResourceResponse[JurisdictionAttributes]): """Single jurisdiction response."""
[docs] class JurisdictionsResponse(ResourceListResponse[JurisdictionAttributes]): """Jurisdiction list response."""
[docs] class RegionAttributes(BaseSchema): """ISO 3166 sub-region code entry.""" code: str | None = None name: str | None = None
[docs] class RegionData(ResourceData[RegionAttributes]): """A single region record."""
[docs] class RegionResponse(ResourceResponse[RegionAttributes]): """Single region response."""
[docs] class RegionsResponse(ResourceListResponse[RegionAttributes]): """Region list response."""
[docs] class LocalizedName(BaseSchema): """Localized name entry used by the ELF and OOR code lists.""" name: str | None = None local_name: str | None = None language: str | None = None language_code: str | None = None transliterated_name: str | None = None
[docs] class EntityLegalFormAttributes(BaseSchema): """ISO 20275 entity legal form (ELF) code entry.""" code: str | None = None country: str | None = None jurisdiction: str | None = None country_code: str | None = None subdivision_code: str | None = None date_created: str | None = None status: str | None = None names: list[LocalizedName] = Field(default_factory=list)
[docs] class EntityLegalFormData(ResourceData[EntityLegalFormAttributes]): """A single entity legal form record."""
[docs] class EntityLegalFormResponse(ResourceResponse[EntityLegalFormAttributes]): """Single entity legal form response."""
[docs] class EntityLegalFormsResponse(ResourceListResponse[EntityLegalFormAttributes]): """Entity legal form list response."""
[docs] class OfficialOrganizationalRoleAttributes(BaseSchema): """ISO 5009 official organizational role (OOR) code entry.""" code: str | None = None country: str | None = None jurisdiction: str | None = None country_code: str | None = None subdivision_code: str | None = None date_created: str | None = None status: str | None = None elf_code: str | None = None names: list[LocalizedName] = Field(default_factory=list)
[docs] class OfficialOrganizationalRoleData( ResourceData[OfficialOrganizationalRoleAttributes], ): """A single official organizational role record."""
[docs] class OfficialOrganizationalRoleResponse( ResourceResponse[OfficialOrganizationalRoleAttributes], ): """Single official organizational role response."""
[docs] class OfficialOrganizationalRolesResponse( ResourceListResponse[OfficialOrganizationalRoleAttributes], ): """Official organizational role list response."""
[docs] class RegistrationAuthorityJurisdiction(BaseSchema): """Jurisdiction covered by a registration authority.""" country: str | None = None country_code: str | None = None jurisdiction: str | None = None
[docs] class RegistrationAuthorityAttributes(BaseSchema): """GLEIF Registration Authority (RA) code list entry.""" code: str | None = None international_name: str | None = None local_name: str | None = None international_organization_name: str | None = None local_organization_name: str | None = None website: str | None = None jurisdictions: list[RegistrationAuthorityJurisdiction] = Field( default_factory=list, )
[docs] class RegistrationAuthorityData(ResourceData[RegistrationAuthorityAttributes]): """A single registration authority record."""
[docs] class RegistrationAuthorityResponse( ResourceResponse[RegistrationAuthorityAttributes], ): """Single registration authority response."""
[docs] class RegistrationAuthoritiesResponse( ResourceListResponse[RegistrationAuthorityAttributes], ): """Registration authority list response."""
[docs] class RegistrationAgentAttributes(BaseSchema): """Registration agent entry.""" name: str | None = None lei: str | None = None lei_issuer: str | None = None websites: list[str] = Field(default_factory=list)
[docs] class RegistrationAgentData(ResourceData[RegistrationAgentAttributes]): """A single registration agent record."""
[docs] class RegistrationAgentResponse(ResourceResponse[RegistrationAgentAttributes]): """Single registration agent response."""
[docs] class RegistrationAgentsResponse(ResourceListResponse[RegistrationAgentAttributes]): """Registration agent list response."""