# Wine E-Label Compliance (https://eulabel.eu/docs/knowledge-base/guides/wine-e-label)

> Fetch the complete documentation index at: https://eulabel.eu/docs/llms.txt
> Use this file to discover all available pages before exploring further.
> Full content: https://eulabel.eu/docs/llms-full.txt
> Append .md to any page URL for markdown, or send Accept: text/markdown.



This guide walks you through creating a wine e-label that meets EU Regulation 2021/2117 requirements. By the end, your wine product will have a scannable QR code linking to a Digital Product Passport with all mandatory information.

> **Warning**
> EU Regulation 2021/2117 requires e-labels for wines produced and labelled after December 8, 2023. If you ship into multiple member states, your e-label must be available in the relevant languages.

At a glance [#at-a-glance]

* **Outcome**: a compliant e-label passport page + machine-readable dataset, reachable from a GS1 Digital Link QR code.
* **Time to first result**: \~10 minutes in sandbox, then production.
* **What you’ll submit**: ingredients, nutrition, allergens, origin, net content, alcohol by volume.

What's required [#whats-required]

- [Ingredients](#whats-required) — All additives and processing aids, with clear allergen disclosure
- [Nutrition](#nutrition-declaration-format) — Declared per 100 mL (energy, macros, salt, alcohol where applicable)
- [Allergens](#allergen-codes) — Sulphites, egg, fish, milk, and other Annex II allergens as applicable
- [Origin](#full-workflow) — Country, region, and designation (DOC/IGP) where applicable
- [Label outputs](#full-workflow) — QR code + passport page + structured compliance dataset
Full workflow [#full-workflow]

Register your product [#register-your-product]

    Create a product entry with your wine's GTIN barcode:

    
### CURL

```bash
export EULABEL_API_KEY="sk_test_..."

curl -X POST https://api.eulabel.eu/v1/products \
  -H "Authorization: Bearer $EULABEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Quinta dos Carvalhais Alfrocheiro 2019",
    "category": "wine",
    "brand": "Quinta dos Carvalhais",
    "gtin": "5601012012200"
  }'
```
### JavaScript

```javascript
const EULABEL_API_KEY = process.env.EULABEL_API_KEY;

const product = await fetch('https://api.eulabel.eu/v1/products', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${EULABEL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Quinta dos Carvalhais Alfrocheiro 2019',
    category: 'wine',
    brand: 'Quinta dos Carvalhais',
    gtin: '5601012012200',
  }),
}).then(r => r.json());
```
Save your `productId` [#save-your-productid]

    You’ll use the returned `productId` in the next steps:
```text
PRODUCT_ID=a1b2c3d4-...
```
Attach the e-label data [#attach-the-e-label-data]

    Submit the full passport payload with ingredients, nutrition, allergens, and origin:

    
### CURL

```bash
curl -X POST https://api.eulabel.eu/v1/passports \
  -H "Authorization: Bearer $EULABEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "a1b2c3d4-...",
    "data": {
      "productType": "wine",
      "colour": "red",
      "vintage": 2019,
      "alcoholByVolume": 14.0,
      "netContent": "750 mL",
      "ingredients": [
        "Grapes (Alfrocheiro)",
        "Sulphur Dioxide"
      ],
      "nutrition": {
        "energyKj": 351,
        "energyKcal": 84,
        "fatG": 0,
        "saturatedFatG": 0,
        "carbohydratesG": 0.6,
        "sugarsG": 0.3,
        "proteinG": 0.1,
        "saltG": 0,
        "alcoholG": 13.5
      },
      "allergens": {
        "containsSulphites": true,
        "containsEgg": false,
        "containsFish": false,
        "containsMilk": false,
        "containsCelery": false,
        "containsLupin": false
      },
      "origin": {
        "country": "PT",
        "region": "Dão",
        "designation": "Dão DOC"
      },
      "producers": [
        {
          "name": "Sogrape Vinhos S.A.",
          "role": "producer",
          "country": "PT"
        }
      ]
    }
  }'
```
### JavaScript

```javascript
const passport = await fetch('https://api.eulabel.eu/v1/passports', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${EULABEL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    productId: 'a1b2c3d4-...',
    data: {
      productType: 'wine',
      colour: 'red',
      vintage: 2019,
      alcoholByVolume: 14.0,
      netContent: '750 mL',
      ingredients: ['Grapes (Alfrocheiro)', 'Sulphur Dioxide'],
      nutrition: {
        energyKj: 351, energyKcal: 84,
        fatG: 0, saturatedFatG: 0,
        carbohydratesG: 0.6, sugarsG: 0.3,
        proteinG: 0.1, saltG: 0, alcoholG: 13.5,
      },
      allergens: {
        containsSulphites: true, containsEgg: false,
        containsFish: false, containsMilk: false,
        containsCelery: false, containsLupin: false,
      },
      origin: { country: 'PT', region: 'Dão', designation: 'Dão DOC' },
      producers: [{ name: 'Sogrape Vinhos S.A.', role: 'producer', country: 'PT' }],
    },
  }),
}).then(r => r.json());
```
Download the QR code [#download-the-qr-code]
```bash
curl https://api.eulabel.eu/v1/products/a1b2c3d4-.../qr \
  -H "Authorization: Bearer $EULABEL_API_KEY" \
  -o wine-label-qr.svg
```
    The QR code encodes a GS1 Digital Link URI (`https://eulabel.eu/01/05601012012200`). Print it on your wine label alongside the mandatory "e" symbol.
Verify the passport [#verify-the-passport]

    Scan the QR code or visit the URL directly. The passport page displays:

    * Ingredients list with allergen highlights
    * Nutrition table per 100 mL
    * Origin and producer information
    * Regulatory compliance badges
Nutrition declaration format [#nutrition-declaration-format]

All nutrition values are declared per **100 mL** for beverages:

> **Note**
> If you already store nutrition per serving, convert to per 100 mL before submitting. EUlabel validates required fields and returns actionable errors.

| Field            | Type   | Unit           | Required  |
| ---------------- | ------ | -------------- | --------- |
| `energyKj`       | number | kJ             | Yes       |
| `energyKcal`     | number | kcal           | Yes       |
| `fatG`           | number | g              | Yes       |
| `saturatedFatG`  | number | g              | Yes       |
| `carbohydratesG` | number | g              | Yes       |
| `sugarsG`        | number | g              | Yes       |
| `proteinG`       | number | g              | Yes       |
| `saltG`          | number | g              | Yes       |
| `alcoholG`       | number | g (per 100 mL) | Wine only |

Allergen codes [#allergen-codes]

| Field               | Allergen                    | EU Regulation |
| ------------------- | --------------------------- | ------------- |
| `containsSulphites` | Sulphur dioxide / sulphites | Annex II, #12 |
| `containsEgg`       | Egg and egg products        | Annex II, #3  |
| `containsFish`      | Fish (isinglass fining)     | Annex II, #4  |
| `containsMilk`      | Milk / casein (fining)      | Annex II, #7  |

FAQ [#faq]

### Do I need a separate e-label for each batch or vintage?

Yes. Each batch or vintage with different ingredients or nutrition data should have its own passport. Use the same GTIN if the barcode is shared, or different GTINs for different SKUs.

  
### What languages must the e-label support?

The e-label must be available in the language(s) of the member state(s) where the product is sold. EUlabel supports multi-language passports via the `hreflang` attribute.

  
### When does this regulation take effect?

EU Regulation 2021/2117 requires e-labels for wines produced and labelled after December 8, 2023. New wines entering the EU market must comply.


