Models

Pydantic models for API entities.

Base Models

Base models for all Numista entities.

Common configuration, behavior, and abstract base classes for Pydantic models.

class numistalib.models.base.base_model.NumistaBaseModel[source]

Bases: ABC, BaseModel

Base model for all Numista entities.

Provides a shared Pydantic base configuration with: - Strict validation - Immutability control - Extra field prohibition - Consistent configuration

__rich_repr__() Iterable[Any | Tuple[Any] | Tuple[str, Any] | Tuple[str, Any, Any]][source]

Make models look good when printed with rich.print().

as_panel(style_overrides: dict[str, Any] | None = None) Any[source]

Render model as Rich Panel.

Default implementation creates a panel with formatted fields. Override in subclasses for custom panel layout.

Parameters:

style_overrides (dict[str, Any] | None) – Optional style overrides for the panel

Returns:

Rich Panel with model data

Return type:

Panel

property formatted_fields: list[str]

Return list of formatted strings for all model fields.

Automatically formats all fields (regular and computed) in the model using format_field() with default column alignment and indentation.

Returns:

List of formatted field strings

Return type:

list[str]

property formatted_fields_dict: dict[str, str]

Return dictionary of formatted strings for all model fields.

Automatically formats all fields (regular and computed) in the model using format_field() with default column alignment and indentation.

Returns:

Dictionary mapping field names to formatted field strings

Return type:

dict[str, str]

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

render_compact() ConsoleRenderable | RichCast | str[source]

Render compact representation for grid display.

Default implementation returns formatted title and key metadata. Override in subclasses for custom compact display.

Returns:

Compact renderable for grid/column layout

Return type:

RenderableType

classmethod render_list(items: list[Self]) Group | str[source]

Render list of items as Rich Group with horizontal rule separators.

Helper for CLI list rendering. Calls render_compact() on each item and adds horizontal rules between items when there are multiple.

Parameters:

items (list[Self]) – List of model instances to render

Returns:

Rich Group containing all items with separators, or message if empty

Return type:

Group | str

to_api_dict(**kwargs: Any) dict[Any, Any][source]

Return dict suitable for sending back to API or clean export. Uses aliases, excludes None by default.

class numistalib.models.base.base_model.RichField(value: Any | None = None)[source]

Bases: object

Wrapper for Rich renderables to use as Pydantic fields.

Stores any Rich renderable (Panel, Table, Text, or plain string/None) and implements the Rich console protocol for direct rendering.

Also provides a simple format_field helper used by tests to produce aligned label/value output.

classmethod __get_pydantic_core_schema__(source_type: Any, handler: Any) InvalidSchema | AnySchema | NoneSchema | BoolSchema | IntSchema | FloatSchema | DecimalSchema | StringSchema | BytesSchema | DateSchema | TimeSchema | DatetimeSchema | TimedeltaSchema | LiteralSchema | MissingSentinelSchema | EnumSchema | IsInstanceSchema | IsSubclassSchema | CallableSchema | ListSchema | TupleSchema | SetSchema | FrozenSetSchema | GeneratorSchema | DictSchema | AfterValidatorFunctionSchema | BeforeValidatorFunctionSchema | WrapValidatorFunctionSchema | PlainValidatorFunctionSchema | WithDefaultSchema | NullableSchema | UnionSchema | TaggedUnionSchema | ChainSchema | LaxOrStrictSchema | JsonOrPythonSchema | TypedDictSchema | ModelFieldsSchema | ModelSchema | DataclassArgsSchema | DataclassSchema | ArgumentsSchema | ArgumentsV3Schema | CallSchema | CustomErrorSchema | JsonSchema | UrlSchema | MultiHostUrlSchema | DefinitionsSchema | DefinitionReferenceSchema | UuidSchema | ComplexSchema[source]

Pydantic v2 integration: accept any input and wrap as RichField.

Allows using RichField as a typed field without enabling arbitrary_types_allowed globally.

format_field(label: str, width: int = 20, fill_char: str = ' ') str[source]

Return a simple one-line formatted label/value string.

Parameters:
  • label (str) – Field label to display before the value

  • width (int) – Column at which value starts (minimum)

  • fill_char (str) – Character used to pad between label and value

numistalib.models.base.base_model.format_field(label: str, value: Any, value_column: int | None = None, hanging_indent: int | None = None, short_line_field_separator: str = ' ') str[source]

Format a single field with label and value using Rich markup.

Applies intelligent formatting based on value length and content: - Short values (≤25 chars): Same line, aligned at value_column - Long values (>25 chars): Next line at column 1 - Multiline values: Indented at ‘indent’ columns, extra linefeed after

Parameters:
  • label (str) – Field label

  • value (Any) – Field value

  • value_column (int | None) – Column where values start (default: uses panel_value_column class property)

  • indent (int | None) – Indentation for multiline values (default: uses hanging_indent class property)

Returns:

Formatted field string with Rich markup and proper alignment

Return type:

str

numistalib.models.base.base_model.safe(val: Any, default: str = '') str[source]

Return string representation or default if None or empty.

numistalib.models.base.base_model.scrub(value: Any) str[source]

Scrub HTML from field values, preserving formatting.

Uses BeautifulSoup4 to detect paragraphs, breaks, and links, converting them to appropriate plain text with Rich markup.

Parameters:

value (Any) – Field value (may contain HTML)

Returns:

Cleaned value with Rich markup for links

Return type:

str

Types

Numista catalogue type models.

Pydantic models for Numista coin/banknote/exonumia types. Used for validation and data transfer between integration and service layers.

class numistalib.models.types.Composition(*, text: str)[source]

Bases: NumistaBaseModel

Metal composition information for coin types.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

text: str
class numistalib.models.types.Country(*, code: Annotated[str, MaxLen(max_length=50)], name: Annotated[str, MaxLen(max_length=255)])[source]

Bases: NumistaBaseModel

Country information with code and name.

__str__() str[source]

Return formatted country with code and name.

code: str
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class numistalib.models.types.CurrencyValue(*, text: str, numericValue: float | None = None, numerator: int | None = None, denominator: int | None = None, currency: Currency | None = None)[source]

Bases: NumistaBaseModel

Currency value information.

currency: Currency | None
denominator: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

numerator: int | None
numeric_value: float | None
text: str
class numistalib.models.types.Demonetization(*, isDemonetized: bool, demonetizationDate: date | None = None)[source]

Bases: NumistaBaseModel

Demonetization status and date information.

demonetization_date: date | None
is_demonetized: bool
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod parse_partial_date(v: Any) date | None[source]

Handle partial dates with 00 day or month and various formats.

class numistalib.models.types.Edge(*, description: str | None = None, picture: str | None = None, thumbnail: str | None = None, pictureCopyright: str | None = None, pictureCopyrightUrl: str | None = None, lettering: str | None = None, letteringScripts: list[dict[str, Any]] | None = None, letteringTranslation: str | None = None)[source]

Bases: NumistaBaseModel

Edge specifications for a coin type.

Parameters:
  • description (str | None) – Description of the edge (e.g., ‘Reeded’, ‘Plain’)

  • picture (str | None) – Picture URL of the edge

  • thumbnail (str | None) – Thumbnail URL of the edge

  • picture_copyright (str | None) – Copyright information for the picture

  • lettering (str | None) – Lettering on the edge

  • lettering_scripts (list[dict[str, Any]] | None) – Scripts used in edge lettering

  • lettering_translation (str | None) – Translation of edge lettering

description: str | None
lettering: str | None
lettering_scripts: list[dict[str, Any]] | None
lettering_translation: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

picture: str | None
property pillow_image: Image | None[source]

Download and cache the full picture as a Pillow Image.

property pillow_thumbnail: Image | None[source]

Download and cache the thumbnail as a Pillow Image.

property renderable_image: Any | None[source]

Ready-to-print textual_image renderable (full picture).

property renderable_thumbnail: Any | None[source]

Ready-to-print thumbnail.

thumbnail: str | None
class numistalib.models.types.LetteringScript(*, name: str)[source]

Bases: NumistaBaseModel

Lettering script information for coin designs.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class numistalib.models.types.Obverse(*, engravers: list[str] | None = None, designers: list[str] | None = None, description: str | None = None, lettering: str | None = None, letteringScripts: list[LetteringScript] | None = None, picture: AnyUrl, thumbnail: AnyUrl, pictureCopyright: str | None = None, pictureCopyrightUrl: AnyUrl | None = None, pictureLicenseName: str | None = None, pictureLicenseUrl: AnyUrl | None = None, letteringTranslation: str | None = None, unabridgedLegend: str | None = None)[source]

Bases: SideBase

Obverse (front/heads) side of a coin or banknote.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class numistalib.models.types.Printer(*, id: int, name: str)[source]

Bases: NumistaBaseModel

Printer information for banknotes.

Similar to Mint but for banknote printers.

Parameters:
  • id (int) – Unique printer ID

  • name (str) – Printer name

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class numistalib.models.types.References(*, references: list[Reference])[source]

Bases: NumistaBaseModel

Collection of references for a type.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

references: list[Reference]
class numistalib.models.types.Reverse(*, engravers: list[str] | None = None, designers: list[str] | None = None, description: str | None = None, lettering: str | None = None, letteringScripts: list[LetteringScript] | None = None, picture: AnyUrl, thumbnail: AnyUrl, pictureCopyright: str | None = None, pictureCopyrightUrl: AnyUrl | None = None, pictureLicenseName: str | None = None, pictureLicenseUrl: AnyUrl | None = None, letteringTranslation: str | None = None, unabridgedLegend: str | None = None)[source]

Bases: SideBase

Reverse (back/tails) side of a coin or banknote.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class numistalib.models.types.Ruler(*, numista_id: int, name: str, wikidataId: str | None = None, nomismaId: str | None = None, group: RulerGroup | None = None)[source]

Bases: NumistaBaseModel

Maps to Numista ruler schema for detailed ruler information.

group: RulerGroup | None
property group_id: int | None

Extract group ID from group.

Returns:

Group ID if group present, else None.

Return type:

int | None

property group_name: str | None

Extract group name from group.

Returns:

Group name if group present, else None.

Return type:

str | None

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
nomisma_id: str | None
render_compact() str[source]

Render compact ruler display.

classmethod render_table(items: list[Ruler], title: str = '') Table[source]

Generate table for ruler list with computed group fields.

Parameters:
  • items (list[Ruler]) – List of Ruler instances

  • title (str) – Table title

Returns:

Rich table with ruler information

Return type:

Table

wikidata_id: str | None
property wikidata_url: Url | None

Computed Wikidata URL from wikidata_id.

Returns:

Full Wikidata URL if wikidata_id present, else None.

Return type:

Url | None

class numistalib.models.types.RulerGroup(*, numista_id: int, name: str)[source]

Bases: NumistaBaseModel

Ruler group information for hierarchical ruler organization.

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class numistalib.models.types.SideBase(*, engravers: list[str] | None = None, designers: list[str] | None = None, description: str | None = None, lettering: str | None = None, letteringScripts: list[LetteringScript] | None = None, picture: AnyUrl, thumbnail: AnyUrl, pictureCopyright: str | None = None, pictureCopyrightUrl: AnyUrl | None = None, pictureLicenseName: str | None = None, pictureLicenseUrl: AnyUrl | None = None, letteringTranslation: str | None = None, unabridgedLegend: str | None = None)[source]

Bases: NumistaBaseModel, ABC

Base class for obverse and reverse sides of a type.

Formatted copyright link for textual display.

description: str | None
designers: list[str] | None
engravers: list[str] | None
property formatted_fields: list[str]

Return formatted fields excluding redundant computed fields and formatting lists properly.

lettering: str | None
property lettering_lines: list[str]

Splits the lettering into individual lines using the embedded line break.

lettering_scripts: list[LetteringScript] | None
lettering_translation: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

picture: AnyUrl
picture_license_name: str | None
picture_license_url: AnyUrl | None

Formatted picture link for textual display.

property pillow_image: Image | None[source]

Download and cache the full picture as a Pillow Image.

property pillow_thumbnail: Image | None[source]

Download and cache the thumbnail as a Pillow Image.

property renderable_image: Any | None[source]

Ready-to-print textual_image renderable (full picture).

property renderable_thumbnail: Any | None[source]

Ready-to-print thumbnail.

thumbnail: AnyUrl

Formatted thumbnail link for textual display.

unabridged_legend: str | None
class numistalib.models.types.Technique(*, text: str)[source]

Bases: NumistaBaseModel

Minting technique information.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

text: str
class numistalib.models.types.TypeBase(*, id: Annotated[int, Gt(gt=0)], title: Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=500, pattern=None)], category: Literal['coin', 'banknote', 'exonumia'], minYear: Annotated[int | None, Ge(ge=-9999), Le(le=9999)] = None, maxYear: Annotated[int | None, Ge(ge=-9999), Le(le=9999)] = None)[source]

Bases: NumistaBaseModel, ABC

Common fields shared between basic and full type representations.

category: Literal['coin', 'banknote', 'exonumia']
max_year: int | None
min_year: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

numista_id: int
property numista_url: HttpUrl

Get canonical Numista URL for this type.

title: Annotated[str, StringConstraints(strip_whitespace=True, max_length=500)]
validate_years() TypeBase[source]

Validate that min_year does not exceed max_year.

property year_range: str

Get human-readable year range.

class numistalib.models.types.TypeBasic(*, id: Annotated[int, Gt(gt=0)], title: Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=500, pattern=None)], category: Literal['coin', 'banknote', 'exonumia'], minYear: Annotated[int | None, Ge(ge=-9999), Le(le=9999)] = None, maxYear: Annotated[int | None, Ge(ge=-9999), Le(le=9999)] = None, issuer: Issuer | None = None, country: Country | None = None, obverseThumbnail: HttpUrl | None = None, reverseThumbnail: HttpUrl | None = None)[source]

Bases: TypeBase

Basic type information from search results.

country: Country | None
issuer: Issuer | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

obverse_thumbnail: HttpUrl | None
render_compact() Any[source]

Render compact representation with thumbnail and formatted fields.

Returns:

Rich renderable (Group with thumbnail + text or just text)

Return type:

Any

classmethod render_table(items: list[TypeBasic], title: str = '') Table[source]

Render a concise table for type search results.

Columns include key catalogue search fields expected by the CLI: Numista ID, Type title, Category, First year, Last year, Issuer, Country, Obverse thumb URL, Reverse thumb URL. Issuer is rendered as a short name (link when possible).

reverse_thumbnail: HttpUrl | None
to_dict() dict[str, object][source]

Return a compact dict representation used by tests.

class numistalib.models.types.TypeFull(*, id: Annotated[int, Gt(gt=0)], title: Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=500, pattern=None)], category: Literal['coin', 'banknote', 'exonumia'], minYear: Annotated[int | None, Ge(ge=-9999), Le(le=9999)] = None, maxYear: Annotated[int | None, Ge(ge=-9999), Le(le=9999)] = None, url: HttpUrl, issuer: Issuer, issueTerms: IssueTerms | None = None, issuingEntity: dict[str, Any] | None = None, secondaryIssuingEntity: dict[str, Any] | None = None, type: Annotated[str | None, MaxLen(max_length=100)] = None, ruler: list[Ruler] | None = None, value: CurrencyValue | None = None, demonetization: Demonetization | None = None, size: Annotated[float | None, Ge(ge=0)] = None, size2: Annotated[float | None, Ge(ge=0)] = None, thickness: Annotated[float | None, Ge(ge=0)] = None, weight: Annotated[float | None, Ge(ge=0)] = None, shape: Annotated[str | None, MaxLen(max_length=100)] = None, composition: Composition | None = None, technique: Technique | None = None, obverse: Obverse | None = None, reverse: Reverse | None = None, watermark: Watermark | None = None, references: list[Reference] | None = None, mints: list[Mint] | None = None, printers: list[Printer] | None = None, comments: str | None = None, tags: list[str] | None = None, edge: Edge | None = None, relatedTypes: list[TypeBasic] | None = None, orientation: str | None = None, series: str | None = None, commemoratedTopic: str | None = None)[source]

Bases: TypeBase

Full type details including physical specifications.

commemorated_topic: str | None
comments: str | None
property comments_rendered: str | None

Return terminal-safe scrubbed comments.

Comments field may contain HTML with line feeds, links, images, and formatting. This computed field scrubs HTML artifacts for clean terminal display with Rich markup.

Returns:

Scrubbed comments ready for terminal rendering, or None if no comments

Return type:

str | None

composition: Composition | None
demonetization: Demonetization | None
edge: Edge | None
issue_terms: IssueTerms | None
issuer: Issuer
issuing_entity: dict[str, Any] | None
mints: list[Mint] | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

obverse: Obverse | None
orientation: str | None
property orientation_symbol: str | None

Return symbol representation of orientation.

Returns ⇈ (upup arrows) for medal, ⇅ (updown arrows) for coin, or None.

classmethod preprocess_data(data: Any) Any[source]

Preprocess API data to normalize nested structures.

printers: list[Printer] | None
references: list[Reference] | None
related_types: list[TypeBasic] | None
render_detail(cache_indicator: str = '') Any[source]

Render detailed type information using theme-aware, vertical scrolling layout.

Parameters:

cache_indicator (str) – Cache indicator (e.g., “💾” for cached, “🌐” for fresh)

Returns:

Group of Rich panels for display

Return type:

Any

reverse: Reverse | None
rulers: list[Ruler] | None
secondary_issuing_entity: dict[str, Any] | None
series: str | None
shape: str | None
size: float | None
size2: float | None
tags: list[str] | None
technique: Technique | None
thickness: float | None
type: str | None
url: HttpUrl
value: CurrencyValue | None
watermark: Watermark | None
weight: float | None
class numistalib.models.types.Watermark(*, engravers: list[str] | None = None, designers: list[str] | None = None, description: str | None = None, lettering: str | None = None, letteringScripts: list[LetteringScript] | None = None, picture: AnyUrl, thumbnail: AnyUrl, pictureCopyright: str | None = None, pictureCopyrightUrl: AnyUrl | None = None, pictureLicenseName: str | None = None, pictureLicenseUrl: AnyUrl | None = None, letteringTranslation: str | None = None, unabridgedLegend: str | None = None)[source]

Bases: SideBase

Watermark specifications for banknotes.

Extends SideBase with all standard side fields (engravers, designers, description, lettering, picture, etc.) for watermark representation.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Catalogues

Numista catalogues models.

Pydantic models for Numista reference catalogues.

class numistalib.models.catalogues.Catalogue(*, id: Annotated[int, Gt(gt=0)], code: Annotated[str, MaxLen(max_length=50)], title: Annotated[str, MaxLen(max_length=1000)], author: Annotated[str | None, MaxLen(max_length=500)] = None, publisher: Annotated[str | None, MaxLen(max_length=500)] = None, isbn13: str | None = None)[source]

Bases: NumistaBaseModel

Reference catalogue information.

Maps to Numista catalogue entity (e.g., KM, Krause).

author: str | None
code: str
property display_label: str

Formatted label with code and title.

isbn13: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

numista_id: int
publisher: str | None
classmethod render_table(items: list[Self], title: str = '') Table[source]

Generate table for catalogue list.

Parameters:
  • items (list[Self]) – List of Catalogue instances

  • title (str) – Table title

Returns:

Rich table with catalogue information

Return type:

Table

title: str
to_dict() dict[str, object][source]

Return a compact dict representation used by tests.

Includes only core identifying fields and omits optional metadata.

Issuers

Numista issuer import model.

Minimal Pydantic model for importing issuers from Numista API listings. Aligns with the subset of fields required for the coinlib issuer table (country_code, name_en, code, numista_id).

class numistalib.models.issuer.Issuer(*, code: Annotated[str, MaxLen(max_length=100)], name: Annotated[str, MaxLen(max_length=255)], flag: str | None = None, wikidataId: str | None = None, level: Annotated[int | None, Ge(ge=1)] = None, parentCode: Annotated[str | None, MaxLen(max_length=100)] = None, parentName: Annotated[str | None, MaxLen(max_length=255)] = None)[source]

Bases: NumistaBaseModel

Issuing country or territory record from Numista.

Represents a country, territory, or entity that issues coins, banknotes, or exonumia. Supports recurse, hierarchical relationships.

Parameters:
  • code (str) – Slug/short code (primary key, max 100 chars)

  • name (str) – Display name (max 255 chars)

  • flag (str) – URL to flag image

  • wikidata_id (str | None) – Optional Wikidata identifier for cross-reference

  • level (int) – Hierarchy level (1=country, 2+=subdivision)

  • parent_code (str | None) – Parent issuer code if nested (optional)

  • parent_name (str | None) – Parent issuer name if nested (optional)

  • raw (dict) – Original API payload

Raises:

ValidationError – If required fields missing or invalid types

Examples

>>> issuer = Issuer(
...     code="split_notgeld",
...     name="Split, City of",
...     flag="https://en.numista.com/design/pays/yugoslavia_notgeld.gif",
...     wikidata_id="Q1663",
...     level=3,
...     parent_code="yugoslavia_notgeld",
...     parent_name="Yugoslavia Notgeld",
...     raw={}
... )
>>> print(f"{issuer.name} (level {issuer.level})")
Split, City of (level 3)
code: str
flag: str | None
level: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
parent_code: str | None
parent_name: str | None
classmethod render_table(items: list[Self], title: str = '') Table[source]

Generate table for issuer list.

Parameters:
  • items (list[Self]) – List of Issuer instances

  • title (str) – Table title

Returns:

Rich table with issuer information

Return type:

Table

to_dict() dict[str, object][source]

Return a compact dict representation for Issuer used by tests.

wikidata_id: str | None

Issues

Numista issues models.

Pydantic models for Numista coin issues (specific years/mints of a type).

class numistalib.models.issues.Issue(*, numistaId: int, typeId: int, isDated: bool, year: int | None = None, gregorianYear: int | None = None, minYear: int | None = None, maxYear: int | None = None, mintLetter: ~typing.Annotated[str | None, ~annotated_types.MaxLen(max_length=10)] = None, marks: list[~numistalib.models.issues.Mark] = <factory>, signatures: list[~numistalib.models.issues.Signature] = <factory>, mintage: int | None = None, references: list[~numistalib.models.references.Reference] = <factory>, comment: str | None = None)[source]

Bases: NumistaBaseModel

Coin issue (specific year/mint of a type).

Maps to Numista issue entity. Issues represent specific mintings of a type with particular year, mint mark, or variety.

Parameters:
  • numista_id (int) – Numista issue ID (unique identifier)

  • type_id (int) – Parent type ID

  • is_dated (bool) – Whether issue has a visible date on the coin

  • year (int | None) – Year visible on coin (optional)

  • gregorian_year (int | None) – Gregorian calendar year (optional)

  • mint_letter (str | None) – Mint mark or letter (max 10 chars, optional)

  • mintage (int | None) – Number of coins minted (optional)

  • comment (str | None) – Additional notes or variety information (optional)

  • raw (dict) – Original API payload

Raises:

ValidationError – If required fields missing or invalid types

Examples

>>> issue = Issue(
...     numista_id=123456,
...     type_id=95420,
...     is_dated=True,
...     year=1622,
...     gregorian_year=1622,
...     mint_letter="D",
...     mintage=50000,
...     raw={}
... )
>>> print(f"{issue.year} {issue.mint_letter}")
1622 D
comment: str | None
gregorian_year: int | None
is_dated: bool
marks: list[Mark]
max_year: int | None
min_year: int | None
mint_letter: str | None
mintage: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

numista_id: int
references: list[Reference]
classmethod render_table(items: list[Self], title: str = '') Table[source]

Generate table for issue list.

Parameters:
  • items (list[Self]) – List of Issue instances

  • title (str) – Table title

Returns:

Rich table with issue information

Return type:

Table

signatures: list[Signature]
type_id: int
year: int | None
class numistalib.models.issues.IssueTerms(*, isIssued: bool, issueDate: date | None = None)[source]

Bases: NumistaBaseModel

Terms related to a coin issue.

Parameters:
  • is_issued (bool) – Whether the issue was officially issued

  • issue_date (date | None) – Official issue date (optional)

Raises:

ValidationError – If required fields missing or invalid types

Examples

>>> terms = IssueTerms(
...     is_issued=True,
...     issue_date=date(1973, 1, 1)
... )
>>> print(terms.is_issued)
True
is_issued: bool
issue_date: date | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod parse_partial_date(v: Any) date | None[source]

Handle partial dates with 00 day or month and various formats.

class numistalib.models.issues.IssuingEntity(*, numista_id: int, name: str, wikidataId: str | None = None)[source]

Bases: NumistaBaseModel

Entity responsible for issuing a coin.

Parameters:
  • id (int) – Unique identifier for the issuing entity

  • name (str) – Name of the issuing entity

  • wikidata_id (str | None) – Optional Wikidata identifier

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
wikidata_id: str | None
property wikidata_url: HttpUrl | None

Computed Wikidata URL from wikidata_id.

Returns:

Full Wikidata URL if wikidata_id present, else None.

Return type:

HttpUrl | None

class numistalib.models.issues.Mark(*, markId: int, title: str | None = None, picture: HttpUrl | None = None, letters: str | None = None)[source]

Bases: NumistaBaseModel

Mint mark, privy mark, or die mark on a coin.

Parameters:
  • mark_id (int) – Unique ID of the mark

  • title (str | None) – Title/name of the mark (optional)

  • picture (HttpUrl | None) – URL to picture of the mark (optional)

  • letters (str | None) – Letters of the mark (optional)

Notes

Marks either have a picture or letters, not both.

letters: str | None
mark_id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

picture: HttpUrl | None
title: str | None
class numistalib.models.issues.Signature(*, signerName: str, signerTitle: str | None = None)[source]

Bases: NumistaBaseModel

Signature on a banknote.

Parameters:
  • signer_name (str) – Name of the person who signed

  • signer_title (str | None) – Job title of the person who signed (optional)

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

signer_name: str
signer_title: str | None

Mints

Numista mints models.

Pydantic models for Numista mint facilities.

class numistalib.models.mints.Mint(*, numista_id: Annotated[int, Gt(gt=0)], name: Annotated[str, MaxLen(max_length=255)], localName: Annotated[str | None, MaxLen(max_length=255)] = None, code: Annotated[str | None, MaxLen(max_length=50)] = None, place: Annotated[str | None, MaxLen(max_length=255)] = None, country: Issuer | None = None, startYear: int | None = None, endYear: int | None = None, nomismaId: Annotated[str | None, MaxLen(max_length=100)] = None, wikidataId: Annotated[str | None, MaxLen(max_length=100)] = None, countryCode: Annotated[str | None, MaxLen(max_length=50)] = None)[source]

Bases: NumistaBaseModel

Mint facility information.

Maps to Numista mint entity.

Parameters:
  • id (int) – Numista mint ID

  • name (str) – Mint name in chosen language

  • local_name (str | None) – Mint name in local language (optional)

  • code (str | None) – Mint code or abbreviation (optional)

  • place (str | None) – Place where mint is located (optional)

  • country (Issuer | None) – Country issuer information (optional)

  • start_year (int | None) – First year of operation (optional)

  • end_year (int | None) – Last year of operation, 9999=still active (optional)

  • nomisma_id (str | None) – Nomisma identifier (optional)

  • wikidata_id (str | None) – Wikidata identifier (optional)

  • country_code (str | None) – Issuing country code - deprecated, use country.code (optional)

code: str | None
country: Issuer | None
country_code: str | None
end_year: int | None
id: int
local_name: str | None
property mint_identifier: str

Mint code if available, otherwise name.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
nomisma_id: str | None
place: str | None
render_compact() str[source]

Render compact mint display.

classmethod render_table(items: list[Self], title: str = '') Table[source]

Generate table for mint list.

Parameters:
  • items (list[Self]) – List of Mint instances

  • title (str) – Table title

Returns:

Rich table with mint information

Return type:

Table

start_year: int | None
wikidata_id: str | None

Collections

Numista collections models.

Pydantic models for Numista user collections.

class numistalib.models.collections.CollectedItem(*, id: int, quantity: int, type: TypeDetail, forSwap: bool, issue: dict[str, object] | None = None, grade: Literal['g', 'vg', 'f', 'vf', 'xf', 'au', 'unc'] | None = None, privateComment: str | None = None, publicComment: str | None = None, price: dict[str, object] | None = None, collection: UserCollection | None = None, pictures: list[Picture] | None = None, storageLocation: str | None = None, acquisitionPlace: str | None = None, acquisitionDate: date | None = None, serialNumber: str | None = None, internalId: str | None = None, weight: float | None = None, size: float | None = None, axis: Annotated[int | None, Ge(ge=1), Le(le=12)] = None, gradingDetails: GradingDetails | None = None)[source]

Bases: NumistaBaseModel

Item in a user’s collection.

Maps to Numista collected_item entity with full swagger specification.

Parameters:
  • id (int) – Unique ID of the item

  • quantity (int) – Quantity of items

  • type (TypeDetail) – Type details (id, title, category, issuer)

  • for_swap (bool) – Available for swap

  • issue (dict | None) – Issue information (full issue object)

  • grade (Literal | None) – Grade (g, vg, f, vf, xf, au, unc)

  • private_comment (str | None) – Private comment (auth required)

  • public_comment (str | None) – Public comment

  • price (dict | None) – Price object reference

  • collection (UserCollection | None) – Parent collection reference

  • pictures (list[Picture] | None) – Pictures or PDF documents

  • storage_location (str | None) – Storage location

  • acquisition_place (str | None) – Acquisition place

  • acquisition_date (date_type | None) – Date acquired (YYYY-MM-DD)

  • serial_number (str | None) – Serial number

  • internal_id (str | None) – Internal ID

  • weight (float | None) – Weight in grams

  • size (float | None) – Size in millimeters

  • axis (int | None) – Die axis (1-12, h notation)

  • grading_details (GradingDetails | None) – Professional grading information

acquisition_date: date | None
acquisition_place: str | None
axis: int | None
collection: UserCollection | None
for_swap: bool
grade: Literal['g', 'vg', 'f', 'vf', 'xf', 'au', 'unc'] | None
grading_details: GradingDetails | None
id: int
internal_id: str | None
issue: dict[str, object] | None
property issue_id: int | None

Extract issue ID from issue object.

property item_summary: str

Summary of collected item.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

pictures: list[Picture] | None
price: dict[str, object] | None
private_comment: str | None
public_comment: str | None
quantity: int
serial_number: str | None
size: float | None
storage_location: str | None
type: TypeDetail
property type_id: int

Extract type ID from type object.

weight: float | None
class numistalib.models.collections.GradingCompany(*, id: int, name: str)[source]

Bases: NumistaBaseModel

Grading company information.

Parameters:
  • id (int) – ID of the grading service in Numista

  • name (str) – Name of the grading service

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class numistalib.models.collections.GradingDesignation(*, id: int, value: str)[source]

Bases: NumistaBaseModel

Grading designation.

Parameters:
  • id (int) – ID of the grading designation in Numista

  • value (str) – Value of the grading designation

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

value: str
class numistalib.models.collections.GradingDetails(*, gradingCompany: GradingCompany | None = None, slabGrade: SlabGrade | None = None, slabNumber: str | None = None, cacSticker: Literal['Green', 'Gold'] | None = None, gradingDesignations: list[GradingDesignation] | None = None, gradingStrike: GradingStrike | None = None, gradingSurface: GradingSurface | None = None)[source]

Bases: NumistaBaseModel

Professional grading details.

Parameters:
  • grading_company (GradingCompany | None) – Grading service information

  • slab_grade (SlabGrade | None) – Slab grade information

  • slab_number (str | None) – Slab number

  • cac_sticker (Literal[``”Green”, ``"Gold"] | None) – CAC sticker type

  • grading_designations (list[GradingDesignation] | None) – List of grading designations

  • grading_strike (GradingStrike | None) – Grading strike information

  • grading_surface (GradingSurface | None) – Grading surface information

cac_sticker: Literal['Green', 'Gold'] | None
grading_company: GradingCompany | None
grading_designations: list[GradingDesignation] | None
grading_strike: GradingStrike | None
grading_surface: GradingSurface | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

slab_grade: SlabGrade | None
slab_number: str | None
class numistalib.models.collections.GradingStrike(*, id: int, value: str)[source]

Bases: NumistaBaseModel

Grading strike information.

Parameters:
  • id (int) – ID of the grading strike in Numista

  • value (str) – Value of the grading strike

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

value: str
class numistalib.models.collections.GradingSurface(*, id: int, value: str)[source]

Bases: NumistaBaseModel

Grading surface information.

Parameters:
  • id (int) – ID of the grading surface in Numista

  • value (str) – Value of the grading surface

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

value: str
class numistalib.models.collections.Picture(*, url: HttpUrl, thumbnailUrl: HttpUrl)[source]

Bases: NumistaBaseModel

Picture or PDF document.

Parameters:
  • url (HttpUrl) – URL to the picture or document in original size

  • thumbnail_url (HttpUrl) – URL to the thumbnail

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

thumbnail_url: HttpUrl
url: HttpUrl
class numistalib.models.collections.SlabGrade(*, id: int, value: str)[source]

Bases: NumistaBaseModel

Slab grade information.

Parameters:
  • id (int) – ID of the grading mark in Numista

  • value (str) – Value of the grading mark

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

value: str
class numistalib.models.collections.TypeDetail(*, id: int, title: str, category: Literal['coin', 'banknote', 'exonumia'], issuer: dict[str, str] | None = None)[source]

Bases: NumistaBaseModel

Type detail for collected items.

Parameters:
  • id (int) – ID of the type

  • title (str) – Title of the type

  • category (Literal[``”coin”, ``"banknote", "exonumia"]) – Category

  • issuer (dict | None) – Issuer information (code, name)

category: Literal['coin', 'banknote', 'exonumia']
id: int
issuer: dict[str, str] | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

title: str
class numistalib.models.collections.UserCollection(*, numista_id: Annotated[int, Gt(gt=0)], name: str)[source]

Bases: NumistaBaseModel

User-defined collection container.

Represents a named collection that groups collected items for a user.

id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
to_dict() dict[str, object][source]

Convert collection to dictionary representation.

Literature

Numista literature models.

Pydantic models for Numista numismatic literature catalogue.

class numistalib.models.literature.Contributor(*, role: Literal['author', 'editor', 'translator'], name: str, id: int | None = None)[source]

Bases: NumistaBaseModel

Publication contributor information.

Parameters:
  • role (Literal[``”author”, ``"editor", "translator"]) – Contributor’s role

  • name (str) – Full name of the contributor

  • id (int | None) – Unique ID of the person in Numista

id: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
role: Literal['author', 'editor', 'translator']
class numistalib.models.literature.PartOf(*, type: Literal['volume_group', 'volume', 'article_group'], id: str, title: str, volumeNumber: str | None = None)[source]

Bases: NumistaBaseModel

Parent publication reference.

Parameters:
  • type (Literal[``”volume_group”, ``"volume", "article_group"]) – Type of parent publication

  • id (str) – Unique ID of the parent publication

  • title (str) – Title of the parent publication

  • volume_number (str | None) – Number or specific title the volume has within its volume group

id: str
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

title: str
type: Literal['volume_group', 'volume', 'article_group']
volume_number: str | None
class numistalib.models.literature.Publication(*, id: str, type: Literal['volume', 'article', 'volume_group', 'article_group'], title: str | None = None, url: HttpUrl | None = None, translatedTitle: str | None = None, volumeNumber: str | None = None, subtitle: str | None = None, translatedSubtitle: str | None = None, edition: str | None = None, languages: list[str] | None = None, year: int | None = None, pageCount: int | None = None, pages: str | None = None, cover: Literal['softcover', 'hardcover', 'spiral', 'hidden_spiral'] | None = None, isbn10: str | None = None, isbn13: str | None = None, issn: str | None = None, oclcNumber: str | None = None, contributors: list[Contributor] | None = None, publishers: list[Publisher] | None = None, publicationPlaces: list[PublicationPlace] | None = None, partOf: list[PartOf] | None = None, bibliographicalNotice: str | None = None, homepageUrl: HttpUrl | None = None, downloadUrls: list[HttpUrl] | None = None)[source]

Bases: NumistaBaseModel

Bibliographic publication record.

Represents a volume (book), article (authored book chapter), series of books (volume_group), or series of articles (article_group).

Parameters:
  • id (str) – Numista publication ID

  • type (Literal[``”volume”, ``"article", "volume_group", "article_group"]) – Type of publication

  • title (str) – Publication title

  • url (HttpUrl | None) – URL of the publication entry

  • translated_title (str | None) – Title translated into English

  • volume_number (str | None) – Volume number within group (volumes only)

  • subtitle (str | None) – Subtitle (volumes only)

  • translated_subtitle (str | None) – Subtitle translated into English (volumes only)

  • edition (str | None) – Edition information (volumes only)

  • languages (list[str] | None) – ISO 639 (alpha-2) language codes

  • year (int | None) – Publication year (for volumes and articles)

  • page_count (int | None) – Total number of pages (volumes only)

  • pages (str | None) – Page range (articles only)

  • cover (Literal[``”softcover”, ``"hardcover", "spiral", "hidden_spiral"] | None) – Type of cover (volumes only)

  • isbn10 (str | None) – ISBN-10 code (volumes only)

  • isbn13 (str | None) – ISBN-13 code (volumes only)

  • issn (str | None) – ISSN code (volume groups only)

  • oclc_number (str | None) – OCLC catalogue number

  • contributors (list[Contributor] | None) – List of contributors (authors, editors, translators)

  • publishers (list[Publisher] | None) – Information about the publishers (volumes only)

  • publication_places (list[PublicationPlace] | None) – Places where the volume was released (volumes only)

  • part_of (list[PartOf] | None) – Parent publication(s) this belongs to

  • bibliographical_notice (str | None) – HTML-formatted bibliographical notice

  • homepage_url (HttpUrl | None) – URL of the website representing the publication

  • download_urls (list[HttpUrl] | None) – URLs where the publication can be downloaded

Examples

>>> pub = Publication(
...     id="456",
...     type="volume",
...     title="Standard Catalog of World Coins",
...     year=2024,
...     isbn13="978-1234567890",
...     contributors=[
...         Contributor(role="author", name="George S. Cuhaj", id=123)
...     ]
... )
>>> print(f"{pub.title} ({pub.year})")
Standard Catalog of World Coins (2024)
bibliographical_notice: str | None
contributors: list[Contributor] | None
cover: Literal['softcover', 'hardcover', 'spiral', 'hidden_spiral'] | None
download_urls: list[HttpUrl] | None
edition: str | None
homepage_url: HttpUrl | None
id: str
isbn10: str | None
isbn13: str | None
issn: str | None
languages: list[str] | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

oclc_number: str | None
page_count: int | None
pages: str | None
part_of: list[PartOf] | None
publication_places: list[PublicationPlace] | None
publishers: list[Publisher] | None
subtitle: str | None
title: str | None
translated_subtitle: str | None
translated_title: str | None
type: Literal['volume', 'article', 'volume_group', 'article_group']
url: HttpUrl | None
volume_number: str | None
year: int | None
class numistalib.models.literature.PublicationPlace(*, name: str, geonamesId: str | None = None)[source]

Bases: NumistaBaseModel

Publication place information.

Parameters:
  • name (str) – City and country of publication

  • geonames_id (str | None) – GeoNames ID for location reference

geonames_id: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class numistalib.models.literature.Publisher(*, name: str, id: int | None = None)[source]

Bases: NumistaBaseModel

Publisher information.

Parameters:
  • name (str) – Name of the publisher

  • id (int | None) – Unique ID of the publisher in Numista

id: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str

Prices

Numista prices models.

Pydantic models for Numista price estimates.

class numistalib.models.prices.Price(*, issueId: Annotated[int, Gt(gt=0)], grade: Annotated[str, MaxLen(max_length=10)], currency: Annotated[str, MaxLen(max_length=3)], value: Annotated[float, Ge(ge=0)])[source]

Bases: NumistaBaseModel

Price estimate for a specific issue and grade.

Maps to Numista price data.

currency: str
property formatted_price: str

Price with currency code.

grade: str
issue_id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod render_table(items: list[Self], title: str = '') Table[source]

Generate table for price list.

Parameters:
  • items (list[Self]) – List of Price instances

  • title (str) – Table title

Returns:

Rich table with price information

Return type:

Table

value: float

Users

Numista users models.

Pydantic models for Numista user profiles.

class numistalib.models.users.User(*, id: Annotated[int, Gt(gt=0)], username: Annotated[str, MaxLen(max_length=100)], avatar: HttpUrl | None = None, countryCode: Annotated[str | None, MaxLen(max_length=10)] = None, memberSince: str | None = None)[source]

Bases: NumistaBaseModel

Numista user profile information.

Maps to Numista user entity.

Parameters:
  • numista_id (int) – Numista user ID

  • username (str) – Unique username

  • avatar (HttpUrl | None) – URL to avatar picture (optional)

  • country_code (str | None) – ISO country code (optional, not in swagger)

  • member_since (str | None) – Registration date (optional, not in swagger)

avatar: HttpUrl | None
country_code: str | None
member_since: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

numista_id: int
to_dict() dict[str, object][source]

Convert user to dictionary representation.

property user_profile: str

Formatted user profile.

username: str

Currency

Numista currency models.

Pydantic models for Numista currency information.

class numistalib.models.currency.Currency(*, id: Annotated[int, Gt(gt=0)], code: Annotated[str | None, MaxLen(max_length=10)] = None, name: Annotated[str, MaxLen(max_length=255)], fullName: Annotated[str, MaxLen(max_length=255)], symbol: Annotated[str | None, MaxLen(max_length=10)] = None)[source]

Bases: NumistaBaseModel

Currency information.

Maps to Numista currency entity referenced in type details.

Parameters:
  • numista_id (int) – Numista currency ID

  • code (str) – ISO 4217 currency code (max 10 chars)

  • full_name (str) – Full currency name (max 255 chars)

  • symbol (str | None) – Currency symbol (optional)

Examples

>>> currency = Currency(
...     numista_id=123,
...     code="USD",
...     full_name="United States Dollar",
...     symbol="$"
... )
>>> print(f"{currency.symbol} {currency.full_name}")
$ United States Dollar
code: str | None
property display_format: str

Format currency with symbol if available.

full_name: str
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
numista_id: int
symbol: str | None

References

Numista reference and localized label models.

Pydantic models for reference catalogues and multilingual labels.

class numistalib.models.references.Catalogue(*, id: int, code: Annotated[str, MaxLen(max_length=50)])[source]

Bases: NumistaBaseModel

Catalogue information.

Parameters:
  • id (int) – Numista catalogue ID

  • code (str) – Catalogue code identifier

code: str
id: int
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class numistalib.models.references.LocalizedLabel(*, language: Annotated[str, MaxLen(max_length=2)], label: Annotated[str, MaxLen(max_length=500)])[source]

Bases: NumistaBaseModel

Localized text label.

Maps to Numista localized_label schema for multilingual content.

Parameters:
  • language (str) – ISO 639-1 language code (2 chars)

  • label (str) – Localized text content (max 500 chars)

Examples

>>> label_en = LocalizedLabel(language="en", label="United States")
>>> label_es = LocalizedLabel(language="es", label="Estados Unidos")
>>> print(f"{label_en.language}: {label_en.label}")
en: United States
label: str
language: str
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class numistalib.models.references.Reference(*, catalogue: Catalogue, number: Annotated[str, MaxLen(max_length=100)], url: HttpUrl | None = None)[source]

Bases: NumistaBaseModel

Reference catalogue information.

Parameters:
  • catalogue (Catalogue) – Catalogue details with ID and code

  • number (str) – Reference number in catalogue

  • url (HttpUrl | None) – External URL to reference (optional)

catalogue: Catalogue
property display_reference: str

Formatted catalogue reference.

classmethod handle_catalogue_formats(data: Any) Any[source]

Handle both string and object formats for catalogue field.

API inconsistency: Some endpoints return catalogue as string (code only), others return nested object with id and code. This validator normalizes both.

model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

number: str
render_compact() str[source]

Render compact reference display.

classmethod render_table(items: list[Self], title: str = '') Table[source]

Generate table for reference list with proper None handling.

Parameters:
  • items (list[Self]) – List of Reference instances

  • title (str) – Table title

Returns:

Rich table with catalogue, number, and URL columns

Return type:

Table

url: HttpUrl | None

Errors

Numista error models.

Pydantic models for Numista API error responses.

class numistalib.models.errors.ErrorResponse(*, errorMessage: str)[source]

Bases: NumistaBaseModel

API error response.

Maps to Numista error schema from API responses.

Parameters:

error_message (str) – Human-readable error description

Examples

>>> error = ErrorResponse(error_message="Invalid API key")
>>> print(error.error_message)
Invalid API key
error_message: str
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Updates

Numista update models.

Pydantic models for Numista API write operations (POST/PATCH).

class numistalib.models.updates.IssueUpdate(*, isDated: bool, year: int | None = None, gregorianYear: int | None = None, mintLetter: Annotated[str | None, MaxLen(max_length=10)] = None, mintage: int | None = None, comment: str | None = None)[source]

Bases: NumistaBaseModel

Issue creation/update payload.

Maps to Numista issue_update schema for POST/PATCH operations.

Parameters:
  • is_dated (bool) – Whether issue has a visible date

  • year (int | None) – Year visible on coin (optional)

  • gregorian_year (int | None) – Gregorian calendar year (optional)

  • mint_letter (str | None) – Mint mark (optional)

  • mintage (int | None) – Number minted (optional)

  • comment (str | None) – Additional notes (optional)

Examples

>>> update = IssueUpdate(
...     is_dated=True,
...     year=2024,
...     gregorian_year=2024,
...     mint_letter="P",
...     mintage=1000000
... )
>>> print(f"{update.year} {update.mint_letter}")
2024 P
comment: str | None
gregorian_year: int | None
is_dated: bool
mint_letter: str | None
mintage: int | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

to_dict() dict[str, object][source]

Convert update to dictionary representation.

Returns:

Dictionary representation excluding None values

Return type:

dict[str, object]

year: int | None
class numistalib.models.updates.TypeSideUpdate(*, engravers: list[str] | None = None, description: str | None = None, lettering: str | None = None)[source]

Bases: NumistaBaseModel

Type side (obverse/reverse) update payload.

Maps to Numista type_side_update schema for editing coin sides.

Parameters:
  • engravers (list[str] | None) – List of engraver names (optional)

  • description (str | None) – Side description (optional)

  • lettering (str | None) – Side lettering/inscription (optional)

Examples

>>> side = TypeSideUpdate(
...     engravers=["John Doe", "Jane Smith"],
...     description="National emblem",
...     lettering="E PLURIBUS UNUM"
... )
>>> print(side.engravers)
['John Doe', 'Jane Smith']
description: str | None
engravers: list[str] | None
lettering: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property panel_template: str

Return formatted panel content for type side update display.

to_dict() dict[str, object][source]

Convert update to dictionary representation.

Returns:

Dictionary representation excluding None values

Return type:

dict[str, object]

class numistalib.models.updates.TypeUpdate(*, title: Annotated[str, MaxLen(max_length=500)], category: Annotated[str, MaxLen(max_length=50)], issuerCode: Annotated[str | None, MaxLen(max_length=100)] = None, valueText: Annotated[str | None, MaxLen(max_length=100)] = None, valueNumeric: float | None = None, currencyCode: Annotated[str | None, MaxLen(max_length=10)] = None, composition: Annotated[str | None, MaxLen(max_length=500)] = None, weight: float | None = None, diameter: float | None = None, thickness: float | None = None, obverseDescription: str | None = None, obverseLettering: str | None = None, reverseDescription: str | None = None, reverseLettering: str | None = None)[source]

Bases: NumistaBaseModel

Type creation/update payload.

Maps to Numista type_update schema for POST/PATCH operations.

Parameters:
  • title (str) – Type title (max 500 chars)

  • category (str) – Category: coin, banknote, or exonumia

  • issuer_code (str | None) – Issuer code (optional)

  • value_text (str | None) – Face value as text (optional)

  • value_numeric (float | None) – Numeric face value (optional)

  • currency_code (str | None) – ISO 4217 currency code (optional)

  • composition (str | None) – Metal composition (optional)

  • weight (float | None) – Weight in grams (optional)

  • diameter (float | None) – Diameter in mm (optional)

  • thickness (float | None) – Thickness in mm (optional)

  • obverse_description (str | None) – Obverse description (optional)

  • obverse_lettering (str | None) – Obverse lettering (optional)

  • reverse_description (str | None) – Reverse description (optional)

  • reverse_lettering (str | None) – Reverse lettering (optional)

Examples

>>> update = TypeUpdate(
...     title="1 Dollar",
...     category="coin",
...     issuer_code="usa",
...     composition="Silver",
...     weight=26.73
... )
>>> print(update.title)
1 Dollar
category: str
composition: str | None
currency_code: str | None
diameter: float | None
issuer_code: str | None
model_config: ClassVar[ConfigDict] = {'alias_generator': <function to_camel>, 'arbitrary_types_allowed': False, 'extra': 'forbid', 'frozen': False, 'populate_by_name': True, 'strict': True, 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

obverse_description: str | None
obverse_lettering: str | None
reverse_description: str | None
reverse_lettering: str | None
thickness: float | None
title: str
to_dict() dict[str, object][source]

Convert update to dictionary representation.

Returns:

Dictionary representation excluding None values

Return type:

dict[str, object]

value_numeric: float | None
value_text: str | None
weight: float | None