DPPespr.com

API Documentation

The DPPespr.com REST API lets you create and manage ESPR Digital Product Passports programmatically, ideal for integrating with ERP, PIM, PLM or LCA systems. All responses are JSON. The base URL is https://dppespr.com/api/v1.

Authentication

Machine requests authenticate with an API key sent in the X-API-Key header. Generate keys from your account under Developer → API keys. The key is shown once at creation, store it securely.

X-API-Key: dpp_live_xxxxxxxxxxxxxxxxxxxxxxxx
App users can alternatively authenticate with a JWT Authorization: Bearer <token>. API keys are the recommended method for server-to-server integration.

Create a passport

POST/api/v1/passports

Creates a Digital Product Passport and returns it with a generated GS1 Digital Link QR asset. Counts against your plan's active-passport allowance.

Request body

{
  "product": {
    "gtin_ean": "5060123456789",
    "batch_lot_number": "LOT-2026-04",
    "product_name": "Organic Cotton Crew Tee",
    "country_of_origin": "PT",
    "industry_category": "TEXTILES",
    "internal_sku": "SKU-001",
    "category": "T-shirts"
  },
  "fibers": [
    { "fiber_type": "Organic cotton", "percentage_weight": 92, "recycled_content_percentage": 20 },
    { "fiber_type": "Elastane", "percentage_weight": 8 }
  ],
  "certificates": [
    { "regulatory_body": "GOTS", "license_number": "GOTS-12345", "expiry_date": "2027-01-01" }
  ],
  "circularity": {
    "care_text_raw": "Machine wash cold.",
    "repairability_index": 8,
    "recycling_end_of_life_instructions": "Return to textile recycling."
  },
  "lifecycle": {
    "carbon_footprint_kg_co2e": 4.2,
    "recycled_content_pct": 20
  }
}

Material composition (fibers) must total exactly 100% when provided. industry_category is one of TEXTILES, ELECTRONICS, FURNITURE, BATTERIES, TYRES, METALS, CONSTRUCTION, OTHER (defaults to TEXTILES).

Bulk import

POST/api/v1/passports/bulk

Create up to 200 passports in one request. Returns a per-item result array so you can see which succeeded and which failed.

{ "passports": [ { "product": { ... }, "fibers": [ ... ] }, { ... } ] }
{
  "created": 2,
  "failed": 1,
  "results": [
    { "index": 0, "ok": true, "id": "…", "gtin_ean": "…", "passport_url": "https://dppespr.com/gtin/…/lot/…" },
    { "index": 1, "ok": false, "error": "GTIN_EXISTS", "message": "A passport with this GTIN already exists" }
  ]
}

Retrieve a passport

GET/gtin/{gtin}/lot/{batch}

The GS1 Digital Link URL. Content negotiation by the Accept header:

Accept headerResponse
text/html (default)Human-readable passport page
application/ld+jsonUNTP-style JSON-LD machine credential for customs systems
curl -H "Accept: application/ld+json" \
  https://dppespr.com/gtin/5060123456789/lot/LOT-2026-04

JSON-LD response

The machine-readable response is a UNTP-style Digital Product Passport credential. It now includes the full public dataset, including category-specific attributes, lifecycle and circularity data. All fields are public by design (a DPP is a publicly accessible record). Empty fields are returned as null.

{
  "@type": "DigitalProductPassport",
  "identifier": "urn:gtin:5060123456789",
  "gs1DigitalLinkPath": "https://dppespr.com/gtin/5060123456789/lot/LOT-2026-04",
  "productName": "Example Jacket",
  "category": "Outerwear",
  "productCategory": "TEXTILES",
  "batchLotNumber": "LOT-2026-04",
  "serialNumber": null,
  "origin": "PT",
  "complianceVerified": true,
  "complianceState": "GREEN",
  "materialComposition": [ { "material": "Organic cotton", "percentByWeight": 80 }, { "material": "Recycled polyester", "percentByWeight": 20 } ],
  "lifecycle": {
    "carbonFootprintKgCo2e": "12.4", "recycledContentPct": "35", "expectedLifespanMonths": "60",
    "energyEfficiencyClass": null, "softwareSupportUntil": null, "sparePartsUrl": null,
    "substancesOfConcern": "None above threshold", "disassemblyGuidance": null
  },
  "circularity": { "careInstructions": "Wash cold...", "repairabilityIndex": 7, "endOfLifeInstructions": "Return to..." },
  "attributes": { "Repairability class (A–E)": "B", "IP rating (dust / water)": "IP68" },
  "certificates": [ { "issuingBody": "OEKO-TEX", "licenseNumber": "...", "expiryDate": "2027-01-01", "auditStatus": "VERIFIED" } ],
  "ledgerAnchor": null
}

The attributes object holds the category-specific fields (battery chemistry, repairability class, Euroclass fire rating, tyre grades, etc.), keyed by their human-readable label. The set of keys depends on productCategory.

Serial & batch-level resolution

Unit-level GS1 Digital Link URLs resolve to the same passport credential. serialNumber is echoed back when present.

PatternLevel
/01/{gtin}/10/{lot}Batch / lot
/01/{gtin}/21/{serial}Individual unit
/01/{gtin}/10/{lot}/21/{serial}Unit within a lot

List your passports

GET/api/v1/passports

Returns all passports owned by the authenticated account.

Update a passport

PUT/api/v1/passports/id/{id}

Updates an existing passport. GTIN and batch/lot are immutable (printed on the physical label). Every update writes a revision to the audit history. Optionally include public_reason to show a note on the public passport.

{
  "product": { "product_name": "Updated name" },
  "fibers": [ { "fiber_type": "Organic cotton", "percentage_weight": 100 } ],
  "public_reason": "Composition corrected after supplier re-test"
}

Revision history

GET/api/v1/passports/id/{id}/revisions

Returns the change history (actor, timestamp, note) supporting the 10-year ESPR audit requirement.

Lifecycle events

Track a product through its life — from manufacture to recycling. Your ERP, WMS or a partner's system can post events with an API key; they appear as a timeline on the public passport.

POST/api/v1/passports/{id}/events
{ "state": "IN_TRANSIT", "location": "Rotterdam DC", "note": "Left port", "serial": "SN-000123" }

state is one of: MANUFACTURED, QUALITY_CHECKED, PACKAGED, IN_TRANSIT, AT_DISTRIBUTOR, ON_SHELF, SOLD, IN_USE, SERVICED, RETURNED, REFURBISHED, RECYCLED, DISPOSED. location, note and serial are optional.

GET/api/v1/passports/{id}/events

Returns the full history newest-first, plus current_state. The latest state and recent timeline are also included in the public JSON-LD passport as lifecycleStatus and lifecycleEvents.

Async bulk import (large catalogues)

For very large uploads (up to 5000 per job), queue the work and poll for progress instead of waiting on one request.

POST/api/v1/passports/bulk-async
{ "passports": [ { "product": { ... }, "fibers": [ ... ] }, … ] }
→ 202 { "job_id": "…", "status": "PENDING", "total": 1200, "status_url": "https://dppespr.com/api/v1/passports/bulk-jobs/…" }
GET/api/v1/passports/bulk-jobs/{id}
{ "job_id": "…", "status": "PROCESSING", "total": 1200, "processed": 450, "created": 448, "failed": 2 }
// when status is DONE, a full per-item "results" array is included
For smaller batches (≤200) the synchronous /passports/bulk endpoint above returns results immediately and is simpler.

Tamper-evidence (ledger notary)

Once a day, every passport that changed is hashed into a Merkle tree and the single root is anchored to the XRP Ledger — one transaction makes the whole day's passports tamper-evident, and each passport keeps its own cryptographic proof. You can check any passport at any time.

GET/api/v1/verify/{gtin}/lot/{batch}

Public. Recomputes the passport's hash from current data and checks it against the anchored Merkle root.

{
  "gtin": "5060123456789", "lot": "LOT-2026-04",
  "anchored": true,
  "verified": true,              // matches anchored data AND root is confirmed on-ledger
  "matchesCurrentData": true,    // current data still equals what was anchored
  "proofValid": true,            // Merkle proof recomputes to the root
  "anchorStatus": "CONFIRMED",
  "merkleRoot": "…64 hex…", "txId": "…", "network": "livenet", "ledgerSequence": 9123456,
  "anchoredAt": "2026-06-15T02:00:00Z", "checkedAt": "2026-06-15T12:00:00Z"
}
GET/api/v1/passports/{id}/notary

Authenticated owner view of the same proof and status for one of your passports.

Errors

StatusCodeMeaning
400VALIDATIONMissing or invalid fields
401INVALID_API_KEYAPI key invalid or revoked
402SUBSCRIPTION_INACTIVEPlan lapsed, renew to continue
403CAP_REACHEDActive-passport limit reached
409GTIN_EXISTSA passport with this GTIN already exists
422COMPOSITION_INVALIDMaterial composition does not total 100%
Standards note: passport output uses GS1 Digital Link and UNTP-style JSON-LD. The API is designed to align with the emerging EN 18222 / EN 18223 DPP API standards and to support EU DPP Registry submission once the registry is operational.