DPP endpoints
Traceable exposes DPP data through two complementary systems, each serving a different purpose.
Two access methods
| Method | URL pattern | Response | Use case |
|---|---|---|---|
| GS1 Digital Link resolver | /01/{GTIN}[/21/{serial}][/10/{batch}] | HTML (DPP viewer) | QR codes on physical batteries |
| JSON data API | /api/dpp/{slug} | JSON / JSON-LD | Machine-readable integration |
The GS1 Digital Link format is what EU Battery Regulation 2023/1542 requires to be encoded in the data carrier (QR code) on the physical battery. The JSON API is for programmatic access to the underlying data.
Both methods resolve to the same underlying DPP. A battery without a GTIN assigned in Traceable will only have a slug-based URL — the GS1 resolver requires a GTIN.
GS1 Digital Link resolver
GET /01/:gtin
GET /01/:gtin/21/:serial
GET /01/:gtin/10/:batch
Resolves a GTIN to the corresponding DPP and renders the battery passport viewer inline. The GS1 URI remains in the browser URL bar — there is no redirect to a slug-based URL.
This is the endpoint that QR codes on physical batteries should encode. It implements the GS1 Digital Link standard (ISO/IEC 18975).
Path structure
| Segment | Application Identifier | Description |
|---|---|---|
/01/{GTIN} | AI 01 | GTIN (required). 8, 12, 13, or 14 digits with a valid GS1 check digit. |
/21/{serial} | AI 21 | Individual serial number (optional) |
/10/{batch} | AI 10 | Batch or lot number (optional) |
Examples
https://app.traceable.digital/01/09506000134352
https://app.traceable.digital/01/09506000134352/21/ABC123
https://app.traceable.digital/01/09506000134352/21/ABC123/10/BATCH-2026-04
Validation
The GTIN is validated using the standard GS1 modulo-10 check digit algorithm before the database lookup. Requests with an invalid check digit return a 404 immediately — no database query is made.
Supported formats:
| Format | Digits | Example |
|---|---|---|
| GTIN-8 | 8 | 01234565 |
| GTIN-12 | 12 | 012345678905 |
| GTIN-13 | 13 | 0123456789012 |
| GTIN-14 | 14 | 01234567890128 |
Response
- 200 OK — HTML page rendering the DPP viewer for the resolved product. The DPP data is embedded in the page and in the HTML
<head>as JSON-LD. - 404 Not Found — GTIN not found in the Traceable registry, GTIN check digit is invalid, or the matched product's DPP is not published.
This endpoint returns HTML, not JSON. To retrieve machine-readable DPP data for a product you know by GTIN, resolve the GTIN first to get the slug, then use the JSON API.
Constructing a GS1 Digital Link URI
When generating the QR code URI for a battery product in Traceable, the platform uses this format when a GTIN is assigned:
https://app.traceable.digital/01/{GTIN}/21/{serialNumber}
If no GTIN has been assigned, the platform falls back to the slug-based URL:
https://app.traceable.digital/dpp/{slug}
The platform's QR code generator in the Operator Portal handles this automatically and displays a "GS1 Compliant" badge when the GTIN-based format is used.
JSON data API
GET /api/dpp/:slug
Retrieve the complete public DPP data for a battery product as JSON.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | The URL-safe product identifier assigned at DPP creation. Example: swiftvolt-48v-100ah-ev-pack |
Authentication
None required for public fields. To access restricted supply chain fields via an approved PoLI token, include both the accessToken query parameter and the Authorization: Bearer {apiKey} header.
Optional query parameters
| Parameter | Type | Description |
|---|---|---|
accessToken | string | A 24-hour access token obtained from an approved PoLI access request (GET /api/poli/verify). When present and valid, the response also includes a restrictedFields object containing detailed supply chain data not returned in the standard public response. |
When an accessToken is provided:
- The
Authorization: Bearer {apiKey}header must also be present. - The response includes the standard public fields plus a
restrictedFieldsobject (raw material sourcing by mine/country, full supplier audit references, internal test documentation references). - If the token has expired (tokens are valid for 24 hours), the endpoint returns
401 Unauthorized. CallGET /api/poli/verifyagain with the originalrequestIdto obtain a fresh token. - If the token does not match the requested product slug, the endpoint returns
403 Forbidden.
For most PoLI integrations the restricted fields are already returned directly in the GET /api/poli/verify response — a separate DPP call with an accessToken is only needed when re-fetching updated values after the initial approval. See PoLI endpoints for the full token lifecycle.
curl "https://app.traceable.digital/api/dpp/swiftvolt-48v-100ah-ev-pack?accessToken=pat_eyJ..." \
-H "Authorization: Bearer ${TRACEABLE_API_KEY}"
Response — 200 OK
Returns the full DPP object for the requested product.
| Field | Type | Description |
|---|---|---|
id | string | Internal DPP record identifier |
slug | string | URL-safe product identifier. Immutable after publish. |
productName | string | Full commercial product name |
batteryCategory | string | One of: EV_BATTERY, LMT_BATTERY, INDUSTRIAL_BATTERY, SLI_BATTERY, PORTABLE_BATTERY |
status | string | published — only published DPPs are returned by this endpoint |
version | integer | Version number, incremented each time the DPP is updated and republished |
manufacturer | object | Manufacturer name, country, registration number, and contact details |
carbonFootprint | object | null | Carbon footprint data (present for EV and Industrial batteries; null for others) |
recycledContent | object | Recycled content percentages for cobalt, lithium, nickel, lead |
performance | object | Capacity, energy density, cycle life, round-trip efficiency |
hazardousSubstances | array | List of hazardous substances above threshold, with CAS numbers and concentrations |
supplyChain | object | Supply chain due diligence summary and responsible sourcing information |
compliance | object | Regulatory compliance declarations and certification references |
publishedAt | string | ISO 8601 timestamp when the DPP was first published |
updatedAt | string | ISO 8601 timestamp of the most recent update |
createdAt | string | ISO 8601 timestamp when the DPP record was created |
Response — 404 Not Found
Returned when the slug does not match any product, or the product's DPP is not published.
{
"error": "DPP not found or not published",
"code": "PRODUCT_NOT_FOUND",
"details": {}
}
Response — 429 Too Many Requests
{
"error": "Rate limit exceeded",
"code": "RATE_LIMITED",
"retryAfter": 23
}
Examples
curl
curl -s https://app.traceable.digital/api/dpp/swiftvolt-48v-100ah-ev-pack | jq .
JavaScript (Node.js / browser fetch)
async function fetchDpp(slug: string): Promise<DppObject> {
const response = await fetch(
`https://app.traceable.digital/api/dpp/${encodeURIComponent(slug)}`
);
if (response.status === 404) {
throw new Error(`DPP not found for slug: ${slug}`);
}
if (response.status === 429) {
const data = await response.json();
throw new Error(`Rate limited. Retry after ${data.retryAfter} seconds.`);
}
if (!response.ok) {
const data = await response.json().catch(() => ({}));
throw new Error(`Failed to fetch DPP: ${data.error ?? response.statusText}`);
}
return response.json();
}
Python (requests)
import requests
def fetch_dpp(slug: str) -> dict:
url = f"https://app.traceable.digital/api/dpp/{slug}"
response = requests.get(url, timeout=10)
if response.status_code == 404:
raise ValueError(f"DPP not found or not published for slug: {slug}")
if response.status_code == 429:
retry_after = response.json().get("retryAfter", 60)
raise RuntimeError(f"Rate limited. Retry after {retry_after}s.")
response.raise_for_status()
return response.json()
GET /api/dpp/:slug/jsonld
Retrieve a DPP in JSON-LD format for semantic web interoperability.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | The URL-safe product identifier |
Authentication
None required.
Response — 200 OK
Returns a JSON-LD document representing the DPP. The Content-Type is application/ld+json.
The @id of the returned document is the canonical URI for the product:
- If the product has a GTIN assigned:
https://app.traceable.digital/01/{GTIN}/21/{serial}(GS1 Digital Link) - If no GTIN:
https://app.traceable.digital/dpp/{slug}
The document uses:
@context: A combination ofhttps://schema.organd the Traceable custom vocabulary athttps://vocab.traceable.digital/v1@type:["schema:Product", "traceable:BatteryPassport"]
Response — 404 Not Found
{
"error": "DPP not found or not published",
"code": "PRODUCT_NOT_FOUND",
"details": {}
}
Example JSON-LD response (product with GTIN)
{
"@context": {
"schema": "https://schema.org/",
"traceable": "https://vocab.traceable.digital/v1#",
"xsd": "http://www.w3.org/2001/XMLSchema#"
},
"@type": ["schema:Product", "traceable:BatteryPassport"],
"@id": "https://app.traceable.digital/01/09506000134352/21/SN-2026-00421",
"schema:name": "SwiftVolt 48V 100Ah EV Pack",
"schema:identifier": "09506000134352",
"schema:manufacturer": {
"@type": "schema:Organization",
"schema:name": "SwiftVolt Energy Systems GmbH",
"schema:addressCountry": "DE",
"schema:vatID": "DE298471625",
"schema:email": "compliance@swiftvolt.de"
},
"traceable:batteryCategory": "EV_BATTERY",
"traceable:version": 3,
"traceable:status": "published",
"traceable:carbonFootprint": {
"@type": "traceable:CarbonFootprint",
"traceable:totalKgCO2ePerKwh": 61.4,
"traceable:lifecycleStages": {
"traceable:rawMaterialExtraction": 28.2,
"traceable:manufacturing": 18.6,
"traceable:distribution": 2.1,
"traceable:usePhase": 7.3,
"traceable:endOfLife": 5.2
},
"traceable:verifiedBy": "TÜV Rheinland",
"traceable:verifiedAt": {
"@type": "xsd:dateTime",
"@value": "2025-01-15T00:00:00Z"
}
},
"traceable:recycledContent": {
"traceable:cobaltPercent": 16.0,
"traceable:lithiumPercent": 6.0,
"traceable:nickelPercent": 6.0,
"traceable:leadPercent": 0.0
},
"traceable:performance": {
"traceable:nominalCapacityKwh": 4.8,
"traceable:ratedVoltageV": 48,
"traceable:cycleLifeAtEightyPercent": 2000,
"traceable:roundTripEfficiencyPercent": 96.2
},
"schema:datePublished": {
"@type": "xsd:dateTime",
"@value": "2025-02-01T10:14:22Z"
},
"schema:dateModified": {
"@type": "xsd:dateTime",
"@value": "2025-03-18T08:45:11Z"
}
}
For full details on consuming JSON-LD responses, see the JSON-LD format data model page and the Parse JSON-LD output integration example.