Primer plazo DPP de la UE (Baterías): 130 días Cumpla ahora
Idioma
EN DE FR IT ES NL PL BG CS DA EL ET FI HR HU LT LV MT PT RO SK SL SV
Producto
Funcionalidades Posventa Cómo funciona Demostración Enterprise Precios
Sectores
Todos los sectores Textiles Electrónica Baterías
Recursos
Blog Comparar software DPP Requisitos por país Evaluación de preparación Comprobador de afirmaciones ecológicas Descargas gratuitas Glosario
Empresa
Partners Contacto
Iniciar sesión Comience gratis
Desarrolladores / REST API

Referencia de la API

Todo MyProductPassport está disponible mediante una API REST autenticada con clave: cree productos, genere y publique pasaportes digitales de producto, envíe datos de batería en tiempo real y compruebe la conformidad, directamente desde su ERP, PIM o canal de compilación.

v1 https://myproductpassport.eu/api/v1 Empezar gratis Especificación OpenAPI ↓

01 / Primeros pasosAutenticación

Cada solicitud se autentica con una clave API enviada como token Bearer. Las claves se crean en la aplicación, en Claves API, se muestran una sola vez y se guardan con hash; cada clave tiene su propio conjunto de permisos, una lista opcional de IP permitidas y una fecha de caducidad opcional. Las claves se pueden rotar sin interrupciones.

Cabecera de la solicitud
Authorization: Bearer pk_your_api_key
En todos los planes. Las claves API se pueden crear y usar en todos los planes, incluido el gratuito. El plan determina cuántas solicitudes por minuto puede hacer una clave (abajo) y cuántos productos y pasaportes puede tener el espacio de trabajo.
Modo de prueba. Una clave de prueba (pk_test_...) ejecuta cada llamada exactamente igual que una clave de producción, con la misma validación, los mismos ids y las mismas respuestas, y después la deshace: no se guarda nada, no se envía ningún correo electrónico ni webhook y no se conserva ningún archivo. Las respuestas incluyen "test_mode": true y una cabecera X-MPP-Mode: test. Cree y pruebe una integración con sus datos reales y, después, pase a usar una clave de producción.

Los permisos se conceden por clave, de modo que una integración solo obtiene lo que necesita:

PermisoConcesiones
products:readLeer productos
products:writeCrear, actualizar y eliminar productos
passports:readLeer pasaportes
passports:writeGenerar pasaportes
passports:publishPublicar y archivar pasaportes
webhooks:manageCrear, probar y eliminar endpoints de webhook
items:readRead individual items and their history
items:writeAdd, update and flag individual items
aftersales:readRead owner registrations and service requests
aftersales:writeUpdate service requests and reply to customers

02 / Primeros pasosLímites de solicitudes

Los límites son por clave y por minuto, y dependen del plan:

PlanSolicitudes / minuto
Gratuito30
Micro60
E-Label60
Starter120
Professional300
Business600
Battery600

Cada respuesta incluye las cabeceras X-RateLimit-Limit y X-RateLimit-Remaining. Si se supera el límite se devuelve 429:

429 Too Many Requests
{ "error": "Rate limit exceeded.", "limit": 300, "retry_after": 60 }

03 / Primeros pasosErrores

Los errores se devuelven en JSON con un código de estado habitual. Los más comunes:

EstadoSignificadoCuerpo de ejemplo
401Clave ausente, no válida, revocada o caducada{"error": "Invalid or revoked API key."}
403A la clave le falta un permiso, la IP no está en la lista permitida o se ha alcanzado el cupo del plan{"message": "API key does not have 'products:write' permission."}
404El recurso no existe en su espacio de trabajo{"message": "Not found."}
422La validación ha fallado{"message": "…", "errors": {"gtin": ["…"]}}
429Límite de solicitudes superado{"error": "Rate limit exceeded."}

04 / Primeros pasosPaginación

Los endpoints de listado devuelven 25 elementos por página con los objetos links y meta estándar. Pase ?page=2 para recorrer la colección.

05 / Primeros pasosConector de asistente de IA (MCP)

Conecta Claude, Cursor o cualquier asistente que hable el Model Context Protocol y pídele con tus palabras que cree productos, rellene pasaportes con lo que le digas y compruebe lo que falta. Usa una clave API con sus permisos y su límite de solicitudes. Puede crear borradores y rellenar campos; nunca publica, archiva ni elimina nada: eso sigue en tus manos en la aplicación.

Dirección del servidor (Streamable HTTP)
https://myproductpassport.eu/api/mcp
Claude Code
claude mcp add --transport http myproductpassport https://myproductpassport.eu/api/mcp \
  --header "Authorization: Bearer pk_live_your_key"
Cursor (mcp.json)
{
  "mcpServers": {
    "myproductpassport": {
      "url": "https://myproductpassport.eu/api/mcp",
      "headers": { "Authorization": "Bearer pk_live_your_key" }
    }
  }
}
Claude Desktop y otros clientes que inician un servidor local
{
  "mcpServers": {
    "myproductpassport": {
      "command": "npx",
      "args": ["mcp-remote", "https://myproductpassport.eu/api/mcp", "--header", "Authorization: Bearer pk_live_your_key"]
    }
  }
}

Las herramientas que ofrece:

HerramientaQué hace
list_productsLos productos del espacio de trabajo, del más reciente al más antiguo, 25 por página, con su sector y su último pasaporte.
get_productUn producto con sus datos, sector, secciones normativas y último pasaporte.
list_sectorsLas plantillas de sector que puede usar un producto (textil, electrónica, baterías, vino y más), con sus identificadores. El sector de un producto decide qué campos del pasaporte son obligatorios.
create_productAñade un producto al espacio de trabajo. Usa un sector_id de list_sectors. compliance_sections añade secciones normativas a su pasaporte: gpsr, epr, france, chemicals, eudr.
list_passportsLos pasaportes del espacio de trabajo, del más reciente al más antiguo, 25 por página, con su estado (draft, published, archived), porcentaje de cumplimiento y dirección pública.
get_passportUn pasaporte: estado, versión, porcentaje de cumplimiento, dirección pública y enlaces al código QR.
create_passportCrea un pasaporte en borrador para un producto. No se publica: lo publica una persona en la aplicación.
get_passport_fieldsLo que pide un pasaporte: las claves de los campos obligatorios y opcionales, qué significa cada uno (etiqueta, descripción, ejemplo), los valores que tiene y qué campos obligatorios faltan.
update_passport_fieldsEscribe valores de campos en un pasaporte en borrador o publicado (uno publicado se actualiza en el sitio: misma dirección, mismo código QR). Claves de get_passport_fields; un texto vacío elimina un valor. Escribe solo hechos que indiquen el usuario o sus documentos.
get_complianceLa completitud de un pasaporte: porcentaje, estado y los campos obligatorios que aún faltan.
Pruébalo con una clave de prueba. Con una clave de prueba (pk_test_...) los cambios del asistente se comprueban y luego se deshacen, para que veas lo que haría antes de darle una clave real.

06 / EndpointsCuenta

GET /me

Devuelve la cuenta autenticada, su plan de suscripción y cuánto se ha usado del límite de productos. Útil como comprobación de conexión.

Solicitud
curl https://myproductpassport.eu/api/v1/me \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": {
    "id": 42,
    "name": "Jane Doe",
    "email": "[email protected]",
    "company_name": "Acme Ltd",
    "subscription_tier": "professional",
    "product_count": 128,
    "product_limit": 500,
    "passport_count": 96,
    "organization": {"id": 7, "name": "Acme Ltd"},
    "api_key": {"name": "ERP sync", "permissions": ["*"], "rate_limit_per_minute": 1000, "expires_at": null},
    "webhooks_available": true
  }
}

07 / EndpointsProductos

GET /products requiere products:read

Lista los productos de su espacio de trabajo, del más reciente al más antiguo, 25 por página. Cada producto incluye su sector y un resumen de su pasaporte más reciente.

ParámetroTipoDescripción
pageintegerNúmero de página.
Solicitud
curl "https://myproductpassport.eu/api/v1/products?page=1" \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": [
    {
      "id": 512,
      "name": "Alpine Merino Crew Sweater",
      "sku": "AM-CREW-01",
      "gtin": "05012345678900",
      "brand": "Northloom",
      "category": "textiles",
      "status": "active",
      "country_of_origin": "PT",
      "weight": 0.4,
      "weight_unit": "kg",
      "materials": [
        { "name": "Merino wool (RWS)", "percentage": 78 },
        { "name": "Recycled nylon (GRS)", "percentage": 20 },
        { "name": "Elastane", "percentage": 2 }
      ],
      "sector": { "id": 3, "name": "Textiles" },
      "latest_passport": {
        "id": 96, "version": 1,
        "status": "published", "compliance_percentage": 100
      },
      "created_at": "2026-08-14T09:21:00+00:00",
      "updated_at": "2026-09-01T16:02:11+00:00"
    }
  ],
  "links": { "next": null },
  "meta": { "current_page": 1, "per_page": 25, "total": 1 }
}
POST /products requiere products:write

Crea un producto. Falla con 403 si se ha agotado el cupo de productos del plan.

ParámetroTipoDescripción
namestringobligatorioNombre del producto, hasta 255 caracteres.
skustringSu SKU interno, hasta 100 caracteres.
gtinstringGTIN-8, 12, 13 o 14 (solo dígitos).
brandstringMarca que se muestra en el pasaporte público.
descriptionstringHasta 2.000 caracteres.
categorystringCategoría de texto libre. Por defecto, «general».
sector_idintegerUn identificador de sector, que selecciona la plantilla de campos del pasaporte.
country_of_originstringCódigo de país, p. ej. «PT».
weightnumberPeso neto.
weight_unitstringUno de kg, g, lb, oz. Por defecto, kg.
materialsarrayObjetos de {name, percentage 0-100}.
has_packagingbooleanAñade al pasaporte los campos de la plantilla de embalaje (claves que empiezan por pkg_), con el mismo código QR.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/products \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Alpine Merino Crew Sweater",
    "sku": "AM-CREW-01",
    "gtin": "05012345678900",
    "sector_id": 3,
    "materials": [
      {"name": "Merino wool (RWS)", "percentage": 78},
      {"name": "Recycled nylon (GRS)", "percentage": 22}
    ]
  }'
Respuesta
{
  "data": {
    "id": 513,
    "name": "Alpine Merino Crew Sweater",
    "sku": "AM-CREW-01",
    "status": "active",
    "sector": { "id": 3, "name": "Textiles" },
    "created_at": "2026-09-07T18:40:00+00:00"
  }
}
POST /products/bulk requiere products:write

Crea hasta 100 productos en una llamada. Todo el lote se rechaza con 403 si superara el cupo de productos restante. Para catálogos de miles de artículos, llame a este endpoint en bucle o use la importación CSV de la aplicación.

ParámetroTipoDescripción
productsarrayobligatorioDe 1 a 100 objetos de producto con los mismos campos que «Crear un producto» (sin materiales).
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/products/bulk \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      {"name": "PSL-BT-122000", "sku": "PSL-BT-122000", "sector_id": 5},
      {"name": "PSL-BT-123000", "sku": "PSL-BT-123000", "sector_id": 5}
    ]
  }'
Respuesta
{
  "message": "2 product(s) created.",
  "products": [
    { "id": 514, "name": "PSL-BT-122000", "status": "active" },
    { "id": 515, "name": "PSL-BT-123000", "status": "active" }
  ]
}
GET /products/{id} requiere products:read

Devuelve un producto con su sector y un resumen de su pasaporte más reciente. 404 si el id no está en su espacio de trabajo.

Solicitud
curl https://myproductpassport.eu/api/v1/products/512 \
  -H "Authorization: Bearer pk_your_key"
PUT /products/{id} requiere products:write

Actualiza parcialmente un producto. Envíe solo los campos que quiera cambiar; la lista de campos es la misma que en Crear un producto.

Solicitud
curl -X PUT https://myproductpassport.eu/api/v1/products/512 \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"brand": "Northloom"}'
DELETE /products/{id} requiere products:write

Elimina un producto de forma lógica (soft delete). Los pasaportes publicados del producto siguen funcionando, de modo que los códigos QR impresos nunca quedan huérfanos.

Solicitud
curl -X DELETE https://myproductpassport.eu/api/v1/products/512 \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{ "message": "Product deleted." }

08 / EndpointsPasaportes

GET /passports requiere passports:read

Lista los pasaportes, del más reciente al más antiguo, 25 por página, con resumen del producto y todos los campos del pasaporte.

ParámetroTipoDescripción
pageintegerNúmero de página.
Solicitud
curl https://myproductpassport.eu/api/v1/passports \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": [
    {
      "id": 96,
      "uuid": "36ff3776-d517-4228-8cde-9208136ea84a",
      "version": 1,
      "status": "published",
      "compliance_status": "compliant",
      "compliance_percentage": 100,
      "public_url": "https://myproductpassport.co.uk/p/36ff3776-…",
      "gs1_url": "https://myproductpassport.co.uk/01/05012345678900",
      "product": { "id": 512, "name": "Alpine Merino Crew Sweater", "sku": "AM-CREW-01" },
      "fields": [
        { "key": "material_composition", "value": "…", "verification_status": "verified" }
      ],
      "published_at": "2026-08-16T10:00:00+00:00"
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 1 }
}
POST /products/{productId}/passports requiere passports:write

Genera un pasaporte en borrador para un producto y rellena los campos a partir de los datos del producto y la plantilla del sector. Devuelve el borrador con su puntuación de conformidad. Si el producto ya tiene un pasaporte publicado, devuelve 409 con ese pasaporte: corríjalo con PUT /passports/{id}/fields, que conserva su dirección y su código QR.

Solicitud
curl -X POST https://myproductpassport.eu/api/v1/products/512/passports \
  -H "Authorization: Bearer pk_your_key"
GET /passports/{id} requiere passports:read

Devuelve un pasaporte con el producto, los campos, la URL pública y el GS1 Digital Link.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96 \
  -H "Authorization: Bearer pk_your_key"
POST /passports/{id}/publish requiere passports:publish

Publica un borrador de pasaporte y activa su página pública y su código QR. Solo se pueden publicar borradores; cualquier otro estado devuelve 404.

Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/publish \
  -H "Authorization: Bearer pk_your_key"
POST /passports/{id}/archive requiere passports:publish

Archiva un pasaporte y retira su página pública de la circulación.

Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/archive \
  -H "Authorization: Bearer pk_your_key"
POST /passports/bulk-publish requiere passports:publish

Publica hasta 50 borradores de pasaporte en una sola llamada e informa del resultado de cada uno, de modo que un fallo nunca aborta el lote.

ParámetroTipoDescripción
passport_idsarrayobligatorioDe 1 a 50 identificadores de pasaporte.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/bulk-publish \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"passport_ids": [96, 97, 98]}'
Respuesta
{
  "published": 2,
  "failed": 1,
  "published_ids": [96, 97],
  "errors": [
    { "id": 98, "error": "Compliance below the publishing threshold." }
  ]
}
POST /passports/{id}/successor requiere passports:write

Para un producto preparado para su reutilización, reconvertido o refabricado, el Reglamento de Pilas y Baterías (artículo 77, apartado 7) exige un nuevo pasaporte vinculado al original. Esto crea un nuevo registro de producto y un pasaporte en borrador rellenado a partir del publicado y vinculado a él. El original sigue publicado y ambos pasaportes muestran el vínculo. Publique el nuevo con POST /passports/{id}/publish.

ParámetroTipoDescripción
stagestringobligatorioprepared_for_reuse, repurposed o remanufactured.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/successor \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "stage": "repurposed" }'
Respuesta
{
  "data": {
    "id": 131, "status": "draft", "version": 1,
    "lineage": {
      "stage": "repurposed",
      "original": { "id": 96, "url": "https://myproductpassport.co.uk/p/..." },
      "originals": [{ "passport_id": 96, "product_id": 40, "stage": "repurposed", "status": "published", "url": "https://myproductpassport.co.uk/p/..." }],
      "successors": []
    }
  }
}
GET /passports/{id}/fields requiere passports:read

Devuelve las claves de campo que pide la plantilla del sector del pasaporte (obligatorias y opcionales), los valores actuales y qué claves obligatorias faltan todavía. Úselo para construir el cuerpo de PUT /passports/{id}/fields.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/fields \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "passport_id": 96,
  "sector": "batteries",
  "compliance_percentage": 84,
  "required": ["battery_category", "carbon_footprint", "..."],
  "optional": ["energy_round_trip_efficiency", "..."],
  "missing_required": ["carbon_footprint_class", "recycled_content"],
  "values": { "battery_category": "Industrial", "...": "..." }
}
PUT /passports/{id}/fields requiere passports:write

Escribe cualquier conjunto de valores de campo en un pasaporte en borrador o publicado: el conjunto completo del anexo XIII para una batería, los campos de una plantilla de sector o sus propias claves. Envíe solo las claves que quiera cambiar; un valor nulo o vacío elimina ese campo. Un pasaporte publicado se actualiza en el mismo sitio, su dirección y su código QR no cambian y sus traducciones automáticas se regeneran. El cumplimiento se vuelve a puntuar. Esta llamada no publica un borrador; use POST /passports/{id}/publish.

ParámetroTipoDescripción
fieldsobjectobligatorioMapa de clave de campo a valor. Las claves son letras minúsculas, dígitos y guiones bajos; los valores, de hasta 5.000 caracteres. Hasta 200 claves por llamada.
Solicitud
curl -X PUT https://myproductpassport.eu/api/v1/passports/96/fields \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "carbon_footprint": "61.2 kg CO2e/kWh",
      "carbon_footprint_class": "C",
      "recycled_content": "Cobalt 16%, lithium 6%, nickel 6%, lead 0%"
    }
  }'
Respuesta
{
  "message": "3 field(s) changed, 0 removed.",
  "changed": ["carbon_footprint", "carbon_footprint_class", "recycled_content"],
  "removed": [],
  "passport": { "id": 96, "status": "published", "compliance_percentage": 92 }
}
POST /passports/{id}/state-of-health requiere passports:write

Envía los datos propios de esta batería (anexo XIII, punto 4, del Reglamento (UE) 2023/1542) a un pasaporte publicado, para sistemas BMS y de flotas. Envíe cualquier subconjunto de los campos siguientes; el cumplimiento se vuelve a comprobar tras la actualización. Estos valores solo se muestran a los visitantes aprobados por el titular del pasaporte (artículo 77, apartado 2), nunca en la página pública. capacity_fade, power_capability e internal_resistance se guardan como lecturas actuales de esta batería (current_*), separadas de los valores originales del modelo.

ParámetroTipoDescripción
state_of_healthstringp. ej., «97 % a los 412 ciclos».
state_of_certified_energystringEnergía certificada restante (baterías de vehículos eléctricos).
battery_statusstringoriginal, repurposed, re-used, remanufactured o waste.
capacity_fadestringPérdida de capacidad hasta la fecha. Se guarda como current_capacity_fade.
power_capabilitystringCapacidad de potencia actual. Se guarda como current_power_capability.
internal_resistancestringResistencia interna medida. Se guarda como current_internal_resistance.
use_datastringCiclos, incidentes negativos, temperatura y estado de carga, hasta 5000 caracteres.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/state-of-health \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "state_of_health": "97% at 412 cycles",
    "capacity_fade": "3% from initial rated capacity"
  }'
Respuesta
{
  "message": "2 field(s) updated.",
  "updated_fields": ["state_of_health", "current_capacity_fade"],
  "passport": { "id": 96, "status": "published", "compliance_percentage": 100 }
}
POST /passports/{id}/units requiere passports:write

Cada batería necesita su propio pasaporte (Reglamento (UE) 2023/1542, artículo 77, apartado 1). Registre hasta 10 000 baterías de un modelo en una llamada, cada una con su número de serie (hasta 20 letras, dígitos, puntos, guiones o guiones bajos) y, opcionalmente, manufacturing_date, battery_status y sus datos del anexo XIII, punto 4. Los números de serie existentes se actualizan; los valores omitidos se conservan. Si el producto tiene GTIN, la dirección de cada batería es su GS1 Digital Link, /01/{gtin}/21/{serial}. Los datos del punto 4 solo los ven las personas que el titular autorice.

ParámetroTipoDescripción
units[].serialstringobligatorioEl número de serie de la batería.
units[].manufacturing_datestringMes y año, p. ej. "2026-09".
units[].battery_statusstringoriginal o waste. Un cambio de estado necesita los valores medidos en él (anexo XIII, punto 4, letra a)); waste también necesita responsible_party_type (producer, pro o waste_operator), responsible_party_name y responsible_party_contact (artículo 77, apartado 7). recycled, con recycled_at y recycler_name, pone fin al pasaporte (artículo 77, apartado 8). Una batería reconvertida, reutilizada o refabricada recibe un nuevo pasaporte: POST /passports/{id}/units/{serial}/successor.
units[].state_of_healthstringTambién state_of_certified_energy, current_capacity_fade, current_power_capability, current_internal_resistance, remaining_capacity_ah, power_fade, internal_resistance_increase, round_trip_efficiency, round_trip_efficiency_fade, expected_lifetime_cycles_remaining, self_discharge_rate, ohmic_resistance y use_data.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/units \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"units": [{"serial": "KES-00001", "manufacturing_date": "2026-09", "state_of_health": "100%"}]}'
Respuesta
{ "created": 1, "updated": 0, "skipped": 0, "errors": [] }
PATCH /passports/{id}/units/{serial} requiere passports:write

Para un sistema de gestión de baterías que envía los datos de una batería: cualquiera de battery_status, state_of_health, state_of_certified_energy, current_capacity_fade, current_power_capability, current_internal_resistance y use_data. Haga GET a la misma ruta para leerlos, o GET /passports/{id}/units para la lista (per_page hasta 500).

Solicitud
curl -X PATCH https://myproductpassport.eu/api/v1/passports/96/units/KES-00001 \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"state_of_health": "96% at 412 cycles"}'
Respuesta
{
  "data": { "serial": "KES-00001", "public_url": "https://myproductpassport.co.uk/01/05012345678900/21/KES-00001", "battery_status": "original", "data": { "state_of_health": "96% at 412 cycles" } }
}
GET /passports/{id}/units/{serial}/snapshots requiere passports:read

El anexo XIII, punto 4, letra a), exige los valores de rendimiento y durabilidad cuando la batería se introduce en el mercado y cuando cambia su estado. Esas lecturas se conservan tal como eran, independientemente de lo que se envíe después; envíe record_snapshot: true con un PATCH para conservar también una lectura periódica.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/units/KES-00001/snapshots \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": [
    { "event": "placed_on_market", "status": "original", "values": { "state_of_health": "100%" }, "measured_at": "2026-09-26T09:00:00+00:00", "source": "api" },
    { "event": "status_change", "status": "waste", "values": { "remaining_capacity_ah": "71 Ah", "power_fade": "14%", "internal_resistance_increase": "22%", "expected_lifetime_cycles_remaining": "0" }, "measured_at": "2029-03-02T10:00:00+00:00", "source": "bms" }
  ]
}
POST /passports/{id}/units/{serial}/successor requiere passports:write

Artículo 77, apartado 7: una batería que ha sido preparada para la reutilización, reconvertida o refabricada tiene un nuevo pasaporte vinculado a su original. Esto registra la batería de nuevo, con un nuevo número de serie e identificador, bajo un modelo de batería de segunda vida de su espacio de trabajo (creado a partir de este modelo si aún no existe), vincula ambas y conserva los valores medidos en el cambio. La batería original conserva su pasaporte. Complete y publique el modelo de segunda vida con POST /passports/{id}/publish.

ParámetroTipoDescripción
stagestringobligatorioprepared_for_reuse, repurposed o remanufactured.
valuesobjectobligatorioLos valores medidos en el cambio: al menos uno de remaining_capacity_ah o current_capacity_fade, de current_power_capability o power_fade, de current_internal_resistance o internal_resistance_increase, y expected_lifetime_cycles_remaining (anexo IV, parte A).
serialstringEl nuevo número de serie. Por defecto: el número de serie original más -RU, -RP o -RM.
measured_atstringCuándo se midieron los valores.
member_statestringCódigo de dos letras del Estado miembro en el que se evaluó el estado de salud (artículo 73, apartado 1, letra a)).
target_passport_idintegerUn modelo de segunda vida existente de este modelo de batería en el que registrarla.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/units/KES-00001/successor \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"stage": "repurposed", "values": {"remaining_capacity_ah": "82 Ah", "power_fade": "9%", "internal_resistance_increase": "15%", "expected_lifetime_cycles_remaining": "2000"}}'
Respuesta
{
  "data": {
    "serial": "KES-00001-RP", "battery_status": "repurposed", "passport_id": 131,
    "lineage": { "originals": [{ "serial": "KES-00001", "passport_id": 96, "stage": "repurposed" }], "successors": [] }
  }
}
POST /passports/{id}/registry requiere passports:write

Guarda en un pasaporte el envío al registro de DPP de la UE y su resultado: estado, ID de correlación, el identificador de registro que devuelve el registro y un enlace opcional a una copia de seguridad alojada por un proveedor de servicios DPP. El registro en sí se realiza en el registro de la Comisión (formulario web o carga de archivo); esto conserva el resultado junto al pasaporte. GET /passports/{id} devuelve el mismo bloque en registry.

ParámetroTipoDescripción
statusstringnot_submitted, submitted, registered o failed.
product_groupstringGrupo de productos del registro, por ejemplo batteries.
granularitystringmodelo, lote o artículo.
upistringIdentificador único de producto como URL https. Por defecto, la URL del pasaporte público.
correlation_idstringIdentificador de correlación asignado por el Registro al enviar.
uristringIdentificador de registro devuelto por el registro.
backup_urlstringEnlace https a la copia de seguridad alojada por un proveedor de servicios DPP.
submitted_atdateFecha de envío.
registered_atdateFecha de registro.
errorstringDescripción del error de un envío fallido.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/registry \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "registered",
    "correlation_id": "7f3a2c1e-0b4d-4f8e-9a6b-2d1c3e4f5a6b",
    "uri": "urn:eu:dpp:reg:00000001",
    "registered_at": "2027-02-18"
  }'
Respuesta
{
  "message": "Registry details updated.",
  "passport": {
    "id": 96,
    "registry": {
      "status": "registered",
      "upi": "https://myproductpassport.co.uk/p/552fbb4e-5d9a-41da-9050-cc9005d8b66b",
      "correlation_id": "7f3a2c1e-0b4d-4f8e-9a6b-2d1c3e4f5a6b",
      "uri": "urn:eu:dpp:reg:00000001",
      "registered_at": "2027-02-18T00:00:00+00:00"
    }
  }
}
GET /passports/{id}/qr requiere passports:read

El código QR del pasaporte como archivo: svg (por defecto), png (con marca, listo para imprimir) o pdf (hoja de etiquetas).

ParámetroTipoDescripción
formatstringsvg | png | pdf
Solicitud
curl "https://myproductpassport.eu/api/v1/passports/96/qr?format=png" \
  -H "Authorization: Bearer pk_your_key" -o passport-96.png

09 / EndpointsConformidad

GET /passports/{passportId}/compliance requiere passports:read

Ejecuta una comprobación de cumplimiento en vivo de un pasaporte frente a los campos obligatorios de su sector e indica exactamente qué falta.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/compliance \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": {
    "passport_id": 96,
    "product_name": "Alpine Merino Crew Sweater",
    "status": "compliant",
    "percentage": 100,
    "completed_fields": 12,
    "total_fields": 12,
    "missing_fields": []
  }
}

10 / EndpointsSectores

GET /sectors

Los sectores en los que se puede clasificar un producto: los sectores del sistema de la plataforma más los que haya definido su espacio de trabajo. Use el id al crear productos y las claves de campo al escribir campos del pasaporte.

Solicitud
curl https://myproductpassport.eu/api/v1/sectors \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": [
    {
      "id": 4,
      "slug": "batteries",
      "name": "Batteries",
      "system": true,
      "regulations_finalised": true,
      "deadline": "2027-02-18",
      "deadline_label": "18 Feb 2027",
      "required_fields": ["battery_category", "battery_weight", "..."],
      "optional_fields": ["energy_round_trip_efficiency", "..."]
    }
  ]
}

11 / EndpointsDocumentos

GET /products/{productId}/documents requiere products:read

Declaraciones de conformidad, informes de ensayo y certificados adjuntos al producto. Los documentos públicos se enlazan desde cada pasaporte publicado del producto.

Solicitud
curl https://myproductpassport.eu/api/v1/products/512/documents \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": [
    {
      "id": 31,
      "product_id": 512,
      "filename": "declaration-of-conformity.pdf",
      "mime_type": "application/pdf",
      "file_size": 184322,
      "is_public": true,
      "processing_status": "completed",
      "public_url": "https://myproductpassport.co.uk/p/3f0c.../document/31",
      "created_at": "2026-09-22T10:12:00+00:00"
    }
  ]
}
POST /products/{productId}/documents requiere products:write

Carga multipart. PDF, Word, Excel, CSV, texto, PNG y JPEG de hasta 10 MB, como máximo 20 por producto. El texto se extrae en segundo plano.

ParámetroTipoDescripción
filefileobligatorioEl documento.
is_publicbooleanMostrarlo en el pasaporte público (por defecto false).
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/products/512/documents \
  -H "Authorization: Bearer pk_your_key" \
  -F "[email protected]" \
  -F "is_public=1"
PATCH /products/{productId}/documents/{id} requiere products:write

Indica si el documento se enlaza desde el pasaporte público.

ParámetroTipoDescripción
is_publicbooleanobligatorio
Solicitud
curl -X PATCH https://myproductpassport.eu/api/v1/products/512/documents/31 \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"is_public": false}'
DELETE /products/{productId}/documents/{id} requiere products:write

Elimina el archivo y su vínculo con el pasaporte.

Solicitud
curl -X DELETE https://myproductpassport.eu/api/v1/products/512/documents/31 \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{ "message": "Document deleted." }

12 / EndpointsCadena de suministro

GET /products/{productId}/supply-chain requiere products:read

Los pasos que se muestran en el pasaporte del producto, en orden.

Solicitud
curl https://myproductpassport.eu/api/v1/products/512/supply-chain \
  -H "Authorization: Bearer pk_your_key"
PUT /products/{productId}/supply-chain requiere products:write

Sustituye todos los pasos por la lista que envíe, en el orden enviado. Envíe una lista vacía para borrarla. Tipos de paso: raw_material, processing, manufacturing, assembly, packaging, distribution.

ParámetroTipoDescripción
stepsarrayobligatorioHasta 50 pasos.
steps[].step_typestringobligatorio
steps[].supplier_namestringobligatorio
steps[].supplier_locationstring
steps[].supplier_countrystringISO 3166-1 alfa-2.
steps[].lat / lngnumber
steps[].descriptionstring
steps[].certificationsarray
steps[].datedate
Solicitud
curl -X PUT https://myproductpassport.eu/api/v1/products/512/supply-chain \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"steps": [{"step_type": "raw_material", "supplier_name": "Merino Growers Co-op", "supplier_country": "NZ", "certifications": ["RWS"]}, {"step_type": "manufacturing", "supplier_name": "Northloom Mill", "supplier_location": "Biella", "supplier_country": "IT"}]}'

13 / EndpointsTraducciones

GET /passports/{id}/translations requiere passports:read

Cada valor de campo traducido por idioma, con su origen: auto (automático, generado al publicar) o manual.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/translations \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": {
    "passport_id": 96,
    "available_locales": ["bg", "cs", "da", "de", "..."],
    "translations": {
      "de": {"care_instructions": {"value": "Kalt waschen", "source": "manual"}}
    }
  }
}
PUT /passports/{id}/translations/{locale} requiere passports:write

Define las traducciones de un idioma, por clave de campo. Una traducción manual nunca se sobrescribe automáticamente. Envíe una cadena vacía para eliminar una.

ParámetroTipoDescripción
fieldsobjectobligatoriofield_key: valor traducido
Solicitud
curl -X PUT https://myproductpassport.eu/api/v1/passports/96/translations/de \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"fields": {"care_instructions": "Kalt waschen, nicht bleichen"}}'
Respuesta
{ "message": "1 translation(s) written, 0 removed.", "locale": "de", "written": 1, "removed": 0 }

14 / EndpointsIntegridad y exportaciones

GET /passports/{id}/integrity requiere passports:read

Cada estado publicado del pasaporte como un registro encadenado por hash y firmado con Ed25519: huella digital (SHA-256), valor de la cadena y firma. Las claves públicas están en /.well-known/mpp-integrity-keys.json, de modo que cualquiera puede verificar la cadena.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/integrity \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{ "data": { "state": "intact", "hash_algorithm": "SHA-256", "signature_algorithm": "Ed25519", "records": [ { "sequence": 1, "event": "published", "content_hash": "8f3a...", "chain_hash": "c21e...", "signature": "MEUC...", "key_id": "3fa9c21e0b7d4a11" } ], "problems": [] } }
GET /passports/{id}/integrity/{sequence} requiere passports:read

El registro completo tal como se firmó, instantánea incluida: lo que decía el pasaporte en ese momento, hasta el hash de cada archivo adjunto.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/integrity/1 \
  -H "Authorization: Bearer pk_your_key"
GET /passports/{id}/epcis requiere passports:read

El pasaporte como documento JSON-LD de GS1 EPCIS 2.0: el artículo puesto en servicio, cada etapa de la cadena de suministro como una observación, las baterías individuales y un pasaporte de segunda vida como una transformación. Los identificadores son URI de GS1 Digital Link cuando el producto tiene un GTIN.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/epcis \
  -H "Authorization: Bearer pk_your_key"

15 / EndpointsSolicitudes a proveedores

POST /passports/{id}/supplier-requests requiere passports:write

Envía por correo electrónico a un proveedor un enlace privado para rellenar los campos que usted elija, en su idioma. Nada llega al pasaporte hasta que alguien de su espacio de trabajo lo aprueba.

ParámetroTipoDescripción
supplier_namestringobligatorio
supplier_emailstringobligatorio
field_keysarrayobligatorioClaves de campo de la plantilla del pasaporte.
localestringIdioma del correo electrónico y del formulario, p. ej., de.
due_atdateFecha límite de respuesta; 14 días si se omite.
messagestring
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/supplier-requests \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"supplier_name": "Mei Chen", "supplier_email": "[email protected]", "field_keys": ["recycled_content_cobalt", "carbon_footprint"], "locale": "de"}'
GET /passports/{id}/supplier-requests requiere passports:read

Todas las solicitudes del pasaporte con su estado.

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/supplier-requests \
  -H "Authorization: Bearer pk_your_key"
GET /supplier-requests/{id} requiere passports:read

Una solicitud con las respuestas del proveedor, la nota y los nombres de los archivos adjuntos.

Solicitud
curl https://myproductpassport.eu/api/v1/supplier-requests/12 \
  -H "Authorization: Bearer pk_your_key"

16 / EndpointsPosventa

POST /passports/{id}/items requiere items:write

Dé a los artículos de un producto (cualquier sector excepto baterías, que usan /units) su propio número de serie: cada uno recibe su propia dirección y código QR, un código de autenticidad oculto para su etiqueta, y su propietario puede registrarlo. Envíe hasta 10.000 artículos o un rango. Con un GTIN, la dirección es el GS1 Digital Link /01/{gtin}/21/{serial}.

ParámetroTipoDescripción
items[].serialstringobligatorioHasta 20 letras, cifras, puntos, guiones o guiones bajos.
items[].batchstringLote, hasta 20 caracteres.
items[].manufactured_onstringFecha de fabricación, AAAA-MM-DD.
rangeobjectEn lugar de items: prefix, start, count, digits y batch, por ejemplo SN-00001 a SN-00500.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/passports/96/items \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"range": {"prefix": "SN-", "start": 1, "count": 500, "digits": 5, "batch": "B2026-10"}}'
Respuesta
{ "created": 500, "updated": 0, "skipped": 0, "over_limit": 0, "errors": [] }
GET /passports/{id}/items/{serial} requiere items:read

Un artículo con su dirección, estado, si está registrado y hasta cuándo dura su garantía, sus comprobaciones de autenticidad y su historial. Una clave con items:write obtiene también su código oculto, para imprimir. GET /passports/{id}/items los enumera (filtros status y batch, per_page hasta 500).

Solicitud
curl https://myproductpassport.eu/api/v1/passports/96/items/SN-00001 \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{
  "data": { "serial": "SN-00001", "status": "active", "url": "https://myproductpassport.co.uk/01/05012345678900/21/SN-00001", "registered": true, "warranty_ends_on": "2028-10-02", "events": [ { "type": "registered", "country": "IE", "at": "2026-10-03T09:12:00+00:00" } ] }
}
PATCH /passports/{id}/items/{serial} requiere items:write

Ponga status en stolen o recalled y su página avisará a quien lo escanee, con su status_note; un artículo robado no se puede registrar. retired desactiva su página. También se pueden cambiar batch y manufactured_on.

ParámetroTipoDescripción
statusstringactive, stolen, recalled o retired.
status_notestringSe muestra en la página del artículo, hasta 500 caracteres.
Solicitud
curl -X PATCH https://myproductpassport.eu/api/v1/passports/96/items/SN-00001 \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"status": "stolen", "status_note": "Reported stolen on 2 October 2026."}'
GET /owner-registrations requiere aftersales:read

Personas que registraron sus productos: nombre, correo, país, fecha de compra, tienda, fechas de garantía y si aceptaron novedades y ofertas (marketing_consent=1 solo enumera esos). Registros activos por defecto; status=pending, transferred o ended para los demás; since= para cambios posteriores a una fecha.

Solicitud
curl "https://myproductpassport.eu/api/v1/owner-registrations?marketing_consent=1&since=2026-10-01" \
  -H "Authorization: Bearer pk_your_key"
GET /service-requests requiere aftersales:read

Reparaciones, reclamaciones de garantía, devoluciones, recambios y preguntas enviadas desde sus pasaportes, las más recientes primero, con filtros status y type. GET /service-requests/{reference} añade la conversación.

Solicitud
curl "https://myproductpassport.eu/api/v1/service-requests?status=new" \
  -H "Authorization: Bearer pk_your_key"
POST /service-requests/{reference}/replies requiere aftersales:write

Su respuesta se envía al cliente por correo con un enlace a la página de su solicitud, en su idioma. internal: true añade una nota que solo ve su equipo. PATCH /service-requests/{reference} con un status la hace avanzar (se avisa al cliente cuando está en curso, resuelta o cerrada).

ParámetroTipoDescripción
bodystringobligatorioLa respuesta, hasta 5.000 caracteres.
internalbooleanUna nota para su equipo en lugar de una respuesta.
statusstringnew, in_progress, waiting, resolved o closed.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/service-requests/SR-7K3F9Q/replies \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"body": "A new lid is on its way today.", "status": "waiting"}'

17 / EndpointsEdiciones masivas e imágenes

PATCH /products/bulk-fields requiere products:write

Establece un dato del producto o un campo del pasaporte en hasta 5.000 productos. mode es set, fill (solo donde esté vacío) o clear. En la solicitud se actualizan hasta 100 productos; los conjuntos más grandes se ponen en cola (202).

ParámetroTipoDescripción
product_idsarrayobligatorio
targetstringobligatorioproduct | field
keystringobligatorio
valuestring
modestringset | fill | clear
Solicitud
curl -X PATCH https://myproductpassport.eu/api/v1/products/bulk-fields \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"product_ids": [12, 13, 14], "target": "field", "key": "warranty_period", "value": "10 years", "mode": "fill"}'
Respuesta
{ "data": { "changed": 2, "skipped": 1, "errors": [] } }
POST /products/{id}/images requiere products:write

Carga multipart de un archivo JPG, PNG o WebP (hasta 15MB, 8 por producto). La primera imagen es la portada del pasaporte público.

ParámetroTipoDescripción
imagefileobligatorio
altstringDescripción de la imagen.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/products/12/images \
  -H "Authorization: Bearer pk_your_key" \
  -F [email protected] -F alt="Front of the battery"
PUT /products/{id}/images/order requiere products:write

Pase image_ids en el orden que desee; la primera será la portada.

ParámetroTipoDescripción
image_idsarrayobligatorio
Solicitud
curl -X PUT https://myproductpassport.eu/api/v1/products/12/images/order \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"image_ids": [31, 30]}'
DELETE /products/{id}/images/{imageId} requiere products:write

Elimina la imagen y su archivo.

Solicitud
curl -X DELETE https://myproductpassport.eu/api/v1/products/12/images/31 \
  -H "Authorization: Bearer pk_your_key"

18 / EndpointsWebhooks

GET /webhooks requiere webhooks:manage

Los endpoints registrados para su espacio de trabajo. Los secretos no se incluyen aquí; obtenga un endpoint concreto para ver su secreto.

Solicitud
curl https://myproductpassport.eu/api/v1/webhooks \
  -H "Authorization: Bearer pk_your_key"
POST /webhooks requiere webhooks:manage

Registra una URL HTTPS pública para uno o más eventos. La respuesta incluye el secreto de firma. Se rechazan los hosts privados o internos.

ParámetroTipoDescripción
urlstringobligatorio
eventsarrayobligatorioCualquiera de los eventos indicados abajo.
Solicitud
curl -X POST https://myproductpassport.eu/api/v1/webhooks \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://erp.acme.example/mpp", "events": ["passport.published", "product.updated"]}'
Respuesta
{
  "data": {
    "id": 3,
    "url": "https://erp.acme.example/mpp",
    "events": ["passport.published", "product.updated"],
    "is_active": true,
    "failure_count": 0,
    "secret": "9f1c...64 hex characters...",
    "created_at": "2026-09-22T10:12:00+00:00"
  }
}
GET /webhooks/{id} requiere webhooks:manage

Solicitud
curl https://myproductpassport.eu/api/v1/webhooks/3 \
  -H "Authorization: Bearer pk_your_key"
PUT /webhooks/{id} requiere webhooks:manage

Cambie la URL o los eventos, o páuselo y reanúdelo. Al reanudarlo se pone a cero el contador de fallos; un endpoint se pausa automáticamente tras 10 entregas fallidas consecutivas.

ParámetroTipoDescripción
urlstring
eventsarray
is_activeboolean
Solicitud
curl -X PUT https://myproductpassport.eu/api/v1/webhooks/3 \
  -H "Authorization: Bearer pk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"is_active": true}'
POST /webhooks/{id}/test requiere webhooks:manage

Pone en cola una entrega webhook.test para que pueda comprobar su receptor y su código de firma.

Solicitud
curl -X POST https://myproductpassport.eu/api/v1/webhooks/3/test \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{ "message": "Test delivery queued." }
GET /webhooks/{id}/deliveries requiere webhooks:manage

Entregas recientes, de la más reciente a la más antigua, con el estado HTTP que devolvió su endpoint y los primeros 500 caracteres del cuerpo.

ParámetroTipoDescripción
per_pageintegerHasta 100.
Solicitud
curl https://myproductpassport.eu/api/v1/webhooks/3/deliveries \
  -H "Authorization: Bearer pk_your_key"
DELETE /webhooks/{id} requiere webhooks:manage

Solicitud
curl -X DELETE https://myproductpassport.eu/api/v1/webhooks/3 \
  -H "Authorization: Bearer pk_your_key"
Respuesta
{ "message": "Webhook endpoint deleted." }

19 / EventosWebhooks

En lugar de consultar periódicamente, registre un endpoint de webhook en la aplicación (página Webhooks, disponible a partir del plan Starter) y MyProductPassport enviará JSON por POST a su URL cuando ocurran los eventos:

EventoSe activa cuando
product.createdSe crea un producto (aplicación, API o importación CSV)
product.updatedSe actualiza un producto
product.deletedSe elimina un producto
passport.createdSe genera un pasaporte
passport.publishedUn pasaporte se publica
passport.archivedUn pasaporte se archiva
supplier_request.submittedUn proveedor envía la información que usted ha solicitado
owner.registeredUn propietario confirma su registro
owner.transferredUn artículo pasa a un nuevo propietario registrado
service_request.createdUn cliente envía una solicitud de servicio desde un pasaporte
service_request.updatedUna solicitud de servicio recibe una respuesta o un nuevo estado
item.status_changedUn artículo se marca como robado, retirado del mercado o dado de baja, o se le quita la marca
item.verification_failedFalla una lectura segura, se acumulan códigos erróneos o un número de serie aparece en demasiados lugares
webhook.testEnvía una entrega de prueba desde la aplicación

Cada entrega es un sobre JSON: un identificador de entrega (el mismo identificador se reenvía en los reintentos, para que pueda eliminar duplicados), el evento, el número de intento, una marca de tiempo y los datos del evento. Los eventos de pasaporte incluyen el uuid y la URL pública del pasaporte, así que rara vez necesitará una segunda solicitud:

Cuerpo de la entrega
{
  "id": 8123,
  "event": "passport.published",
  "attempt": 1,
  "created_at": "2026-09-22T10:12:00+00:00",
  "data": {
    "passport_id": 96,
    "uuid": "3f0c8f1e-...",
    "version": 2,
    "status": "published",
    "public_url": "https://myproductpassport.co.uk/p/3f0c8f1e-...",
    "product_id": 512,
    "product": {"id": 512, "name": "Alpine Merino Crew Sweater", "sku": "NL-AMC-001", "gtin": "5012345678900"}
  }
}

Las cabeceras incluyen el nombre del evento, el id de entrega, una marca de tiempo Unix y una firma HMAC del cuerpo sin procesar, para que pueda verificar que procede de nosotros y rechazar repeticiones:

Cabeceras de la entrega
Content-Type: application/json
User-Agent: MyProductPassport-Webhooks/1.0
X-MPP-Event: passport.published
X-MPP-Delivery: 8123
X-MPP-Timestamp: 1790084320
X-MPP-Signature: sha256=<hex hmac of the raw body, keyed with your endpoint secret>

Responda con cualquier código 2xx en 10 segundos. Cualquier otra respuesta se reintenta cinco veces durante unos 90 minutos (30 s, 1 min, 5 min, 15 min, 1 h); tras 10 fallos consecutivos, el endpoint se pausa hasta que lo vuelva a activar.

Verificar (PHP)
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $endpointSecret);
abort_unless(hash_equals($expected, $request->header('X-MPP-Signature')), 401);