Skip to main content

Passport product data model (UNTP)

The product object accepted by POST /v1/dpp/passports and by bulk import follows the UN Transparency Protocol (UNTP) Core Digital Product Passport model, v0.7.0 — specification, JSON-LD context. Keyban uses this model as its internal pivot: whatever the source — a manual create, a bulk import, or the Shopify catalogue sync — every passport's product ends up in this shape, and every downstream projection (the public passport page, the on-chain certificate, the verifiable credential) is derived from it.

Two identifiers are generated by Keyban and must not be sent by the caller: product.id and product.idScheme. Object type tuples (type: ['Product'], type: ['Claim'], …) default server-side and can be omitted from the payload.

Granularity drives which fields are required​

Granularity is carried by product.idGranularity, not by a top-level discriminant field:

idGranularityIdentifiers required on product
modelmodelNumber
batchmodelNumber + batchNumber
itemmodelNumber + batchNumber + itemNumber

modelNumber, batchNumber and itemNumber are nullable at the schema level for all three granularities — the requirement above is enforced by the import/create service against idGranularity, not by a type union. Sending an item without batchNumber fails validation even though the field type itself allows null.

Core sections of product, and where they surface on the passport​

SectionKey fieldsWhere it appears on the published passport
Identityname, modelNumber / batchNumber / itemNumberPage title, and the "Product identity" card
CategoryproductCategory[]"Category" field inside the "Product identity" card
Primary imageproductImageImage carousel at the top of the page
Technical specificationscharacteristics (free-form key/value)"Technical specifications" card
Origin and manufactureproducedAtFacility, countryOfProduction"Origin and manufacture" card; countryOfProduction is also shown in the hero on model passports
Production dateproductionDateHero of item passports only — not shown on model / batch
Dimensionsdimensions (weight, length, width, height, volume)"Product dimensions" card
Material compositionmaterialProvenance[]"Material composition" card (material, origin, mass, recycled share, hazardous)
Conformity claimsperformanceClaim[]"Evidence of sustainability" card
Related partiesrelatedParty[]"Actors involved" card (manufacturer, distributor, …)
Related documentsrelatedDocument[]"Documents" card
Product labelsproductLabel[]"Labels and certifications" card — images only, name / description are not rendered
PackagingpackagingNot rendered today. Accepted and stored, but the public passport viewer has no card for it yet.

This table covers what maps to a visible block on the passport, not the exhaustive field list — for that (including fields with no dedicated UI, like expiryDate), see the CreateDppPassportDto schema.

Full example​

A model-granularity passport with a material breakdown and a conformity claim, trimmed from a real import payload:

{
"application": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"network": "BaseMainnet",
"product": {
"name": "Organic cotton crewneck T-shirt — White",
"idGranularity": "model",
"modelNumber": "KB-TS-001",
"description": "100% GOTS-certified organic cotton, classic straight cut.",
"productImage": {
"linkURL": "https://ipfs.io/ipfs/QmNXXmCD9xzH8em8EbhirCyNrHai4SVTYBYpWAfhptBuRn",
"linkName": "Organic cotton crewneck T-shirt — White"
},
"characteristics": {
"Color": "White",
"Size range": "XS-XXL",
"Gender": "Unisex"
},
"productCategory": [
{
"code": "53102501",
"name": "T-shirts",
"schemeID": "https://vocabulary.uncefact.org/unspsc",
"schemeName": "UNSPSC"
}
],
"relatedParty": [
{
"role": "manufacturer",
"party": {
"id": "did:web:keyban.io",
"name": "Keyban",
"registeredId": "3760123450017",
"idScheme": {
"id": "https://id.gs1.org/417",
"name": "GS1 Global Location Number"
}
}
}
],
"dimensions": {
"weight": { "unit": "GRM", "value": 180 }
},
"materialProvenance": [
{
"name": "Organic cotton",
"originCountry": { "countryCode": "IN" },
"materialType": {
"code": "cotton-organic",
"name": "Organic cotton",
"schemeID": "https://vocabulary.uncefact.org/material",
"schemeName": "UN/CEFACT Material Vocabulary"
},
"massFraction": 1,
"recycledMassFraction": 0,
"hazardous": false
}
],
"performanceClaim": [
{
"id": "https://passport.keyban.io/credentials/dcc/kb-ts-001/gots",
"name": "Global Organic Textile Standard (GOTS) 7.0",
"description": "Certifies a high share of organic fibres and compliance with environmental and social criteria across the textile chain.",
"claimDate": "2026-02-10",
"referenceCriteria": [],
"claimedPerformance": [],
"conformityTopic": [
{
"id": "https://vocabulary.uncefact.org/conformityTopic#environment.material",
"name": "environment.material"
}
],
"referenceStandard": [
{
"id": "https://global-standard.org/",
"name": "Global Organic Textile Standard (GOTS) 7.0"
}
],
"evidence": [
{
"linkURL": "https://passport.keyban.io/credentials/dcc/kb-ts-001/gots",
"linkName": "DCC — GOTS certificate"
}
]
}
]
}
}

referenceCriteria and claimedPerformance are schema-valid as empty arrays, though at least one entry is expected in practice — reserve the empty form for a claim backed only by a third-party certificate (evidence) rather than a self-reported measurement.

Shopify sync vs. manual or bulk import​

The Shopify catalogue sync auto-fills identity, images, and variant-derived fields (model / item) straight from the Shopify product. It has no native equivalent for the traceability and conformity sections — materialProvenance, performanceClaim, relatedParty, packaging — because Shopify's own product model doesn't carry them. Shopify-sourced passports (source = "shopify") are read-only through PATCH, so these fields stay empty unless populated at the source; passports created through POST /v1/dpp/passports or POST /v1/imports (source = "manual" / "import") can set the full model in one call. See Prepare your Shopify catalogue for how modelNumber is derived from the Shopify product identifier, and why the sync never produces batch-granularity passports.

API reference​

For the exhaustive, always-current field list — including nested object shapes, optionality, and validation rules — see CreateDppPassportDto.