DPP Agent docs

Akeneo PIM — integration guide

This page walks through connecting a brand's Akeneo Enterprise or Community PIM to DPP Agent, end to end. It is the canonical reference for IT-security review.

What the adapter does, in one sentence

DPP Agent reads a tightly-scoped slice of Akeneo's product catalogue (specific channel, locale, family, attribute allowlist) and maps each returned product to a Digital Product Passport row, with explicit field-level mappings under your control. No write-back, no schema changes on your PIM, no internal-only data leaves your tenant.

Authentication

OAuth2 client credentials + service-account password — the standard Akeneo grant_type=password flow. You provide four secrets at connection time:

{
  "client_id":     "from Akeneo → Connect → Connection settings",
  "client_secret": "(generated by Akeneo for this connection)",
  "username":      "akeneo-svc-dppagent",
  "password":      "(service account password)"
}

How those four secrets are protected

The client_secret and password are the sensitive pair. We treat them as write-only credentials:

  • Encrypted at rest. All four values land in our credential vault encrypted with AES-256-GCM. Each row is encrypted with a unique per-record nonce; the master key is held only in our hosting platform's encrypted environment-variable store. See the Security & privacy chapter for the full vault model.
  • Never echoed back to the UI. Once saved, the admin UI shows a redacted fingerprint (first-4 + last-4). The full value is not retrievable through the UI by any role — to rotate, the operator pastes a new value over the old, which clears the row before the new one is written.
  • Never logged. Plaintext does not appear in application logs, request traces, audit-log payloads, or error reports.
  • Decrypted only in-memory during a sync. The plaintext lives in the running serverless function for the duration of the Akeneo HTTP call, then drops out of scope when the function returns. No background workers hold the credentials between syncs.
  • Easy revocation. We do not cache access tokens across runs. Revoking the service account on your Akeneo side takes effect on the next sync run with no further action from us.

Token exchange happens at the start of every sync run using the stored client_id / client_secret plus the service account username / password. The bearer token returned by Akeneo is held only for the duration of that single run.

Scope limitation — six independent levers

DPP Agent is designed to read as little as possible from your PIM. Each lever below can be combined; together they reduce what leaves your Akeneo instance from "every attribute" down to "the eight fields ESPR + AGEC actually need".

1. Read-only OAuth scope

The Akeneo connection your admin creates for DPP Agent needs only:

  • Products: read
  • Channels: read
  • Catalog structure: read

No write scopes are requested. Even if our code were compromised it would be incapable of PATCHing a product, mutating an attribute, or seeding data back into your PIM.

2. Channel scoping

settings.channel = "ecommerce" (or your brand's actual channel code) restricts every product fetch to attributes scope-linked to that channel. Attributes scoped to internal channels — R&D, finance, supply-chain ops — are never returned to us in the first place. This is enforced by Akeneo, not by our code.

3. Locale scoping

settings.locale (or settings.locales for the multi-locale ingest described in Locale) controls which translations Akeneo serialises. A brand operating 30 locales internally for print-catalog and translation-vendor purposes can ship us 1–6 public-facing locales for the consumer DPP.

4. Family filter

settings.family = "apparel,footwear" (comma-separated) makes the adapter issue a server-side search query that filters on family IN (...). Spare parts, marketing-only items, and unrelated product trees never enter the response payload.

Akeneo also supports more elaborate filters (categories, completeness, custom attribute predicates). Talk to us if you need a non-family restriction — the settings.search_extra setting accepts any Akeneo-valid JSON filter expression and we pass it through unchanged.

5. Attribute allowlist (per-tenant)

The adapter's Edit modal exposes a block of attr_* settings that pin our canonical ESPR field IDs to your actual Akeneo attribute codes:

attr_gtin           = ean_code              (default: ean)
attr_name           = product_name          (default: name)
attr_description    = product_description   (default: description)
attr_color          = main_color            (default: color)
attr_size           = size_id               (default: size)
attr_composition    = fabric_content        (default: composition)
attr_care           = wash_label_text       (default: care_instructions)
attr_image          = primary_image         (default: image)

Only attribute codes present in this allowlist are read out of the Akeneo response payload. If your products carry 400 attributes, the mapper still touches only the 8 you mapped. Everything else is dropped before it leaves the response parser.

6. Network-level IP allowlist (optional)

Our sync runs on Vercel's serverless platform. Vercel publishes the egress IP ranges for each region at https://vercel.com/docs/edge-network/regions. Your firewall / WAF can restrict your Akeneo API to those ranges so no other tenant of Vercel — and no actor outside it — can reach your PIM through our network path.

Settings reference

Setting Required Purpose
base_url yes https://your-pim.cloud.akeneo.com
client_id yes Per Authentication
client_secret yes (password-style — write-only in UI)
username yes service-account username
password yes service-account password
channel yes Akeneo channel code, e.g. ecommerce
locale yes Default locale, e.g. en_GB. See Locale for multi.
locales no Array of locales to ingest as {locale: value} shape
page_size no 50–100. Default 100.
family no Comma-separated family codes to restrict
search_extra no Raw Akeneo search JSON to merge into the default query
attr_* no Per-field attribute-code overrides
sync_max_pages no Hard ceiling on per-sync pages — capped-by-default safety lever
sync_unlimited no true to walk the entire catalogue. Use after a small-batch dry run.
sync_mode no skeleton (default — fast, no heavy attributes) | full

Sync semantics

Two modes:

  • Skeleton (default, recommended for initial sync). Pulls identifiers + product/variant structure + GTIN + image only. Lands fast — enterprise-scale catalogues (≈10k products) inside the 300s Vercel function ceiling. Used to validate field mapping and populate skeleton DPPs that the brand can then publish or enrich.
  • Full. Pulls every mapped attribute including BOM, supplier list, care instructions, certifications. Use after the skeleton pass confirms the mapping is right.

Subsequent sync runs respect the Conflict policy:

  • Draft DPPs are overwritten freely
  • Active DPPs spawn dpp_revisions(status=pending) for human review
  • Withdrawn / archived / recalled DPPs are skipped

There is no automatic deletion. If a product disappears from your Akeneo catalogue, the corresponding DPP remains in dpp_runtime and becomes orphan (its source = akeneo but the upstream row is gone). Orphans surface in the admin and the brand decides to withdraw, archive, or leave them as historical.

What does the public URL serve after the upstream row is gone?

This is by regulatory design. EN 18219 §4.4 and EN 18223 §4.1.2 require a DPP to outlive the product it describes — both for consumer recall scenarios and for the audit retention period (default 10 years). Removing a product from Akeneo does not authorise removal of the DPP.

Concretely, while the DPP carries dpp_status = active:

  • The public URL keeps resolving with the last successfully synced data. No new updates can arrive (Akeneo has nothing to give), so the rendered content is frozen at the most recent sync.
  • Consumer scanners, brand-owned client apps, and the JSON-LD representation all see that frozen state.
  • Market-surveillance and customs roles still have read access to the row even after the brand later flips status — that's the whole point of the retention requirement.

The brand decides — explicitly — when (and whether) to change status:

Action Public response When to use
Stay active 200 with the last-synced page Product is no longer sold but a consumer may still own one
Withdrawn 410 with a branded "no longer available" notice Reformulated, replaced, or pulled from market
Archived 410 with a historical-record notice Permanently retired, kept for audit trail only
Recalled 410 with a safety-recall notice + manufacturer link Active safety recall

In every case the row itself is preserved. Audit roles (market-surveillance, manufacturer, customs) can still resolve the content under their authentication; only the public face changes. This separation is what lets the brand take the consumer-facing page offline (or change its wording) without erasing the underlying record a regulator may need years later.

Onboarding sequence

  1. Brand-side IT-security approves the read-only service account
  2. Brand pastes client_id / secret / username / password into the DPP Agent Connect modal
  3. Connection test: we run a probe against your channel — succeeds if the four secrets work and the channel is reachable
  4. Brand picks channel, locale[s], optionally family, fills in the attr_* allowlist if defaults don't match
  5. Skeleton sync with sync_max_pages = 2-3 — confirms mapping on ~10–30 products
  6. Brand reviews the resulting drafts in admin, tunes the attr_* mapping if needed, and re-runs
  7. Full sync (sync_unlimited = true, sync_mode = full) once the mapping is locked in
  8. Cron takes over — auto-sync on a 6h schedule by default. The interval is configurable per tenant: hourly, 6h, 12h, 24h, weekly or monthly. Choose the cadence that matches how often the brand updates its catalogue and how quickly downstream consumers need to see those changes

What you DON'T need to do

  • No schema changes in Akeneo
  • No PIM downtime
  • No new attributes added (we read what you already have)
  • No publishing back to your PIM
  • No webhooks (we pull, you don't push — unless you want the separate webhook integration for real-time updates)
  • No data leaves your channel/locale/family scope

Compliance hooks

The Akeneo adapter populates the following ESPR + AGEC fields out of the box (assuming the brand has filled them in upstream):

ESPR / AGEC field Akeneo source (default attribute code)
espr.pid.gtin ean
espr.pid.product_name name
espr.pid.product_description description
espr.pid.color color
espr.pid.size size
espr.mat.composition composition
espr.care.instructions care_instructions
tex.product.hero_image_url image
espr.pid.product_brand (from tenant.brand_name)

Use the per-tenant attr_* overrides to wire your actual codes.

For AGEC traceability (tex.journey.steps), Akeneo does not typically structure supply-chain data in a way we can auto-map. The pragmatic pattern is to maintain those rows in TrusTrace or a dedicated traceability tool and connect that adapter alongside.

Troubleshooting

  • HTTP 401 on token exchange — service-account password is wrong, or the connection was deactivated in Akeneo
  • HTTP 403 with forbidden_scope — the connection lacks one of the three read scopes
  • Empty _embedded.items despite Akeneo having products — channel + locale combination has no scope-linked attributes
  • Slow sync, hitting 300s ceiling — switch to sync_mode = skeleton for the first pass, or set family to restrict scope
  • HTTP 400 on the search_extra filter — Akeneo rejects the JSON; copy-paste your filter into Akeneo's own REST API console to validate the shape before pasting back here

Open a ticket at support@dppagent.com with the integration ID and last sync log entry; we respond inside one business day.