Prima scadenza DPP dell'UE (Batterie): 130 giorni Si metta in regola adesso
Lingua
EN DE FR IT ES NL PL BG CS DA EL ET FI HR HU LT LV MT PT RO SK SL SV
Prodotto
Funzionalità Post-vendita Come funziona Demo Enterprise Prezzi
Settori
Tutti i settori Tessili Elettronica Batterie
Risorse
Blog Confronta software DPP Requisiti per paese Valutazione della preparazione Verifica delle asserzioni ambientali Download gratuiti Glossario
Azienda
Partner Contatti
Accedi Inizia gratuitamente
Sviluppatori / API REST

Riferimento API

Tutto MyProductPassport è disponibile tramite un'API REST autenticata con chiave: crea prodotti, genera e pubblica passaporti digitali del prodotto, invia dati delle batterie in tempo reale e verifica la conformità, direttamente dal tuo ERP, PIM o pipeline di build.

v1 https://myproductpassport.eu/api/v1 Inizia gratis Specifica OpenAPI ↓

01 / Primi passiAutenticazione

Ogni richiesta è autenticata con una chiave API inviata come token Bearer. Le chiavi si creano nell'app in Chiavi API, vengono mostrate una sola volta e sono salvate con hash; ogni chiave ha i propri permessi, una lista facoltativa di IP consentiti e una data di scadenza facoltativa. Le chiavi possono essere ruotate senza interruzioni.

Intestazione della richiesta
Authorization: Bearer pk_your_api_key
Su ogni piano. Le chiavi API si possono creare e usare su ogni piano, anche quello gratuito. Il piano stabilisce quante richieste al minuto può fare una chiave (sotto) e quanti prodotti e passaporti può contenere lo spazio di lavoro.
Modalità di test. Una chiave di test (pk_test_...) esegue ogni chiamata esattamente come farebbe una chiave live, con la stessa validazione, gli stessi id e le stesse risposte, e poi la annulla: non viene salvato nulla, non viene inviata alcuna email né alcun webhook e non viene conservato alcun file. Le risposte contengono "test_mode": true e un'intestazione X-MPP-Mode: test. Sviluppi e testi un'integrazione sui Suoi dati reali, quindi passi a una chiave live.

Le autorizzazioni sono concesse per chiave, così un'integrazione ottiene solo ciò di cui ha bisogno:

AutorizzazioneAutorizzazioni
products:readLeggere i prodotti
products:writeCreare, aggiornare ed eliminare prodotti
passports:readLeggere i passaporti
passports:writeGenera passaporti
passports:publishPubblicare e archiviare passaporti
webhooks:manageCreare, testare e rimuovere endpoint 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 / Primi passiLimiti di richieste

I limiti valgono per chiave e per minuto e dipendono dal piano:

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

Ogni risposta contiene le intestazioni X-RateLimit-Limit e X-RateLimit-Remaining. Superando il limite si ottiene 429:

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

03 / Primi passiErrori

Gli errori sono restituiti in JSON con un codice di stato convenzionale. I più comuni:

StatoSignificatoEsempio di corpo
401Chiave mancante, non valida, revocata o scaduta{"error": "Invalid or revoked API key."}
403Alla chiave manca un'autorizzazione, l'IP non è nella lista consentita o è stata raggiunta la quota del piano{"message": "API key does not have 'products:write' permission."}
404La risorsa non esiste nel tuo spazio di lavoro{"message": "Not found."}
422Convalida non riuscita{"message": "…", "errors": {"gtin": ["…"]}}
429Limite di richieste superato{"error": "Rate limit exceeded."}

04 / Per iniziarePaginazione

Gli endpoint di elenco restituiscono 25 elementi per pagina con gli oggetti links e meta standard. Passa ?page=2 per scorrere la raccolta.

05 / Primi passiConnettore per assistenti IA (MCP)

Collega Claude, Cursor o qualsiasi assistente che parla il Model Context Protocol e chiedigli con parole semplici di creare prodotti, compilare passaporti con ciò che gli dici e controllare cosa manca ancora. Usa una chiave API con le sue autorizzazioni e il suo limite di richieste. Può creare bozze e compilare campi; non pubblica, archivia o elimina mai nulla: questo resta a te nell'app.

Indirizzo del server (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 e altri client che avviano un server locale
{
  "mcpServers": {
    "myproductpassport": {
      "command": "npx",
      "args": ["mcp-remote", "https://myproductpassport.eu/api/mcp", "--header", "Authorization: Bearer pk_live_your_key"]
    }
  }
}

Gli strumenti offerti:

StrumentoCosa fa
list_productsI prodotti dello spazio di lavoro, dal più recente, 25 per pagina, con il settore e l'ultimo passaporto.
get_productUn prodotto con dettagli, settore, sezioni normative e ultimo passaporto.
list_sectorsI modelli di settore che un prodotto può usare (tessile, elettronica, batterie, vino e altro), con i loro ID. Il settore di un prodotto decide quali campi del passaporto sono obbligatori.
create_productAggiunge un prodotto allo spazio di lavoro. Usa un sector_id da list_sectors. compliance_sections aggiunge sezioni normative al suo passaporto: gpsr, epr, france, chemicals, eudr.
list_passportsI passaporti dello spazio di lavoro, dal più recente, 25 per pagina, con stato (draft, published, archived), percentuale di completezza e indirizzo pubblico.
get_passportUn passaporto: stato, versione, percentuale di completezza, indirizzo pubblico e link al codice QR.
create_passportCrea un passaporto in bozza per un prodotto. Non viene pubblicato: lo pubblica una persona nell'app.
get_passport_fieldsCosa chiede un passaporto: le chiavi dei campi obbligatori e facoltativi, il significato di ciascuno (etichetta, descrizione, esempio), i valori presenti e quali campi obbligatori mancano.
update_passport_fieldsScrive valori di campo su un passaporto in bozza o pubblicato (uno pubblicato viene aggiornato sul posto: stesso indirizzo, stesso codice QR). Chiavi da get_passport_fields; un testo vuoto rimuove un valore. Scrivi solo fatti indicati dall'utente o dai suoi documenti.
get_complianceLa completezza di un passaporto: percentuale, stato e campi obbligatori ancora mancanti.
Provalo con una chiave di test. Con una chiave di test (pk_test_...) le modifiche dell'assistente vengono verificate e poi annullate, così vedi cosa farebbe prima di dargli una chiave reale.

06 / EndpointAccount

GET /me

Restituisce l'account autenticato, il suo piano di abbonamento e quanta parte del limite di prodotti è usata. Utile come verifica di connessione.

Richiesta
curl https://myproductpassport.eu/api/v1/me \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 / EndpointProdotti

GET /products richiede products:read

Elenca i prodotti del tuo spazio di lavoro, dal più recente, 25 per pagina. Ogni prodotto include il suo settore e il riepilogo del passaporto più recente.

ParametroTipoDescrizione
pageintegerNumero di pagina.
Richiesta
curl "https://myproductpassport.eu/api/v1/products?page=1" \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 richiede products:write

Crea un prodotto. Restituisce 403 se la quota di prodotti del piano è esaurita.

ParametroTipoDescrizione
namestringobbligatorioNome del prodotto, fino a 255 caratteri.
skustringIl tuo SKU interno, fino a 100 caratteri.
gtinstringGTIN-8, 12, 13 o 14 (solo cifre).
brandstringMarchio mostrato nel passaporto pubblico.
descriptionstringFino a 2.000 caratteri.
categorystringCategoria a testo libero. Valore predefinito «general».
sector_idintegerUn ID di settore, che seleziona il modello di campi del passaporto.
country_of_originstringCodice paese, ad es. «PT».
weightnumberPeso netto.
weight_unitstringUno tra kg, g, lb, oz. Predefinito kg.
materialsarrayOggetti {name, percentage 0-100}.
has_packagingbooleanAggiunge al passaporto i campi del modello Imballaggio (chiavi che iniziano con pkg_), con lo stesso codice QR.
Richiesta
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}
    ]
  }'
Risposta
{
  "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 richiede products:write

Crea fino a 100 prodotti in una chiamata. L'intero lotto viene rifiutato con 403 se supera la quota di prodotti residua. Per cataloghi con migliaia di articoli, richiama questo endpoint in ciclo o usa l'importazione CSV nell'app.

ParametroTipoDescrizione
productsarrayobbligatorioDa 1 a 100 oggetti prodotto con gli stessi campi di «Crea un prodotto» (materiali esclusi).
Richiesta
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}
    ]
  }'
Risposta
{
  "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} richiede products:read

Restituisce un prodotto con il suo settore e il riepilogo del passaporto più recente. 404 se l'id non è nel tuo spazio di lavoro.

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

Aggiorna parzialmente un prodotto. Invia solo i campi da modificare; l'elenco dei campi è lo stesso di Crea un prodotto.

Richiesta
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} richiede products:write

Elimina un prodotto in modo logico (soft delete). I passaporti pubblicati del prodotto continuano a funzionare, così i codici QR stampati non restano mai orfani.

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

08 / EndpointPassaporti

GET /passports richiede passports:read

Elenca i passaporti, dal più recente, 25 per pagina, con riepilogo del prodotto e tutti i campi del passaporto.

ParametroTipoDescrizione
pageintegerNumero di pagina.
Richiesta
curl https://myproductpassport.eu/api/v1/passports \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 richiede passports:write

Genera un passaporto in bozza per un prodotto, precompilando i campi dai dati del prodotto e dal modello del settore. Restituisce la bozza con il suo punteggio di conformità. Se il prodotto ha già un passaporto pubblicato, restituisce 409 con quel passaporto: correggilo con PUT /passports/{id}/fields, che mantiene indirizzo e codice QR.

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

Restituisce un passaporto con prodotto, campi, URL pubblico e GS1 Digital Link.

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

Pubblica una bozza di passaporto, rendendo attivi la pagina pubblica e il codice QR. Si possono pubblicare solo bozze; qualsiasi altro stato restituisce 404.

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

Archivia un passaporto e ritira la sua pagina pubblica dalla circolazione.

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

Pubblica fino a 50 bozze di passaporto in una chiamata e riporta l'esito per ciascuna, così un errore non interrompe mai il lotto.

ParametroTipoDescrizione
passport_idsarrayobbligatorioDa 1 a 50 ID di passaporto.
Richiesta
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]}'
Risposta
{
  "published": 2,
  "failed": 1,
  "published_ids": [96, 97],
  "errors": [
    { "id": 98, "error": "Compliance below the publishing threshold." }
  ]
}
POST /passports/{id}/successor richiede passports:write

Per un prodotto preparato per il riutilizzo, riconvertito o rigenerato, il regolamento sulle batterie (articolo 77, paragrafo 7) richiede un nuovo passaporto collegato all'originale. Questa operazione crea un nuovo record di prodotto e un passaporto in bozza precompilato da quello pubblicato e collegato a esso. L'originale resta online ed entrambi i passaporti mostrano il collegamento. Pubblica il nuovo con POST /passports/{id}/publish.

ParametroTipoDescrizione
stagestringobbligatorioprepared_for_reuse, repurposed o remanufactured.
Richiesta
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" }'
Risposta
{
  "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 richiede passports:read

Restituisce le chiavi di campo richieste dal modello del settore del passaporto (obbligatorie e facoltative), i valori attuali e quali chiavi obbligatorie mancano ancora. Usalo per costruire il payload di PUT /passports/{id}/fields.

Richiesta
curl https://myproductpassport.eu/api/v1/passports/96/fields \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 richiede passports:write

Scrive qualsiasi insieme di valori di campo su un passaporto in bozza o pubblicato: l'intero insieme dell'allegato XIII per una batteria, i campi di un modello di settore o le tue chiavi. Invia solo le chiavi da modificare; un valore null o vuoto rimuove il campo. Un passaporto pubblicato viene aggiornato sul posto, indirizzo e codice QR non cambiano e le traduzioni automatiche vengono rigenerate. La conformità viene ricalcolata. Questa chiamata non pubblica una bozza; usa POST /passports/{id}/publish.

ParametroTipoDescrizione
fieldsobjectobbligatorioMappa da chiave di campo a valore. Le chiavi sono lettere minuscole, cifre e trattini bassi; i valori fino a 5.000 caratteri. Fino a 200 chiavi per chiamata.
Richiesta
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%"
    }
  }'
Risposta
{
  "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 richiede passports:write

Invia i dati specifici di questa batteria (allegato XIII, punto 4, del regolamento (UE) 2023/1542) a un passaporto pubblicato, per sistemi BMS e di gestione flotte. Invia qualsiasi sottoinsieme dei campi seguenti; la conformità viene ricontrollata dopo l'aggiornamento. Questi valori sono mostrati solo ai visitatori approvati dal titolare del passaporto (articolo 77, paragrafo 2), mai sulla pagina pubblica. capacity_fade, power_capability e internal_resistance sono memorizzati come letture attuali di questa batteria (current_*), separate dai valori originali del modello.

ParametroTipoDescrizione
state_of_healthstringad es. «97% a 412 cicli».
state_of_certified_energystringEnergia certificata residua (batterie per veicoli elettrici).
battery_statusstringoriginal, repurposed, re-used, remanufactured o waste.
capacity_fadestringPerdita di capacità finora. Salvata come current_capacity_fade.
power_capabilitystringCapacità di potenza attuale. Salvata come current_power_capability.
internal_resistancestringResistenza interna misurata. Memorizzata come current_internal_resistance.
use_datastringCicli, eventi negativi, temperatura e stato di carica, fino a 5.000 caratteri.
Richiesta
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"
  }'
Risposta
{
  "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 richiede passports:write

Ogni batteria deve avere un proprio passaporto (regolamento (UE) 2023/1542, articolo 77, paragrafo 1). Registra fino a 10.000 batterie di un modello in una chiamata, ciascuna con il proprio numero di serie (fino a 20 lettere, cifre, punti, trattini o trattini bassi) e, facoltativamente, manufacturing_date, battery_status e i dati dell'allegato XIII, punto 4. I numeri di serie esistenti vengono aggiornati; i valori omessi restano invariati. Se il prodotto ha un GTIN, l'indirizzo di ogni batteria è il suo GS1 Digital Link, /01/{gtin}/21/{serial}. I dati del punto 4 sono visibili solo alle persone autorizzate dal titolare.

ParametroTipoDescrizione
units[].serialstringobbligatorioIl numero di serie della batteria.
units[].manufacturing_datestringMese e anno, ad es. "2026-09".
units[].battery_statusstringoriginal o waste. Un cambio di stato richiede i valori misurati in quel momento (allegato XIII, punto 4, lettera a)); waste richiede anche responsible_party_type (producer, pro o waste_operator), responsible_party_name e responsible_party_contact (articolo 77, paragrafo 7). recycled, con recycled_at e recycler_name, pone fine al passaporto (articolo 77, paragrafo 8). Una batteria destinata a nuovo uso, riutilizzata o rifabbricata riceve un nuovo passaporto: POST /passports/{id}/units/{serial}/successor.
units[].state_of_healthstringAnche 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 e use_data.
Richiesta
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%"}]}'
Risposta
{ "created": 1, "updated": 0, "skipped": 0, "errors": [] }
PATCH /passports/{id}/units/{serial} richiede passports:write

Per un sistema di gestione della batteria che invia i dati di una batteria: uno qualsiasi tra battery_status, state_of_health, state_of_certified_energy, current_capacity_fade, current_power_capability, current_internal_resistance e use_data. Esegui GET sullo stesso percorso per leggerli, oppure GET /passports/{id}/units per l'elenco (per_page fino a 500).

Richiesta
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"}'
Risposta
{
  "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 richiede passports:read

L'allegato XIII, punto 4, lettera a), richiede i valori di prestazione e durabilità al momento dell'immissione sul mercato della batteria e quando ne cambia lo stato. Tali letture vengono conservate così come sono, qualunque dato venga inviato in seguito; invii record_snapshot: true con una PATCH per conservare anche una lettura periodica.

Richiesta
curl https://myproductpassport.eu/api/v1/passports/96/units/KES-00001/snapshots \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 richiede passports:write

Articolo 77, paragrafo 7: una batteria preparata per il riutilizzo, destinata a nuovo uso o rifabbricata ha un nuovo passaporto collegato al suo originale. Questa operazione registra di nuovo la batteria, con un nuovo numero di serie e identificativo, sotto un modello di batteria di seconda vita del Suo spazio di lavoro (creato da questo modello se non ne esiste ancora uno), collega le due e conserva i valori misurati al cambio di stato. La batteria originale mantiene il proprio passaporto. Completi e pubblichi il modello di seconda vita con POST /passports/{id}/publish.

ParametroTipoDescrizione
stagestringobbligatorioprepared_for_reuse, repurposed o remanufactured.
valuesobjectobbligatorioI valori misurati al momento del cambio: almeno uno tra remaining_capacity_ah e current_capacity_fade, uno tra current_power_capability e power_fade, uno tra current_internal_resistance e internal_resistance_increase, oltre a expected_lifetime_cycles_remaining (allegato IV, parte A).
serialstringIl nuovo numero di serie. Predefinito: il numero di serie originale più -RU, -RP o -RM.
measured_atstringQuando sono stati misurati i valori.
member_statestringCodice di due lettere dello Stato membro in cui è stato testato lo stato di salute (articolo 73, paragrafo 1, lettera a)).
target_passport_idintegerUn modello di seconda vita già esistente di questo modello di batteria, in cui registrarla.
Richiesta
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"}}'
Risposta
{
  "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 richiede passports:write

Memorizza su un passaporto l'invio al registro DPP dell'UE e il relativo esito: stato, ID di correlazione, l'identificativo di registrazione restituito dal registro e un link facoltativo a una copia di backup ospitata da un fornitore di servizi DPP. La registrazione vera e propria avviene nel registro della Commissione (modulo web o caricamento file); qui si conserva l'esito con il passaporto. GET /passports/{id} restituisce lo stesso blocco in registry.

ParametroTipoDescrizione
statusstringnot_submitted, submitted, registered o failed.
product_groupstringGruppo di prodotti del registro, ad esempio batteries.
granularitystringmodello, lotto o articolo.
upistringIdentificativo unico del prodotto come URL https. Predefinito: l'URL del passaporto pubblico.
correlation_idstringID di correlazione assegnato dal Registro all'invio.
uristringIdentificativo di registrazione restituito dal registro.
backup_urlstringLink https alla copia di backup ospitata da un fornitore di servizi DPP.
submitted_atdateData di invio.
registered_atdateData di registrazione.
errorstringDescrizione dell'errore di un invio non riuscito.
Richiesta
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"
  }'
Risposta
{
  "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 richiede passports:read

Il codice QR del passaporto come file: svg (predefinito), png (con il tuo marchio, pronto per la stampa) o pdf (foglio di etichette).

ParametroTipoDescrizione
formatstringsvg | png | pdf
Richiesta
curl "https://myproductpassport.eu/api/v1/passports/96/qr?format=png" \
  -H "Authorization: Bearer pk_your_key" -o passport-96.png

09 / EndpointConformità

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

Esegue un controllo di conformità in tempo reale di un passaporto rispetto ai campi obbligatori del suo settore e indica esattamente cosa manca.

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

10 / EndpointSettori

GET /sectors

I settori in cui può essere classificato un prodotto: i settori di sistema della piattaforma più quelli definiti dal tuo spazio di lavoro. Usa l'id quando crei prodotti e le chiavi di campo quando scrivi i campi del passaporto.

Richiesta
curl https://myproductpassport.eu/api/v1/sectors \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 / EndpointDocumenti

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

Dichiarazioni di conformità, rapporti di prova e certificati allegati al prodotto. Un documento pubblico è collegato da ogni passaporto pubblicato del prodotto.

Richiesta
curl https://myproductpassport.eu/api/v1/products/512/documents \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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 richiede products:write

Caricamento multipart. PDF, Word, Excel, CSV, testo, PNG e JPEG fino a 10 MB, al massimo 20 per prodotto. Il testo viene estratto in background.

ParametroTipoDescrizione
filefileobbligatorioIl documento.
is_publicbooleanMostralo sul passaporto pubblico (predefinito false).
Richiesta
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} richiede products:write

Stabilisce se il documento è collegato dal passaporto pubblico.

ParametroTipoDescrizione
is_publicbooleanobbligatorio
Richiesta
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} richiede products:write

Rimuove il file e il suo collegamento al passaporto.

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

12 / EndpointCatena di approvvigionamento

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

Le fasi mostrate sul passaporto del prodotto, in ordine.

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

Sostituisce tutte le fasi con l'elenco inviato, nell'ordine inviato. Invia un elenco vuoto per svuotarla. Tipi di fase: raw_material, processing, manufacturing, assembly, packaging, distribution.

ParametroTipoDescrizione
stepsarrayobbligatorioFino a 50 fasi.
steps[].step_typestringobbligatorio
steps[].supplier_namestringobbligatorio
steps[].supplier_locationstring
steps[].supplier_countrystringISO 3166-1 alfa-2.
steps[].lat / lngnumber
steps[].descriptionstring
steps[].certificationsarray
steps[].datedate
Richiesta
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 / EndpointTraduzioni

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

Ogni valore di campo tradotto per lingua, con la sua fonte: auto (automatica, creata alla pubblicazione) o manuale.

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

Imposta le traduzioni per una lingua, per chiave di campo. Una traduzione manuale non viene mai sovrascritta dalla macchina. Invia una stringa vuota per rimuoverne una.

ParametroTipoDescrizione
fieldsobjectobbligatoriofield_key: valore tradotto
Richiesta
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"}}'
Risposta
{ "message": "1 translation(s) written, 0 removed.", "locale": "de", "written": 1, "removed": 0 }

14 / EndpointIntegrità ed esportazioni

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

Ogni stato pubblicato del passaporto come record concatenato tramite hash e firmato Ed25519: impronta (SHA-256), valore della catena e firma. Le chiavi pubbliche sono disponibili su /.well-known/mpp-integrity-keys.json, così chiunque può verificare la catena.

Richiesta
curl https://myproductpassport.eu/api/v1/passports/96/integrity \
  -H "Authorization: Bearer pk_your_key"
Risposta
{ "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} richiede passports:read

Il record completo così come è stato firmato, snapshot incluso: ciò che il passaporto riportava in quel momento, fino all'hash di ogni file allegato.

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

Il passaporto come documento JSON-LD GS1 EPCIS 2.0: la messa in servizio dell'articolo, ogni fase della catena di approvvigionamento come osservazione, le singole batterie e un passaporto seconda vita come trasformazione. Gli identificatori sono URI GS1 Digital Link quando il prodotto ha un GTIN.

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

15 / EndpointRichieste ai fornitori

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

Invia al fornitore via email un link privato per compilare i campi da Lei scelti, nella sua lingua. Nulla viene riportato nel passaporto finché qualcuno del Suo spazio di lavoro non lo approva.

ParametroTipoDescrizione
supplier_namestringobbligatorio
supplier_emailstringobbligatorio
field_keysarrayobbligatorioChiavi di campo del modello del passaporto.
localestringLingua dell'email e del modulo, ad es. de.
due_atdateData entro cui rispondere; 14 giorni se omessa.
messagestring
Richiesta
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 richiede passports:read

Ogni richiesta relativa al passaporto, con il suo stato.

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

Una richiesta con le risposte del fornitore, la nota e i nomi dei file allegati.

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

16 / EndpointPost-vendita

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

Dia agli articoli di un prodotto (qualsiasi settore tranne le batterie, che usano /units) il proprio numero di serie: ognuno riceve il proprio indirizzo e codice QR, un codice di autenticità nascosto per l'etichetta, e può essere registrato dal proprietario. Invii fino a 10.000 articoli o un intervallo. Con un GTIN l'indirizzo è il GS1 Digital Link /01/{gtin}/21/{serial}.

ParametroTipoDescrizione
items[].serialstringobbligatorioFino a 20 lettere, cifre, punti, trattini o trattini bassi.
items[].batchstringLotto, fino a 20 caratteri.
items[].manufactured_onstringData di produzione, AAAA-MM-GG.
rangeobjectAl posto di items: prefix, start, count, digits e batch, ad esempio da SN-00001 a SN-00500.
Richiesta
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"}}'
Risposta
{ "created": 500, "updated": 0, "skipped": 0, "over_limit": 0, "errors": [] }
GET /passports/{id}/items/{serial} richiede items:read

Un articolo con indirizzo, stato, se è registrato e fino a quando dura la garanzia, le verifiche di autenticità e la cronologia. Una chiave con items:write riceve anche il codice nascosto, per la stampa. GET /passports/{id}/items li elenca (filtri status e batch, per_page fino a 500).

Richiesta
curl https://myproductpassport.eu/api/v1/passports/96/items/SN-00001 \
  -H "Authorization: Bearer pk_your_key"
Risposta
{
  "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} richiede items:write

Imposti status su stolen o recalled e la sua pagina avvisa chi lo scansiona, con la Sua status_note; un articolo rubato non può essere registrato. retired mette offline la sua pagina. Si possono modificare anche batch e manufactured_on.

ParametroTipoDescrizione
statusstringactive, stolen, recalled o retired.
status_notestringMostrato sulla pagina dell'articolo, fino a 500 caratteri.
Richiesta
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 richiede aftersales:read

Le persone che hanno registrato i Suoi prodotti: nome, e-mail, paese, data di acquisto, rivenditore, date di garanzia e se hanno accettato novità e offerte (marketing_consent=1 elenca solo queste). Registrazioni attive per impostazione predefinita; status=pending, transferred o ended per le altre; since= per le modifiche dopo una data.

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

Riparazioni, richieste in garanzia, ritiri, ricambi e domande inviati dai Suoi passaporti, dai più recenti, con filtri status e type. GET /service-requests/{reference} aggiunge la conversazione.

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

La Sua risposta viene inviata al cliente via e-mail con un link alla pagina della sua richiesta, nella sua lingua. internal: true aggiunge una nota visibile solo al Suo team. PATCH /service-requests/{reference} con uno status la fa avanzare (il cliente viene avvisato quando è in corso, risolta o chiusa).

ParametroTipoDescrizione
bodystringobbligatorioLa risposta, fino a 5.000 caratteri.
internalbooleanUna nota per il Suo team al posto di una risposta.
statusstringnew, in_progress, waiting, resolved o closed.
Richiesta
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 / EndpointModifiche in blocco e immagini

PATCH /products/bulk-fields richiede products:write

Imposta un dato del prodotto o un campo del passaporto su un massimo di 5.000 prodotti. mode può essere set, fill (solo dove vuoto) o clear. Fino a 100 prodotti vengono aggiornati nella richiesta stessa; gli insiemi più grandi vengono messi in coda (202).

ParametroTipoDescrizione
product_idsarrayobbligatorio
targetstringobbligatorioproduct | field
keystringobbligatorio
valuestring
modestringset | fill | clear
Richiesta
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"}'
Risposta
{ "data": { "changed": 2, "skipped": 1, "errors": [] } }
POST /products/{id}/images richiede products:write

Caricamento multipart di un file JPG, PNG o WebP (fino a 15MB, 8 per prodotto). La prima immagine è quella di copertina nel passaporto pubblico.

ParametroTipoDescrizione
imagefileobbligatorio
altstringDescrizione dell'immagine.
Richiesta
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 richiede products:write

Passi image_ids nell'ordine desiderato; la prima diventa l'immagine di copertina.

ParametroTipoDescrizione
image_idsarrayobbligatorio
Richiesta
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} richiede products:write

Rimuove l'immagine e il relativo file.

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

18 / EndpointWebhook

GET /webhooks richiede webhooks:manage

Gli endpoint registrati per il tuo spazio di lavoro. I segreti non sono inclusi qui; recupera un singolo endpoint per vederne il segreto.

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

Registra un URL HTTPS pubblico per uno o più eventi. La risposta include il segreto di firma. Gli host privati o interni vengono rifiutati.

ParametroTipoDescrizione
urlstringobbligatorio
eventsarrayobbligatorioUno qualsiasi degli eventi elencati sotto.
Richiesta
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"]}'
Risposta
{
  "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} richiede webhooks:manage

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

Modifica l'URL o gli eventi, oppure sospendilo e riprendilo. La ripresa azzera il contatore degli errori; un endpoint viene sospeso automaticamente dopo 10 consegne fallite consecutive.

ParametroTipoDescrizione
urlstring
eventsarray
is_activeboolean
Richiesta
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 richiede webhooks:manage

Mette in coda una consegna webhook.test per verificare il ricevitore e il codice di firma.

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

Consegne recenti, dalla più recente, con lo stato HTTP restituito dal tuo endpoint e i primi 500 caratteri della risposta.

ParametroTipoDescrizione
per_pageintegerFino a 100.
Richiesta
curl https://myproductpassport.eu/api/v1/webhooks/3/deliveries \
  -H "Authorization: Bearer pk_your_key"
DELETE /webhooks/{id} richiede webhooks:manage

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

19 / EventiWebhook

Invece di interrogare periodicamente, registra un endpoint webhook nell'app (pagina Webhook, disponibile dal piano Starter in su) e MyProductPassport invierà JSON in POST al tuo URL quando accadono gli eventi:

EventoSi attiva quando
product.createdViene creato un prodotto (app, API o importazione CSV)
product.updatedUn prodotto viene aggiornato
product.deletedUn prodotto viene eliminato
passport.createdViene generato un passaporto
passport.publishedUn passaporto viene pubblicato
passport.archivedUn passaporto viene archiviato
supplier_request.submittedUn fornitore invia le informazioni richieste
owner.registeredUn proprietario conferma la sua registrazione
owner.transferredUn articolo passa a un nuovo proprietario registrato
service_request.createdUn cliente invia una richiesta di assistenza da un passaporto
service_request.updatedUna richiesta di assistenza riceve una risposta o un nuovo stato
item.status_changedUn articolo viene segnalato come rubato, richiamato o dismesso, oppure torna attivo
item.verification_failedUna lettura sicura fallisce, i codici errati si accumulano o un numero di serie compare in troppi luoghi
webhook.testInvii una consegna di prova dall'app

Ogni consegna è una busta JSON: un ID di consegna (lo stesso ID viene reinviato nei tentativi successivi, così puoi eliminare i duplicati), l'evento, il numero del tentativo, un timestamp e i dati dell'evento. Gli eventi del passaporto contengono l'uuid e l'URL pubblico del passaporto, quindi raramente serve una seconda richiesta:

Corpo della consegna
{
  "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"}
  }
}

Le intestazioni contengono il nome dell'evento, l'id di consegna, un timestamp Unix e una firma HMAC del corpo grezzo, così puoi verificare che provenga da noi e rifiutare le ripetizioni:

Intestazioni della consegna
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>

Rispondi con un qualsiasi codice 2xx entro 10 secondi. Ogni altra risposta viene ritentata cinque volte in circa 90 minuti (30 s, 1 min, 5 min, 15 min, 1 h); dopo 10 errori consecutivi l'endpoint viene sospeso finché non lo riattivi.

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