Un pasaporte digital de producto está pensado para ser leído por personas y por máquinas: el sistema de recepción de un reciclador, una API de aduanas, el rastreador de un marketplace, el script de un auditor de sostenibilidad. Una página HTML solo para humanos no basta. El pasaporte tiene que ser legible por máquinas: una carga útil estructurada que un programa pueda analizar, enlazar y razonar sin necesidad de hacer scraping.
Esta guía es para desarrolladores que se hacen la siguiente pregunta obvia: una vez que tengo un DPP, ¿cómo lo lee realmente una máquina? La respuesta en qr3 es JSON-LD a través del resolver público. Mostraremos la respuesta real, explicaremos cómo la misma URL sirve a personas y a máquinas, y luego situaremos en su contexto EPCIS 2.0, el estándar de eventos complementario de GS1.
Qué significa la legibilidad por máquinas para un DPP
Legible por máquinas es más que "devuelve JSON". Para un pasaporte de producto significa tres cosas:
- Estructurado: campos que un parser puede direccionar (
gtin,name, …), no prosa que haya que scrapear. - Tipado y enlazado: términos anclados a vocabularios compartidos para que
Productsignifique lo mismo para todos. Eso es el Linked Data de JSON-LD. - Estable para obtener: una URL duradera por artículo a la que un script pueda hacer
GETdurante toda la vida del producto.
JSON-LD (JSON for Linking Data) ofrece las tres cosas. Es JSON corriente más un @context que asigna cada clave a un término de un vocabulario público — aquí schema.org y el vocabulario web de GS1. Un rastreador que ya entiende schema.org entiende el pasaporte sin ninguna integración personalizada.
El DPP como JSON-LD (curl real + respuesta verificada)
Cada pasaporte de qr3 se resuelve en una URL de GS1 Digital Link: https://qr3.app/dpp/{gtin}/{serial}. Añade ?format=jsonld para pedir la vista de Linked Data. Contra la demo de batería en vivo:
curl -s "https://qr3.app/dpp/04019999999902/DEMO-BAT-01?format=jsonld"
devuelve:
{
"@context": ["https://schema.org", "https://gs1.org/voc/"],
"@type": "Product",
"gtin": "04019999999902",
"name": "EcoMax 5000 (Demo)"
}
Tres cosas a tener en cuenta:
@contextes un array de dos vocabularios: schema.org para la web general ygs1.org/voc/para los términos de producto de GS1. Las claves se resuelven contra ambos.@type: "Product"indica a cualquier consumidor de Linked Data exactamente qué tipo de entidad es esta.- Los valores (
gtin,name) son reales y en vivo: esta es la carga útil real, no un mock.
Ese es justamente el objetivo: el script de un reciclador no necesita un cliente específico de qr3. Hace un GET HTTP, analiza el JSON-LD que ya entiende y lee el GTIN y el nombre del producto directamente.
Una URL, dos públicos: negociación de contenido
La misma URL https://qr3.app/dpp/{gtin}/{serial} sirve un pasaporte HTML apto para humanos y la vista de máquina: el servidor decide qué devolver en función de lo que pide quien llama. Dos formas de pedirlo:
| Quieres | Parámetro de consulta | O cabecera Accept |
|---|---|---|
| Página HTML para humanos | (por defecto) | Accept: text/html |
| JSON-LD (Linked Data) | ?format=jsonld |
Accept: application/ld+json |
| JSON plano | ?format=json |
— |
| Linkset (recursos relacionados) | ?format=linkset |
— |
| DCAT-AP (metadatos del conjunto de datos) | ?format=dcat-ap |
— |
Así, la cámara de un teléfono que abre el QR aterriza en el pasaporte HTML legible, mientras que un script pide a la URL idéntica el formato application/ld+json y obtiene datos estructurados:
# Vista de máquina mediante negociación por cabecera — misma URL, sin query string
curl -s -H "Accept: application/ld+json" \
"https://qr3.app/dpp/04019999999902/DEMO-BAT-01"
Un identificador, una URL, muchas representaciones. El GTIN/serial permanece estable; la vista se adapta a quien llama. Eso es exactamente lo que hace que un DPP sea a la vez duradero e interoperable.
Dónde encaja EPCIS 2.0 (eventos frente a pasaporte)
Una pregunta habitual a continuación: ¿y qué pasa con EPCIS? ¿No es ese el estándar de GS1 para esto? Distinción importante:
- Un DPP es la descripción estática de un artículo de producto: su identidad, materiales, huella de carbono, reciclabilidad. Responde a "¿qué es esta cosa?". El JSON-LD de arriba es esa instantánea.
- EPCIS 2.0 es el estándar de GS1 para los eventos de la cadena de suministro: los datos de visibilidad de qué ocurrió, dónde, cuándo y por qué: un artículo fue puesto en circulación, enviado, recibido, reciclado. Responde a "¿qué le ha ocurrido a esta cosa y dónde está?".
Son complementarios, no competidores. El pasaporte te dice que el producto es una batería de 5,2 kWh con un 35 % de contenido reciclado; un rastro de eventos EPCIS te diría que se fabricó en Hamburgo en una fecha determinada, se envió a través de un centro de distribución y llegó a un reciclador. EPCIS 2.0 en sí mismo es compatible con JSON/JSON-LD, así que ambos comparten la misma visión del mundo de Linked Data y los mismos identificadores de GS1 (GTIN + serial) como clave de unión.
Alcance de qr3 (sé preciso): qr3 emite el DPP como JSON-LD: eso es lo que demuestra este artículo. qr3 no proporciona captura de eventos EPCIS ni endpoints EPCIS. Considera aquí EPCIS 2.0 como el estándar conceptual y complementario que adoptarías junto a un DPP para lograr una trazabilidad completa de la cadena de suministro, no como una funcionalidad de qr3.
Así que el modelo mental es: el DPP (qr3, JSON-LD) es la ficha de identidad del producto; EPCIS 2.0 (sistema independiente) es su registro de viaje. Mismos identificadores, dos preguntas respondidas.
Generar un DPP que exponga JSON-LD
No tienes que hacer nada especial para "activar" JSON-LD: crea el pasaporte y el resolver sirve cada representación automáticamente:
import { QR3 } from "@qr3/sdk";
const client = new QR3({ apiKey: process.env.QR3_API_KEY! });
const passport = await client.dpp.create({
gtin: "04019999999902",
serial: "SN-00012345",
product_name: "PowerCell 5 kWh LFP",
manufacturer: "ExampleTech GmbH",
origin_country: "DE",
category: "battery",
market_countries: ["DE", "FR", "AT"],
status: "live",
battery_data: {
capacity_kwh: 5,
carbon_footprint_kg: 62,
recycled_content_pct: 12,
recyclability_pct: 95,
},
});
// El pasaporte ahora se resuelve en https://qr3.app/dpp/04019999999902/SN-00012345
// Las personas obtienen HTML; las máquinas añaden ?format=jsonld (o envían Accept: application/ld+json).
console.log(passport.qr.svg); // El QR codifica el GS1 Digital Link al resolver
Una vez creado, la URL del artículo responde a ambos públicos de inmediato: sin ningún paso de publicación adicional para la vista de máquina.
Preguntas frecuentes
¿Por qué JSON-LD y no JSON plano?
El JSON plano es estructurado pero no autodescriptivo: el consumidor tiene que aprender los nombres de tus campos. JSON-LD añade @context, que asigna cada clave a términos de schema.org / GS1, de modo que cualquier consumidor de Linked Data lo entiende sin una integración personalizada. Si solo necesitas una lectura rápida, ?format=json sigue disponible.
¿qr3 implementa EPCIS 2.0? No. qr3 emite el DPP como JSON-LD. EPCIS 2.0 es el estándar de GS1 independiente y complementario para los eventos de la cadena de suministro; lo ejecutarías en paralelo, unido por el GTIN + serial compartidos.
¿Cómo obtengo la vista de máquina?
Añade ?format=jsonld a la URL del resolver, o envía Accept: application/ld+json. Ambos devuelven la misma carga útil de Linked Data.
¿Es estable el @context?
Fija schema.org más el vocabulario web de GS1 (gs1.org/voc/): ambos son vocabularios públicos y versionados, de modo que los consumidores pueden confiar en el significado de los términos.
Fuentes
- JSON-LD 1.1 (Recomendación del W3C)
- Vocabulario web de GS1
- GS1 EPCIS y CBV 2.0
- schema.org Product
- ESPR — Reglamento (UE) 2024/1781
Empieza gratis y crea un DPP que exponga JSON-LD: app.qr3.app/sign-up