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.
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
Authorization: Bearer <token>. API keys are the recommended method for server-to-server integration.Creates a Digital Product Passport and returns it with a generated GS1 Digital Link QR asset. Counts against your plan's active-passport allowance.
{
"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).
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" }
]
}
The GS1 Digital Link URL. Content negotiation by the Accept header:
| Accept header | Response |
|---|---|
text/html (default) | Human-readable passport page |
application/ld+json | UNTP-style JSON-LD machine credential for customs systems |
curl -H "Accept: application/ld+json" \
https://dppespr.com/gtin/5060123456789/lot/LOT-2026-04
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.
Unit-level GS1 Digital Link URLs resolve to the same passport credential. serialNumber is echoed back when present.
| Pattern | Level |
|---|---|
/01/{gtin}/10/{lot} | Batch / lot |
/01/{gtin}/21/{serial} | Individual unit |
/01/{gtin}/10/{lot}/21/{serial} | Unit within a lot |
Returns all passports owned by the authenticated account.
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"
}
Returns the change history (actor, timestamp, note) supporting the 10-year ESPR audit requirement.
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.
{ "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.
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.
For very large uploads (up to 5000 per job), queue the work and poll for progress instead of waiting on one request.
{ "passports": [ { "product": { ... }, "fibers": [ ... ] }, … ] }
→ 202 { "job_id": "…", "status": "PENDING", "total": 1200, "status_url": "https://dppespr.com/api/v1/passports/bulk-jobs/…" }
{ "job_id": "…", "status": "PROCESSING", "total": 1200, "processed": 450, "created": 448, "failed": 2 }
// when status is DONE, a full per-item "results" array is included
/passports/bulk endpoint above returns results immediately and is simpler.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.
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"
}
Authenticated owner view of the same proof and status for one of your passports.
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION | Missing or invalid fields |
| 401 | INVALID_API_KEY | API key invalid or revoked |
| 402 | SUBSCRIPTION_INACTIVE | Plan lapsed, renew to continue |
| 403 | CAP_REACHED | Active-passport limit reached |
| 409 | GTIN_EXISTS | A passport with this GTIN already exists |
| 422 | COMPOSITION_INVALID | Material composition does not total 100% |