DPP Agent docs

DPPs — create, read, update, delete

The DPP is the central object — one row per product (model granularity) or product instance (item granularity, with batch + serial). Every endpoint here is tenant-scoped via the Bearer token.

Object shape

{
  "id": "dpp_3f2a9b1c-e0d8-4f8e-b308-d2541886e331",
  "tenant_id": "tnt_8d3a4f91-427f-4d5d-b527-c0b28363676c",
  "passport_id": "https://example.dpp.dppagent.com/01/07314781685466/21/AX-001",
  "gtin": "07314781685466",
  "batch": null,
  "serial": "AX-001",
  "cpv": null,
  "category": "electronics",
  "granularity": "item",
  "identifier_scheme": "01",
  "template_id": "electronics-premium",
  "dpp_status": "active",
  "dpp_data": { /* ESPR Base + category-specific keys */ },
  "last_updated": "2026-06-26T13:42:05.000Z",
  "created_at": "2026-05-10T09:18:21.000Z"
}

dpp_data carries the structured payload. Keys are flat strings (espr.pid.product_name, bat.chem.cell_chemistry, ict.energy.eu_efficiency_class) so any consumer can read with a single hash lookup. See per-category schemas for what keys exist.

Create one DPP

POST /api/v1/dpps
Authorization: Bearer dpp_live_…
Content-Type: application/json
{
  "tenant_id": "tnt_8d3a4f91-…",
  "gtin": "07314781685466",
  "category": "electronics",
  "granularity": "model",
  "template_id": "electronics-premium",
  "dpp_data": {
    "espr.pid.product_name": "Beosound Explore",
    "espr.pid.product_brand": "Bang & Olufsen",
    "espr.mfr.name": "B&O A/S",
    "espr.eo.country": "DK",
    "ict.energy.eu_efficiency_class": "A"
  }
}

Response201 Created:

{
  "id": "dpp_3f2a9b1c-…",
  "passport_id": "https://bang-olufsen.dpp.dppagent.com/01/07314781685466",
  "dpp_status": "draft"
}

The DPP starts as a draft. Promote it by patching dpp_status: "active" once mandatory fields are filled.

Async creation

Item-granularity DPPs with quantity > 1000 enqueue an async serialization job and return 202 Accepted:

{
  "job_id": "sj_8c3a4f91-…",
  "status_url": "/api/v1/dpps/jobs/sj_8c3a4f91-…"
}

Poll status_url until the job reports completed.

Bulk create

POST /api/v1/dpps-batch
{
  "tenant_id": "tnt_…",
  "stop_on_error": false,
  "items": [
    { "gtin": "0731…0001", "category": "battery", "granularity": "model", "dpp_data": {} },
    { "gtin": "0731…0002", "category": "battery", "granularity": "model", "dpp_data": {} }
  ]
}

Up to 1 000 items per call. Response includes per-item success status — partial successes are normal when stop_on_error: false.

Read one DPP

GET /api/v1/dpps/{id}

Returns the full object including dpp_data. Add ?include=versions to inline the version history.

Update a DPP

PATCH /api/v1/dpps/{id}
Content-Type: application/json
{
  "tenant_id": "tnt_…",
  "dpp_data": {
    "espr.pid.product_name": "Beosound Explore II",
    "ict.energy.eu_efficiency_class": "A+"
  }
}

PATCH is a shallow merge at the top level — your dpp_data replaces the stored map wholesale. To merge subset of keys, read, mutate, write.

Status transitions are also a PATCH:

{ "tenant_id": "tnt_…", "dpp_status": "active" }

Valid status values: draft, active, replaced, withdrawn, archived. Going from active straight to archived triggers a HTTP 410 Gone on the resolver — meaning the consumer scan still resolves but indicates the product is gone.

Delete a DPP

DELETE /api/v1/dpps/{id}

Hard-deletes drafts. active, withdrawn, and archived DPPs cannot be hard-deleted — change dpp_status to archived instead so the audit trail and version history survive.

Find DPPs by GTIN

GET /api/v1/dppsByProductId/{gtin}

Returns the most recent active DPP for a product identifier. Useful for stamp-on-product flows where the integration only knows the GTIN, not the DPP id.

Per-DPP analytics

GET /api/v1/dpps/{id}/analytics?days=90

Returns { total, daily: [{ day, count }], by_country: [{ country, count }], by_device: { mobile, desktop, tablet, unknown }, recent: [{ scanned_at, country, device_class, referer_host, accept_lang, ip_prefix, user_agent }] }. Default window 90 days, override with ?days=.

Version history

GET /api/v1/dpps/{id}/versions

Every PATCH writes a snapshot. Response includes a field-level diff against the previous version — useful for audit trails and regulator queries.

AI Suggest

POST /api/v1/dpps/ai-suggest
{
  "dppId": "dpp_…",
  "fields": ["espr.pid.product_name", "espr.mat.components"]
}

Returns suggested values pulled from integration raw data (Centra, Delogue, Shopify, etc.) or AI-extracted from the brand site, with a source citation per field. Operators review and accept; nothing auto-writes.

Sync from datasource

POST /api/v1/dpps/{id}/sync-from-datasource

Re-pulls this DPP from its origin integration. Useful after a brand edits the source-of-truth in their PIM and wants the DPP to refresh without waiting for the next scheduled sync.