Inbound Webhooks
Sync product data from your PIM or CMS to EUlabel via webhooks.
When product data changes in your PIM (e.g., DatoCMS, Salsify, Akeneo), a webhook triggers EUlabel to regenerate the passport automatically.
At a glance
- Inbound endpoint:
POST /v1/webhooks/ingest - Always verify HMAC signatures using the raw request body
- Keep your handler idempotent (retries can deliver duplicates)
Flow
A product record is created or updated in your PIM.
The PIM sends a webhook POST to https://api.eulabel.eu/v1/webhooks/ingest.
EUlabel validates the webhook signature.
The platform maps PIM fields to passport fields.
The passport is regenerated (or created if new).
The QR code URL continues to resolve to the updated passport.
Recommended handler layout
Example payload (DatoCMS)
{
"event_type": "item.update",
"entity_type": "item",
"entity": {
"id": "Kq7rxxPPS32ErMA8nxxMTA",
"type": "product",
"attributes": {
"product_name": "Quinta dos Carvalhais Alfrocheiro 2019",
"barcode": [
{
"barcode_number": "5601012012200",
"capacity_value": "750 mL",
"vintage_year": 2019
}
],
"list_of_ingredient": [
{ "ingredient_name": "Grapes", "quantity": "99.986%" },
{ "ingredient_name": "Sulphites", "quantity": "0.014%" }
],
"contains_sulfites": true,
"energy_value_kj": "351 kJ/100mL",
"alcohol_content_by_volume": "13.5%vol.",
"product_country": "PT",
"product_region": "Dao"
}
}
}Signature verification
Every inbound webhook includes a signature header:
X-Webhook-Signature: sha256=<HMAC-SHA256 of request body using shared secret>Always use a constant-time comparison when verifying HMAC signatures. A naive string comparison is vulnerable to timing attacks.
Verify it by computing the HMAC of the raw request body with your shared secret and comparing to the provided signature. Requests with invalid signatures are rejected with HTTP 401.
Many frameworks parse JSON and change whitespace or key ordering. Signature verification must be computed over the exact raw body bytes received by your server.
Verification example
import { EUlabel } from "@eulabel/sdk";
const client = new EUlabel({ apiKey: "sk_test_..." });
const isValid = client.webhooks.verify(
requestBody,
request.headers["x-webhook-signature"],
process.env.WEBHOOK_SECRET,
);# Compute HMAC-SHA256 of the raw body
echo -n "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET"Field mapping
EUlabel maps PIM-specific fields to the passport schema. Mapping configurations are stored per tenant, allowing each organization to define their own field correspondence.
| PIM Field | EUlabel Passport Field |
|---|---|
product_name | name |
barcode[].barcode_number | gtin |
list_of_ingredient[].ingredient_name | ingredients[] |
contains_sulfites, contains_egg, etc. | allergens |
energy_value_kj, fat, sugars, etc. | nutrition |
product_country + product_region | origin |
producer[].name | supplier |
Supported platforms
| Platform | Integration | Status |
|---|---|---|
| DatoCMS | Native webhooks + GraphQL | Available |
| Salsify | Webhooks + REST API | Coming soon |
| Akeneo | Event API + REST | Coming soon |
| Contentful | Webhooks + Content Delivery API | Coming soon |
| Custom PIM | Generic webhook endpoint | Available |
For platforms without native webhook support, call the EUlabel API directly using the SDK.