# EPREL integration (v2) Descrybe enriches processed products with EU **EPREL** (European Product Registry for Energy Labelling) data when a registration ID is present on the feed item. ## How it works 1. **Feed sync / mapping** stores product fields in `raw_products.mapped_data` / `raw_data`. Vendor XML often includes an empty or populated `` (also `eprel_id`, `eprelId`, …). 2. **Processing worker** runs the canonical steps: `normalize` → `parse_specs` → `fill_fields` → **`eprel`** → `ai_enhance` (optional). When `EPREL_ENABLED=true`, the `eprel` step: - Discovers an ID via `eprel.ExtractID(normalized, mapped, raw)` (same key variants as legacy: `EPRELID`, `eprel_id`, …). - Calls the public EPREL HTTP API (`internal/eprel.Client` / `Fetcher` interface) with a hard timeout and bounded response body. - Merges results into `processed_products.attributes` and `processed_attributes` as: - Flat keys: `eprel_id`, `eprel_label` / `eprel_label_url`, `eprel_pdf` / `eprel_pdf_url`, `eprel_energy_class`, `eprel_energy_scale` - Nested object: `eprel: { id, label, pdf?, energy_class?, energy_scale? }` - Also records a compact `field_sources.eprel` / step log entry. 3. **Export XML/CSV** resolves those keys (and aliases like `energy_class`, `eprel_label_url`) through the export template `source` field. Map them in the export feed builder like any other attribute. EPREL failures are **soft**: the product still completes; a truncated note may appear in `gpt_response.steps` for the `eprel` step. No API keys or Authorization headers are written to logs. ## Configuration Set on the **worker** process (enrichment runs during `ProcessJob`): | Variable | Default | Purpose | |---|---|---| | `EPREL_ENABLED` | `false` | Turn on enrichment | | `EPREL_TIMEOUT` | `10s` | HTTP client timeout (`10s`, `500ms`, or integer seconds `10`) | | `EPREL_BASE_URL` | `https://eprel.ec.europa.eu/api` | Override for tests/proxies | | `EPREL_FICHE_LANGUAGE` | `EN` | Language for product fiche PDF | | `EPREL_API_KEY` | _(empty)_ | Optional `X-API-KEY` if your deployment requires a whitelisted key — **never log** | Example: ```bash EPREL_ENABLED=true EPREL_TIMEOUT=10s EPREL_FICHE_LANGUAGE=EN ``` ## Public API calls (per product) For registration id `{id}`: - Label URL (constructed): `{base}/product/{id}/labels?format=png` - Fiche: `GET {base}/product/{id}/fiches?noRedirect=true&language={lang}` → PDF path - Info: `GET {base}/product/{id}` → `energyClass`, `energyClassRange` / `energyScale` ## Export mapping examples Template field sources that work out of the box: - `eprel_id` - `eprel_label` / `eprel_label_url` - `eprel_pdf` / `eprel_pdf_url` - `eprel_energy_class` / `energy_class` - `eprel_energy_scale` / `energy_scale` - `attr.eprel_id` (generic attribute path) ## Package layout - `apps/api/internal/eprel` — `Fetcher` interface, HTTP `Client`, ID normalize/extract, `MergeInto` - `apps/api/internal/processing` — Engine step `eprel` (`StepEPREL`) after fill_fields - `apps/api/internal/feeds` — export source aliases for EPREL fields - `apps/api/cmd/worker` — sets `Engine.EPREL` from config when enabled Processing type aliases: `eprel` / `eprel_only` run normalize + eprel only. ## Tests ```bash cd apps/api go test ./internal/eprel/ ./internal/processing/ ./internal/feeds/ ./internal/config/ go build ./... ```