Classification API Data Format
Relevant source files
The following files were used as context for generating this wiki page:
The Classification API provides a standardized data format for beverage categorization within the CellarNode platform. It defines a hierarchical structure of categories and subtypes, enabling consistent label mapping, formatting, and display across various client applications. This data format serves as the backbone for utilities that resolve ambiguous identifiers into human-readable labels.
Sources: README.md:3-5, src/types.ts:1-18
API Endpoints and Data Retrieval
Classification data is retrieved from the CellarNode public API via a standard GET request. The utility libraries (React, Vue, and Angular adapters) use TanStack Query to fetch this data and cache it indefinitely, as beverage classifications are considered stable and rarely change.
Primary Endpoint
GET /api/v1/classifications/beverage-types
Sources: README.md:144-148, src/react/use-beverage-label-map.ts:10-14
Data Retrieval Flow
The following sequence diagram illustrates how framework adapters fetch and process the API data using the internal buildLabelMap utility.
Data Schema
The API response follows a specific TypeScript interface structure defined in the core library. The top-level object contains a list of beverage categories, each containing its own metadata and nested subtypes.
Entity Relationship Model
The relationship between categories and subtypes is a one-to-many hierarchy.
Sources: src/types.ts:1-18
Field Definitions
| Interface | Field | Type | Description |
|---|---|---|---|
BeverageClassification | categories | BeverageCategory[] | Array of top-level beverage categories. |
BeverageCategory | id | string | Unique slug identifier (e.g., "wine"). |
BeverageCategory | name | string | Display name (e.g., "Still Wine"). |
BeverageCategory | hsHeading | string | (Optional) Harmonized System code heading. |
BeverageCategory | subtypes | BeverageSubtype[] | Array of specific subtypes within the category. |
BeverageSubtype | id | string | Unique slug identifier within its category context. |
BeverageSubtype | name | string | Display name (e.g., "Red Wine"). |
BeverageSubtype | oivType | string | (Optional) OIV classification type code. |
Sources: src/types.ts:1-18, README.md:151-166
Internal Label Mapping Logic
To resolve potential ID collisions (e.g., the subtype "red" existing under both "Still Wine" and "Sparkling Wine"), the utility converts the API response into a LabelMap.
Map Key Generation
The buildLabelMap function generates three types of keys for every classification:
- Category ID: Maps category slugs to names (e.g.,
"wine" -> "Still Wine"). - Subtype ID: Maps subtype slugs to names. Note that last-write-wins if IDs are duplicated across categories.
- Composite Key: Maps a combined
category:subtypeslug to the subtype name (e.g.,"wine:red" -> "Red Wine").
Sources: src/label-map.ts:5-14, README.md:31-45
Sources: src/label-map.ts:5-14
Data Normalization
Input data often requires normalization before it can be reliably compared against classification IDs or resolved to codes. The normalizeToken and resolveCountryCode utilities handle these transformations.
Normalization Rules
- Case/Accent: Strings are converted to NFD normalization, diacritics are removed, and text is lowercased.
- Whitespace: Spaces and underscores are collapsed into single hyphens.
- Volume Parsing: Free-text volumes (e.g., "750ml", "20 hl", "bottles 750ml x 4000") are parsed into a standard Liter format.
Sources: src/normalize.ts:7-15, src/normalize.ts:88-115
Volume Parsing Logic
| Input Format | Internal Processing | Output (Liters) |
|---|---|---|
| Bare Number | 330 -> 330 | 330.0 |
| Standard Units | 5 kL -> 5 * 1000 | 5000.0 |
| Metric Sub-units | 750 ml -> 750 * 0.001 | 0.75 |
| Bottle Multiplier | 750ml x 4000 -> 0.75 * 4000 | 3000.0 |
Sources: src/normalize.ts:117-142
Summary
The Classification API Data Format ensures that beverage data remains deterministic and human-readable across the CellarNode ecosystem. By utilizing hierarchical structures, composite keys for disambiguation, and robust normalization for free-text inputs, the system provides a reliable bridge between raw API data and user-facing interfaces.
Sources: README.md:27-30, src/normalize.ts:1-6