# Nyilvános API-végpontok

> A Haszno által hitelesítési adatok nélkül kiszolgált összes végpont teljes referenciája.

> [!NOTE]
> A Haszno API fejlesztői előzetesben van. A `https://haszno.com` hosztolt demójából visszakapott összes adat **szintetikus mintaadat**, hacsak nem jelezzük másképp. A null-szemantikáról, pénznemről és időbélyeg-formátumokról lásd a [Konvenciók](conventions.md) oldalt.

## Összefoglalás

Az alábbi táblázatban szereplő összes végpont hívható a `https://haszno.com` alap URL-en `Authorization` fejléc vagy egyéb hitelesítési adat nélkül. A hitelesítési adatokat igénylő végpontokhoz lásd a [Védett végpontok](protected-endpoints.md) oldalt.

| Metódus | Útvonal | Visszaad |
|---------|---------|---------|
| GET | `/api/health` | Életjelzés-ellenőrzés |
| GET | `/api/geo` | Látogató országa és javasolt felhasználói felület nyelve |
| GET | `/api/categories` | Kategória-taxonómia termékszámokkal |
| GET | `/api/products` | Termékkatalógus árazással és piaci adatokkal |
| GET | `/api/products/supplier-counts` | Termékszám beszállítónként |
| GET | `/api/suppliers` | Konfigurált beszállítólista |
| GET | `/api/stats` | Irányítópult összefoglaló-számok |
| GET | `/api/settings` | Aktív árazási szabályok |
| GET | `/api/impact` | Haszon-mérő: a Hasznónak tulajdonított extra nyereség |
| GET | `/api/orders` | Utolsó 50 rendelés (demóban üres tömb) |
| GET | `/api/proposals` | Árjavaslatok (demóban üres tömb) |
| GET | `/api/peers/invites` | Társ meghívókódok (demóban üres tömb) |
| GET | `/api/peers/links` | Létrejött társ-összekapcsolások (demóban üres tömb) |
| GET | `/api/import-list` | Importlista-tételek |
| GET | `/api/blog` | Közzétett piaci elemzések (valódi adat) |
| GET | `/api/blog/:slug` | Egyetlen közzétett bejegyzés (valódi adat) |
| GET | `/api/blog/rss.xml` | Bejegyzések RSS-feedje |
| GET | `/api/blog/feed.json` | Bejegyzések JSON-feedje |
| GET | `/llms.txt` | LLM által olvasható webhely-összefoglaló |

---

## Rendszer

### GET /api/health

Életjelzési mutatót ad vissza. Ezzel ellenőrizheted, hogy az API elérhető-e, mielőtt más kéréseket küldesz.

**Nyilvános** **Csak olvasás**

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/health
```

**Válasz (200)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `ok` | boolean | Mindig `true`, ha a szerver üzemel. |

```json
{"ok":true}
```

---

### GET /api/geo

Visszaadja a látogató országkódját és a javasolt felhasználói felület nyelvét. Az ország az élhálózat által beállított kérésfejlécekből kerül meghatározásra (`x-vercel-ip-country` vagy `cf-ipcountry`). Az API-szerver soha nem tárolja és nem naplózza az IP-címeket.

**Nyilvános** **Csak olvasás**

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/geo
```

**Válasz (200)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `country` | string \| null | Kétbetűs ISO 3166-1 országkód, vagy `null`, ha az ország nem állapítható meg. |
| `lang` | `"hu"` \| `"en"` | Javasolt felhasználói felület nyelve: `"hu"` Magyarországra vagy ismeretlen esetére, `"en"` minden más országra. |

```json
{"country":"HU","lang":"hu"}
```

> [!NOTE]
> Erre a válaszra `Cache-Control: private, no-store` van beállítva; ne tárold gyorsítótárban közös rétegen.

---

## Demó-katalógusadatok

Az alábbi végpontok **szintetikus mintaadatot** adnak vissza. A választörzsben szerepel `"demo": true`, ahol értelmezhető. A `partnerCount` a demóban mindig `0` — valódi beszállítók nincsenek csatlakoztatva.

---

### GET /api/categories

Visszaadja a termékek rendszerezéséhez használt teljes kategória-taxonómiát. Minden bejegyzés tartalmazza a demó adathalmazra vonatkozó darabszámokat.

**Nyilvános** **Csak olvasás**

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/categories
```

**Válasz (200)**

Kategória-objektumok tömbjét adja vissza. Mindig mind a 14 kategóriát visszaadja; szűrés és lapozás nincs.

| Mező | Típus | Leírás |
|------|-------|--------|
| `key` | string | Belső kategóriakulcs, amelyet szűrőparaméterekben használhatsz, pl. `"kert"`. |
| `label` | string | Magyar megjelenítési név, pl. `"Kert és növény"`. |
| `emoji` | string | Kategória emoji-ikonja. |
| `partnerCount` | integer | Valódi csatlakoztatott beszállítók száma. A demóban mindig `0`. |
| `exampleCount` | integer | Demó/minta-beszállítók száma. |
| `productCount` | integer | Az összes beszállítóra vetített termékek száma a kategóriában. |

```json
[
  {
    "key": "auto",
    "label": "Autó, gumi és motor",
    "emoji": "🛞",
    "partnerCount": 0,
    "exampleCount": 1,
    "productCount": 100
  },
  {
    "key": "kert",
    "label": "Kert és növény",
    "emoji": "🌿",
    "partnerCount": 0,
    "exampleCount": 1,
    "productCount": 100
  }
]
```

**Megjegyzések**

- `partnerCount: 0` a demóban várt érték — nincsenek valódi csatlakoztatott beszállítók.
- A `key` értéket add meg a `cats` paraméterben, ha termékeket vagy statisztikákat szűrsz.

---

### GET /api/products

Visszaadja a termékkatalógust bruttó árakkal, nettó bekerülési árakkal, piaci árak összehasonlításával és árazási javaslatokkal. Ez az integrációs munka fő olvasási végpontja.

**Nyilvános** **Csak olvasás**

> [!NOTE]
> A demó csak szintetikus termékeket ad vissza. A `sku` értékek `DEMO-{id}` mintát követnek. A piaci árak `"source": "mock"` mezőt tartalmaznak. Az árazási paraméterek (`undercutPct`, `minMarginPct`, `vatPct`) elfogadottak, de nem maradnak meg — csak az aktuális választ befolyásolják.

**Paraméterek**

| Név | Hol | Típus | Kötelező | Alapértelmezés | Leírás |
|-----|-----|-------|----------|----------------|--------|
| `cats` | query | vesszővel elválasztott string | Nem | (mind) | Belefoglalandó kategóriakulcsok, pl. `kert,sport`. |
| `supplier` | query | vesszővel elválasztott egész számok | Nem | (mind) | Belefoglalandó beszállítóazonosítók. |
| `all` | query | `"1"` | Nem | kihagyva | Csak valódi példányon; a demó figyelmen kívül hagyja. Ha `"1"`-re van állítva, belefoglalja a csak katalógusban szereplő (nem listázott) termékeket is. |
| `shippingMarkets` | query | vesszővel elválasztott ISO 3166-1 alpha-2 | Nem | `HU` | Csak demóban. Országok, amelyekhez piaci árak összehasonlítását kéred. Érvényes értékek: `HU SK DE AT CZ PL RO`. Valódi példány a bolt elmentett `shippingMarkets` beállítását használja. |
| `undercutPct` | query | szám | Nem | `1` | Csak demóban. Az ajánlott ár kiszámításakor a piaci minimum aluli %-os aláígérés mértéke. Nem marad meg. |
| `minMarginPct` | query | szám | Nem | `10` | Csak demóban. Az árazási motor által érvényesített minimális nettó haszonkulcs %-ban. Nem marad meg. |
| `vatPct` | query | szám | Nem | `27` | Csak demóban. A `recommended` bruttó/nettó átváltásához használt áfakulcs. Nem marad meg. |

**Kérés**

```bash
curl --fail-with-body \
  'https://haszno.com/api/products?cats=kert&shippingMarkets=HU,SK'
```

**Válasz (200)**

Tömböt ad vissza. Minden elem egy terméket képvisel.

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Belső termékazonosító. |
| `sku` | string | Beszállítói SKU. A demóban `DEMO-{id}`. |
| `name` | string | Terméknév (magyarul). |
| `supplierId` | integer | Beszállítóazonosító. |
| `supplierName` | string | Beszállító megjelenítési neve. |
| `category` | string | Kategóriakulcs (megfelel a `GET /api/categories` végpontnak). |
| `costNet` | integer (HUF) | Nettó nagykereskedelmi bekerülési ár ÁFA nélkül. |
| `priceGross` | integer (HUF) | Jelenlegi bruttó eladási ár ÁFÁ-val. |
| `rrpGross` | integer \| null | Beszállító ajánlott fogyasztói ára, bruttó. `null`, ha nem adta meg. |
| `marketMinGross` | integer \| null | Legolcsóbb bruttó ár a figyelt piacokon. `null`, ha nincs adat. |
| `marketShop` | string \| null | A legolcsóbb ajánlatot kínáló bolt neve. |
| `stock` | integer | Elérhető készletegységek száma. |
| `listed` | boolean | Aktívan listázott-e a termék. |
| `example` | boolean | Demó/minta-beszállítói termékek esetén `true`. Csak valódi példányokon van jelen; a szintetikus demóválaszból hiányzik. |
| `current` | object | `{marginNet, marginPct}` — haszon a jelenlegi áron; mindkettő `null`, ha a `costNet` ismeretlen. |
| `recommended` | object | Árazási javaslat — lásd az almezőket alább. |
| `marketByCountry` | object | Rögzített kulcsok: `hu`, `sk` és `eu`. Minden slot: piaci ajánlat objektum vagy `null`. |
| `bestMarket` | object \| null | `{market, ratio}`: az a piac (`"hu"`, `"sk"` vagy `"eu"`), ahol a `minGross / priceGross` arány a legnagyobb; 1 feletti `ratio` azt jelenti, hogy a bolt ott már most a legolcsóbb. A demóban mindig `null`. |
| `markets` | array | Piaci ajánlat rekordok: a demóban kért országonként egy, valódi példányon piaconként (`hu`, `sk`, `eu`) egy, ha van áradat. |
| `trendKeyword` | string \| null | Magyar trendkereső kulcsszó a termékhez. Csak valódi példányokon van jelen; a szintetikus demóválaszból hiányzik. |
| `trendKeywordEn` | string \| null | Angol trendkulcsszó. Csak valódi példányokon van jelen; a szintetikus demóválaszból hiányzik. |
| `updatedAt` | ISO-8601 string \| null | Utolsó frissítés időbélyege. Csak valódi példányokon van jelen; a szintetikus demóválaszból hiányzik. |

**A `recommended` almezői**

| Mező | Típus | Leírás |
|------|-------|--------|
| `priceGross` | integer (HUF) | Javasolt bruttó eladási ár. |
| `floorGross` | integer (HUF) | A legalacsonyabb bruttó ár, amely még megtartja a `minMarginPct` haszonkulcsot; `0`, ha a `costNet` ismeretlen. A képletet a [Konvenciók](conventions.md#currency) oldal tartalmazza. |
| `marginNet` | integer (HUF) \| null | Nettó haszon az ajánlott áron. `null`, ha a `costNet` ismeretlen. |
| `marginPct` | number \| null | Haszonkulcs az ajánlott áron. `null`, ha a `costNet` ismeretlen. |
| `status` | string | Árazási állapot — lásd az enumot alább. |

**A `recommended.status` enum értékei**

| Érték | Jelentés |
|-------|---------|
| `"versenykepes"` | Versenyképes — van ismert piaci ár, és az ajánlott ár `undercutPct`-vel alá megy (90 Ft-ra végződő árra kerekítve), miközben nem esik a `floorGross` alá. |
| `"nem_versenykepes"` | Nem versenyképes — a piaci ár alá menni sértené a minimális haszonkulcsot, ezért az ajánlott ár a `floorGross` marad. |
| `"nincs_piaci_ar"` | Nincs ismert piaci ár. Az ajánlott ár a `rrpGross`, ha az eléri a `floorGross` értéket, különben a `floorGross`. |
| `"nincs_besz_ar"` | A beszerzési ár (`costNet`) ismeretlen, ezért árjavaslat nem készíthető: a `priceGross` a jelenlegi ár marad, a `floorGross` `0`, a `marginNet` és a `marginPct` pedig `null`. |

**Piaci ajánlat objektum (minden slot a `marketByCountry`-ban és minden elem a `markets`-ben)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `market` | string | Piackulcs: `"hu"`, `"sk"` vagy `"eu"`. |
| `country` | string \| null | A legolcsóbb ajánlat kétbetűs ISO-országkódja, például `"DE"` az `eu` piacon. |
| `minGross` | integer (HUF) | Ezen a piacon talált legolcsóbb bruttó ár. |
| `shop` | string | A legolcsóbb ajánlat boltjának neve. |
| `url` | string \| null | A legolcsóbb listázás URL-je. A demóban `null`. |
| `source` | string | Adatforrás: `"dataforseo"` vagy `"mock"`. A demóban mindig `"mock"`. |
| `fetchedAt` | ISO-8601 string | A piaci ár lekérdezésének időpontja. |
| `isCheapest` | boolean | Ez a piac kínálja-e az összességében legolcsóbb ajánlatot. |

A demó mindkét helyen ezt a teljes objektumot adja vissza. Valódi példányon a `marketByCountry` slotjaiban nincs `market` és `isCheapest` mező, a `markets` elemeiben pedig nincs `fetchedAt`.

```json
{
  "id": 101,
  "category": "kert",
  "supplierId": 2,
  "sku": "DEMO-101",
  "name": "Kerti napernyő · 1. változat",
  "supplierName": "Példa-partner · Kert és növény",
  "costNet": 1121,
  "priceGross": 2190,
  "rrpGross": 2190,
  "marketMinGross": 2124,
  "marketShop": "Példa-bolt · HU",
  "stock": 0,
  "listed": true,
  "current": {"marginNet": 603, "marginPct": 35},
  "recommended": {
    "priceGross": 2090,
    "floorGross": 1590,
    "status": "versenykepes",
    "marginNet": 525,
    "marginPct": 31.9
  },
  "marketByCountry": {
    "hu": {
      "market": "hu",
      "country": "HU",
      "minGross": 2124,
      "shop": "Példa-bolt · HU",
      "url": null,
      "source": "mock",
      "fetchedAt": "2026-11-10T00:00:00.000Z",
      "isCheapest": true
    },
    "sk": {
      "market": "sk",
      "country": "SK",
      "minGross": 2650,
      "shop": "Példa-bolt · SK",
      "url": null,
      "source": "mock",
      "fetchedAt": "2026-11-10T00:00:00.000Z",
      "isCheapest": false
    },
    "eu": null
  },
  "bestMarket": null,
  "markets": [
    {"market":"hu","country":"HU","minGross":2124,"shop":"Példa-bolt · HU",
     "url":null,"source":"mock","fetchedAt":"2026-11-10T00:00:00.000Z","isCheapest":true},
    {"market":"sk","country":"SK","minGross":2650,"shop":"Példa-bolt · SK",
     "url":null,"source":"mock","fetchedAt":"2026-11-10T00:00:00.000Z","isCheapest":false}
  ]
}
```

**Megjegyzések**

- Az árak `null` értéke ismeretlen vagy nem elérhető adatot jelent, nem nullát.
- `source: "mock"` a piaci árakon azt jelenti, hogy az ár nem ellenőrzött, élő piaci eredmény.
- A nyilvános demóban a `current.marginPct` rögzített helyőrző érték (`35`), amely nem az árakból következik, a `current.marginNet` viszont számított érték: `round(priceGross / 1.27 − costNet)`, mindig 27 %-os áfával. Csak a `recommended` követi az `undercutPct`, `minMarginPct` és `vatPct` paramétert.
- Egyetlen tömbben adja vissza az összes egyező terméket. Ezen a végponton nincs lapozás.

---

### GET /api/products/supplier-counts

Visszaadja a termékek számát beszállítónként. Hasznos a teljes katalógus betöltése nélküli beszállítói bontás megjelenítéséhez.

**Nyilvános** **Csak olvasás**

**Paraméterek**

A demóban ugyanazok a szűrőparaméterek, mint a `GET /api/products` esetén: `cats`, `supplier`. Valódi példány ezeket figyelmen kívül hagyja, és minden beszállító listázott termékeit megszámolja.

**Kérés**

```bash
curl --fail-with-body 'https://haszno.com/api/products/supplier-counts?cats=kert'
```

**Válasz (200)**

Tömböt ad vissza. Csak azok a beszállítók szerepelnek, amelyeknek legalább egy egyező termékük van.

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Beszállítóazonosító. |
| `name` | string | Beszállító megjelenítési neve. |
| `count` | integer | Szűrőnek megfelelő termékek száma. |

```json
[
  {"id": 2, "name": "Példa-partner · Kert és növény", "count": 100}
]
```

---

### GET /api/suppliers

Visszaadja a boltban konfigurált beszállítók listáját. A demóban szintetikus minta-beszállítókat ad vissza.

**Nyilvános** **Csak olvasás**

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/suppliers
```

**Válasz (200)**

Beszállítóobjektumok tömbjét adja vissza.

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Beszállítóazonosító. |
| `name` | string | Beszállító megjelenítési neve. |
| `category` | string | Elsődleges kategóriakulcs. |
| `visibility` | string | `"private"` vagy `"network"`. |
| `network` | boolean | A beszállító tagja-e a megosztott hálózatnak. |
| `orderMode` | string | Rendelések továbbításának módja (pl. `"email"`). |
| `email` | string \| null | Beszállító kapcsolattartási e-mail-címe, vagy `null`. |

```json
[
  {
    "id": 1,
    "name": "Példa-partner · Autó, gumi és motor",
    "category": "auto",
    "visibility": "private",
    "network": false,
    "orderMode": "email",
    "email": null
  }
]
```

---

### GET /api/stats

Visszaadja az irányítópult összefoglaló-számait. Ezeket az opcionális szűrőknek megfelelő összes terméken számítja ki.

**Nyilvános** **Csak olvasás**

**Paraméterek**

| Név | Hol | Típus | Kötelező | Alapértelmezés | Leírás |
|-----|-----|-------|----------|----------------|--------|
| `cats` | query | vesszővel elválasztott string | Nem | (mind) | Szűrés kategóriakulcsok szerint. |
| `supplier` | query | vesszővel elválasztott egész számok | Nem | (mind) | Szűrés beszállítóazonosítók szerint. |

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/stats
```

**Válasz (200)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `products` | integer | Aktívan listázott termékek száma. |
| `losing` | integer | Negatív nettó haszonnal rendelkező termékek száma a jelenlegi áron. |
| `overMarket` | integer | A legolcsóbb ismert versenytárs fölé árazott termékek száma. |
| `toFix` | integer | Termékek száma, ahol a jelenlegi ár eltér az ajánlott ártól. |
| `orders` | integer | Összes rendelés száma (nem időablakos). |

```json
{"products":1400,"losing":0,"overMarket":1400,"toFix":1400,"orders":0}
```

**Megjegyzések**

- `orders: 0` a demóban várt érték — valódi rendelések nem léteznek.
- `overMarket: 1400` a demóban azt tükrözi, hogy mind az 1 400 szintetikus termék a (szintetikus) piaci minimumuk felett van árazva.

---

### GET /api/settings

Visszaadja a bolt aktuális árazási szabálykonfigurációját.

**Nyilvános** **Csak olvasás**

> [!NOTE]
> A demóválasz tartalmazza `"demo": true` és `"automationPaused": true` mezőket. Az itt megjelenő `undercutPct`, `minMarginPct` és `vatPct` mezők a demóban csak olvashatók; valódi példányon a `PUT /api/settings` végponton írhatod felül őket.

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/settings
```

**Válasz (200)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Mindig `1`. A beállítások boltonként egyediek (singleton). A hosztolt demóválaszból hiányzik. |
| `undercutPct` | number | Az ajánlott ár kiszámításakor a piaci minimum alatti %-os aláígérés mértéke. |
| `minMarginPct` | number | Az árpadló kiszámításakor érvényesített minimális nettó haszonkulcs %-ban. |
| `vatPct` | number | Minden bruttó/nettó átváltásnál alkalmazott áfakulcs. |
| `shippingMarkets` | string[] | ISO-országkódok, amelyekre piaci árakat figyel a rendszer. |
| `automationPaused` | boolean | Szüneteltetett-e az automatizálási motor. |
| `shopId` | integer \| null | A tulajdonos bolt. Csak valódi példányon van jelen. |
| `demo` | boolean | A hosztolt demóban jelen van és értéke `true`. |

```json
{
  "undercutPct": 1,
  "minMarginPct": 10,
  "vatPct": 27,
  "shippingMarkets": ["HU"],
  "automationPaused": true,
  "demo": true
}
```

---

### GET /api/impact

Visszaadja a Haszno átárazási és új termékfelvételi motorjának tulajdonított extra nyereséget egy beállítható időablakra vetítve.

**Nyilvános** **Csak olvasás**

> [!NOTE]
> A demóértékek szintetikus rendeléselőzményből számítódnak. Az `arfutarImpact` meghaladhatja a `profitNet` értékét a demóban — ez várható, ha az attribúciós képlet szintetikus adatokat használó hipotetikus alapszinttel hasonlít.

**Paraméterek**

| Név | Hol | Típus | Kötelező | Alapértelmezés | Leírás |
|-----|-----|-------|----------|----------------|--------|
| `days` | query | egész szám 1–365 | Nem | `30` | Attribúciós időablak napokban, visszaszámolva a jelen pillanattól. |
| `cats` | query | vesszővel elválasztott string | Nem | (mind) | Szűkítés ezekre a kategóriakulcsokra. |

**Kérés**

```bash
curl --fail-with-body 'https://haszno.com/api/impact?days=30'
```

**Válasz (200)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `days` | integer | Kért időablak hossza. |
| `from` | ISO-8601 string | Időablak kezdete. |
| `to` | ISO-8601 string | Időablak vége. |
| `orders` | integer | Rendelések száma az időablakon belül. |
| `revenueGross` | integer (HUF) | Teljes bruttó bevétel az időablakban. |
| `profitNet` | integer (HUF) | Teljes nettó nyereség az időablak összes rendelésére vetítve. |
| `arfutarImpact` | integer (HUF) | A Hasznónak tulajdonított extra nyereség (`fromRepricing` és `fromNewProducts` összege). |
| `fromRepricing` | integer (HUF) | Átárazott termékekből eredő hatás. |
| `fromNewProducts` | integer (HUF) | Újonnan felvett termékekből eredő hatás. |
| `lossProductsFixed` | integer | Átárazással javított veszteséges termékek száma. |
| `autoForwardedOrders` | integer | Automatikusan továbbított vagy teljesített rendelések száma. |
| `minutesPerOrder` | number | Rendelésenként megbecsült megspórolt kézi percek száma. |
| `items` | array | Termékenként bontott attribúció — lásd az almezőket alább. |
| `demo` | boolean | A hosztolt demóban jelen van és értéke `true`. |

**Az `items` almezői**

| Mező | Típus | Leírás |
|------|-------|--------|
| `productId` | integer | Termékazonosító. |
| `name` | string | Terméknév. |
| `kind` | string | `"arazas"` (átárazás) vagy `"felvetel"` (új felvétel). |
| `oldPriceGross` | integer (HUF) \| null | Bruttó ár a változás előtt. Új felvételeknél `null`. |
| `newPriceGross` | integer (HUF) | Bruttó ár a változás után. |
| `unitsBeforePerDay` | number | Átlagos napi eladott mennyiség a régi áron, a változás előtt. |
| `unitsAfter` | integer | A változás után az attribúciós időablakon belül eladott összes egység. |
| `actualProfit` | integer (HUF) | Tényleges nettó nyereség a változás utáni eladásokból. |
| `expectedProfit` | integer (HUF) | Várható alapnyereség a régi áron és a régi eladási ütemben. Új felvételeknél `0`. |
| `impact` | integer (HUF) | Ennek a terméknek tulajdonított nyereséghatás (`actualProfit − expectedProfit`). `0`, ha `insufficientHistory` értéke `true`. |
| `insufficientHistory` | boolean | `true`, ha nincs elegendő rendeléselőzmény a megbízható számításhoz. Az ilyen tételek nem szerepelnek az összesítésekben. |

```json
{
  "days": 30,
  "from": "2026-10-13T14:08:40.424Z",
  "to": "2026-11-12T14:08:40.424Z",
  "orders": 80,
  "revenueGross": 383700,
  "profitNet": 92996,
  "arfutarImpact": 110647,
  "fromRepricing": 66658,
  "fromNewProducts": 43989,
  "lossProductsFixed": 2,
  "autoForwardedOrders": 64,
  "minutesPerOrder": 6,
  "items": [
    {
      "productId": 3,
      "name": "Ablaktörlő · 1. változat",
      "kind": "felvetel",
      "oldPriceGross": null,
      "newPriceGross": 3990,
      "unitsBeforePerDay": 0,
      "unitsAfter": 40,
      "actualProfit": 43989,
      "expectedProfit": 0,
      "impact": 43989,
      "insufficientHistory": false
    }
  ],
  "demo": true
}
```

---

### GET /api/orders

Visszaadja az utolsó 50 rendelést, legújabbtól a legrégebbiig. A nyilvános demó üres tömböt ad vissza.

**Nyilvános** **Csak olvasás**

> [!NOTE]
> A hosztolt demóban `[]`-t ad vissza. Nyilvános hozzáféréshez nem generálódnak szintetikus rendelések. Valódi példányon `items` és `events` tömböt tartalmazó rendelésobjektumokat ad vissza.

**Paraméterek**

A demóban nincsenek. Valódi példány elfogadja a `cats` paramétert (vesszővel elválasztott kategóriakulcsok): ekkor csak azokat a rendeléseket adja vissza, amelyekben van legalább egy tétel ezekből a kategóriákból.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/orders
```

**Válasz (200)**

Rendelésobjektumok tömbjét adja vissza (a demóban üres), a legújabbal kezdve. Minden valódi rendelés tartalmazza: `id`, `externalId`, `customerName`, `customerEmail`, `address`, `status`, `supplierOrderId`, `trackingNumber`, `totalGross` (HUF), `events` (tömb: `{at, text}`), `createdAt`, `forwardingStartedAt`, `shopId` és `items` (tömb: `{orderId, qty, priceGross, name, sku}`).

```json
[]
```

---

### GET /api/proposals

Visszaadja az árazási motor által generált árjavaslatokat. A nyilvános demó üres tömböt ad vissza.

**Nyilvános** **Csak olvasás**

> [!NOTE]
> A hosztolt demóban `[]`-t ad vissza.

**Paraméterek**

A demóban nincsenek. Valódi példány elfogadja a `status` (alapértelmezés: `pending`), a `limit` (alapértelmezés 50, legfeljebb 200) és a `cats` paramétert.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/proposals
```

**Válasz (200)**

Árjavaslat-objektumok tömbjét adja vissza (a demóban üres). Minden elem: `id`, `productId`, `productName`, `productSku`, `productImage`, `supplierName`, `oldPriceGross`, `proposedPriceGross`, `reason`, `source`, `status` (`"pending"`, `"approved"`, `"rejected"`, `"rolled_back"`, `"stale"`), `batchId`, `createdAt`, `decidedAt`.

```json
[]
```

---

### GET /api/peers/invites

Visszaadja a bolt kimenő társ-meghívókódjait. A nyilvános demó üres tömböt ad vissza.

**Nyilvános** **Csak olvasás**

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/peers/invites
```

**Válasz (200)**

Meghívóobjektumok tömbjét adja vissza (a demóban üres). Minden elem: `id`, `code`, `createdBy`, `supplierId`, `supplierName`, `expiresAt`, `acceptedBy`, `acceptedAt`, `revokedAt`, `createdAt`.

```json
[]
```

---

### GET /api/peers/links

Visszaadja a boltok közötti létrejött társ-összekapcsolásokat. A nyilvános demó üres tömböt ad vissza.

**Nyilvános** **Csak olvasás**

**Paraméterek**

Nincsenek.

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/peers/links
```

**Válasz (200)**

Összekapcsolás-objektumok tömbjét adja vissza (a demóban üres). Minden elem: `id`, `supplierId`, `partner`, `createdAt`, `supplierName`, `supplierCategory`.

```json
[]
```

---

### GET /api/import-list

Visszaadja az importlistát — a partnerkatalógusból kiválasztott, csatlakoztatott webshopba való feltöltés előtt álló termékeket.

**Nyilvános** **Csak olvasás**

**Paraméterek**

| Név | Hol | Típus | Kötelező | Alapértelmezés | Leírás |
|-----|-----|-------|----------|----------------|--------|
| `status` | query | string | Nem | (mind) | Szűrés állapot szerint: `varakozik` (várakozik), `feltoltve` (feltöltve a shopba), `elvetve` (elvetve). |
| `q` | query | string | Nem | — | Kis- és nagybetű-érzéketlen részsztring-keresés a terméknévre (valódi példányon a kategóriára is). |

**Kérés**

```bash
curl --fail-with-body 'https://haszno.com/api/import-list?status=varakozik'
```

**Válasz (200)**

Importlista-tételek tömbjét adja vissza.

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Importlista-bejegyzés azonosítója. |
| `addedAt` | ISO-8601 string | A tétel listára kerülésének időpontja. |
| `status` | string | `"varakozik"`, `"feltoltve"` vagy `"elvetve"`. |
| `note` | string \| null | Importáláskor hozzáadott opcionális megjegyzés. |
| `pushedProductId` | integer \| null | A feltöltéskor létrehozott bolt-termékazonosító. |
| `networkProduct` | object | A forrás katalógustermék — lásd az almezőket alább. |

**A `networkProduct` almezői**

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Katalógustermék azonosítója. |
| `name` | string | Terméknév. |
| `imageUrl` | string \| null | Termékkép URL-je. |
| `sku` | string | Beszállítói SKU. |
| `wholesaleNet` | integer (HUF) \| null | Nettó nagykereskedelmi bekerülési ár. |
| `rrpGross` | integer (HUF) \| null | Beszállító ajánlott fogyasztói ára. |
| `stock` | integer | Elérhető készlet. |
| `category` | string | Kategória megjelenítési neve (magyar felirat, pl. `"Kert és növény"`). |
| `supplierName` | string | Beszállító megjelenítési neve. |
| `example` | boolean | Demó/minta-tételeknél `true`. |
| `marginNet` | integer (HUF) \| null | Nettó haszon az ajánlott fogyasztói áron: `round(rrpGross / (1 + vatPct / 100) − wholesaleNet)`. `null`, ha valamelyik ár ismeretlen. |
| `marginPct` | number \| null | Haszonkulcs az ajánlott fogyasztói áron. A nyilvános demóban ugyanaz a rögzített helyőrző érték (`35`), mint a `GET /api/products` `current.marginPct` mezője. |

```json
[
  {
    "id": 1,
    "addedAt": "2026-11-10T08:00:00.000Z",
    "status": "varakozik",
    "note": null,
    "pushedProductId": null,
    "networkProduct": {
      "id": 1,
      "name": "Autós telefontartó · 1. változat",
      "imageUrl": null,
      "sku": "DEMO-1",
      "wholesaleNet": 1019,
      "rrpGross": 1990,
      "stock": 0,
      "category": "Autó, gumi és motor",
      "supplierName": "Példa-partner · Autó, gumi és motor",
      "example": true,
      "marginNet": 548,
      "marginPct": 35
    }
  }
]
```

---

## Blog és piaci elemzések

A blog-végpontok **valódi adatot** adnak vissza — összesített (anonimizált, legalább 5 boltból) trendadatokból generált, közzétett piaci elemzés bejegyzéseket. Ezekben a válaszokban nem szerepel `"demo": true` jelölő.

---

### GET /api/blog

Visszaadja az összes közzétett piaci elemzés bejegyzést, legújabbtól a legrégebbiig.

**Nyilvános** **Csak olvasás**

**Paraméterek**

| Név | Hol | Típus | Kötelező | Alapértelmezés | Leírás |
|-----|-----|-------|----------|----------------|--------|
| `page` | query | egész szám ≥ 1 | Nem | `1` | Oldalszám. |
| `period` | query | `"het"` \| `"honap"` | Nem | (mind) | Szűkítés heti (`"het"`) vagy havi (`"honap"`) bejegyzésekre. |

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/blog
```

**Válasz (200)**

| Mező | Típus | Leírás |
|------|-------|--------|
| `posts` | array | Közzétett bejegyzés-összefoglalók — lásd az elemet alább. |
| `total` | integer | A szűrőnek megfelelő közzétett bejegyzések teljes száma. |
| `page` | integer | Aktuális oldalszám. |
| `perPage` | integer | Rögzített oldalméret (mindig `10`). |

**Bejegyzés-elem mezői**

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Bejegyzésazonosító. |
| `slug` | string | URL-slug, amelyet a `GET /api/blog/:slug` végponton használhatsz. |
| `period` | `"het"` \| `"honap"` | Összesítési periódus típusa: `"het"` = heti, `"honap"` = havi. |
| `periodStart` | ISO-8601 dátumstring | Az összesítési időablak kezdete (pl. `"2026-11-02"`). |
| `periodEnd` | ISO-8601 dátumstring | Az összesítési időablak vége (pl. `"2026-11-08"`). |
| `title` | string | Bejegyzés címe (magyarul). |
| `summary` | string | Rövid összefoglaló bekezdés. |
| `publishedAt` | ISO-8601 string | Közzététel időbélyege. |
| `coverImageUrl` | string \| null | Borítókép URL-je, vagy `null`. |

```json
{
  "posts": [
    {
      "id": 2,
      "slug": "2026-het45-toplista",
      "period": "het",
      "periodStart": "2026-11-02",
      "periodEnd": "2026-11-08",
      "title": "2026/45. hét — Legjobban fogyó termékek",
      "summary": "A 45. héten párásítók és LED-es világítástechnikai termékek forgalma emelkedett...",
      "publishedAt": "2026-11-09T08:00:00.000Z",
      "coverImageUrl": null
    }
  ],
  "total": 3,
  "page": 1,
  "perPage": 10
}
```

---

### GET /api/blog/:slug

Visszaad egy közzétett bejegyzést a slug alapján.

**Nyilvános** **Csak olvasás**

**Útvonalparaméterek**

| Név | Típus | Leírás |
|-----|-------|--------|
| `slug` | string | A bejegyzés slugja a `GET /api/blog` végpont `slug` mezőjéből. |

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/blog/2026-het45-toplista
```

**Válasz (200)**

Egyetlen bejegyzésobjektumot ad vissza. A listaelemekkel ellentétben nincs benne `coverImageUrl`.

| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | integer | Bejegyzésazonosító. |
| `slug` | string | URL-slug. |
| `period` | `"het"` \| `"honap"` | Összesítési periódus típusa: `"het"` = heti, `"honap"` = havi. |
| `periodStart` | ISO-8601 dátumstring | Az összesítési időablak kezdete. |
| `periodEnd` | ISO-8601 dátumstring | Az összesítési időablak vége. |
| `title` | string | Bejegyzés címe (magyarul). |
| `summary` | string | Rövid összefoglaló bekezdés. |
| `bodyMd` | string | A bejegyzés teljes tartalma Markdown formátumban. |
| `data` | object | A bejegyzés mögötti összesített adatok: `shopsCount`, `rankedProducts` és `rankedCategories`. Minden rangsorelemnek van `name`, `units`, `shopsCount` és opcionális `trend` (`"emelkedo"`, `"stabil"` vagy `"csokkeno"`) mezője; a rangsorolt termékeknek `imageUrl` is lehet. |
| `ogTitle` | string \| null | Open Graph-cím; `null` esetén a `title` érvényes. |
| `publishedAt` | ISO-8601 string \| null | Közzététel időbélyege. |
| `status` | string | Ezen a végponton mindig `"publikalt"` (közzétett). |
| `createdAt` | ISO-8601 string | A bejegyzés létrehozásának időpontja. |
| `updatedAt` | ISO-8601 string | A bejegyzés utolsó módosításának időpontja. |

Ha a slug után `.md` utótagot írsz (`/api/blog/2026-het45-toplista.md`), csak a `bodyMd` tartalmat kapod meg, `text/markdown; charset=utf-8` típussal.

**Hibaválaszok**

| Státusz | Mikor |
|---------|-------|
| 404 | A slug nem található, vagy a bejegyzés nincs közzétéve. |

---

### GET /api/blog/rss.xml

Visszaadja a közzétett bejegyzések RSS 2.0 feedjét. A válasz tartalomtípusa `application/rss+xml; charset=utf-8`.

**Nyilvános** **Csak olvasás**

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/blog/rss.xml
```

---

### GET /api/blog/feed.json

Visszaadja a közzétett bejegyzések JSON Feed (1.1-es verzió) feedjét. A válasz tartalomtípusa `application/feed+json; charset=utf-8`.

**Nyilvános** **Csak olvasás**

**Kérés**

```bash
curl --fail-with-body https://haszno.com/api/blog/feed.json
```

---

## Segédvégpontok

### GET /llms.txt

Visszaadja az [llms.txt](https://llmstxt.org/) konvenciót követő, LLM által olvasható webhely-összefoglalót. Tartalomtípus: `text/plain`.

**Nyilvános** **Csak olvasás**

**Kérés**

```bash
curl --fail-with-body https://haszno.com/llms.txt
```
