Referência da API
Tudo na MyProductPassport está disponível através de uma API REST autenticada por chave: crie produtos, gere e publique Passaportes Digitais de Produto, envie dados de baterias em tempo real e verifique a conformidade, diretamente do seu ERP, PIM ou pipeline de build.
01 / Primeiros passosAutenticação
Cada pedido é autenticado com uma chave de API enviada como token Bearer. As chaves são criadas na aplicação em Chaves de API, mostradas uma vez e guardadas com hash; cada chave tem o seu conjunto de permissões, uma lista opcional de IPs permitidos e uma data de expiração opcional. As chaves podem ser rodadas sem tempo de inatividade.
Authorization: Bearer pk_your_api_keyAs permissões são concedidas por chave, para que uma integração só obtenha o que precisa:
| Permissão | Autorizações |
|---|---|
| products:read | Ler produtos |
| products:write | Criar, atualizar e eliminar produtos |
| passports:read | Ler passaportes |
| passports:write | Gerar passaportes |
| passports:publish | Publicar e arquivar passaportes |
| webhooks:manage | Criar, testar e remover endpoints de webhook |
| items:read | Read individual items and their history |
| items:write | Add, update and flag individual items |
| aftersales:read | Read owner registrations and service requests |
| aftersales:write | Update service requests and reply to customers |
02 / Primeiros passosLimites de pedidos
Os limites são por chave, por minuto, e definidos pelo plano:
| Plano | Pedidos / minuto |
|---|---|
| Grátis | 30 |
| Micro | 60 |
| Rótulo eletrónico | 60 |
| Starter | 120 |
| Professional | 300 |
| Business | 600 |
| Battery | 600 |
Cada resposta inclui os cabeçalhos X-RateLimit-Limit e X-RateLimit-Remaining. Exceder o limite devolve 429:
{ "error": "Rate limit exceeded.", "limit": 300, "retry_after": 60 }03 / Primeiros passosErros
Os erros são JSON com um código de estado convencional. Os mais comuns:
| Estado | Significado | Corpo de exemplo |
|---|---|---|
| 401 | Chave em falta, inválida, revogada ou expirada | {"error": "Invalid or revoked API key."} |
| 403 | Falta uma permissão à chave, o IP não está na lista permitida ou foi atingido o limite do plano | {"message": "API key does not have 'products:write' permission."} |
| 404 | O recurso não existe no seu espaço de trabalho | {"message": "Not found."} |
| 422 | A validação falhou | {"message": "…", "errors": {"gtin": ["…"]}} |
| 429 | Limite de pedidos excedido | {"error": "Rate limit exceeded."} |
04 / Primeiros passosPaginação
Os endpoints de listagem devolvem 25 itens por página com os objetos links e meta padrão. Passe ?page=2 para percorrer a coleção.
05 / Primeiros passosConector de assistente de IA (MCP)
Ligue o Claude, o Cursor ou qualquer assistente que fale o Model Context Protocol e peça-lhe, por palavras simples, que crie produtos, preencha passaportes com o que lhe disser e verifique o que ainda falta. Usa uma chave API com as permissões e o limite de pedidos dessa chave. Pode criar rascunhos e preencher campos; nunca publica, arquiva ou elimina nada: isso continua consigo na aplicação.
https://myproductpassport.eu/api/mcpclaude mcp add --transport http myproductpassport https://myproductpassport.eu/api/mcp \
--header "Authorization: Bearer pk_live_your_key"{
"mcpServers": {
"myproductpassport": {
"url": "https://myproductpassport.eu/api/mcp",
"headers": { "Authorization": "Bearer pk_live_your_key" }
}
}
}{
"mcpServers": {
"myproductpassport": {
"command": "npx",
"args": ["mcp-remote", "https://myproductpassport.eu/api/mcp", "--header", "Authorization: Bearer pk_live_your_key"]
}
}
}As ferramentas disponíveis:
| Ferramenta | O que faz |
|---|---|
| list_products | Os produtos do espaço de trabalho, do mais recente, 25 por página, com o setor e o último passaporte. |
| get_product | Um produto com os detalhes, setor, secções regulamentares e último passaporte. |
| list_sectors | Os modelos de setor que um produto pode usar (têxteis, eletrónica, baterias, vinho e outros), com os respetivos IDs. O setor de um produto decide que campos do passaporte são obrigatórios. |
| create_product | Adiciona um produto ao espaço de trabalho. Use um sector_id de list_sectors. compliance_sections acrescenta secções regulamentares ao passaporte: gpsr, epr, france, chemicals, eudr. |
| list_passports | Os passaportes do espaço de trabalho, do mais recente, 25 por página, com estado (draft, published, archived), percentagem de conformidade e endereço público. |
| get_passport | Um passaporte: estado, versão, percentagem de conformidade, endereço público e ligações ao código QR. |
| create_passport | Cria um passaporte em rascunho para um produto. Não é publicado: é uma pessoa que o publica na aplicação. |
| get_passport_fields | O que um passaporte pede: as chaves dos campos obrigatórios e opcionais, o significado de cada um (rótulo, descrição, exemplo), os valores existentes e que campos obrigatórios faltam. |
| update_passport_fields | Escreve valores de campos num passaporte em rascunho ou publicado (um publicado é atualizado no local: mesmo endereço, mesmo código QR). Chaves de get_passport_fields; um texto vazio remove um valor. Escreva apenas factos indicados pelo utilizador ou pelos seus documentos. |
| get_compliance | A completude de um passaporte: percentagem, estado e os campos obrigatórios ainda em falta. |
06 / EndpointsConta
/me
Devolve a conta autenticada, o seu nível de subscrição e quanto do limite de produtos está usado. Útil como verificação de ligação.
curl https://myproductpassport.eu/api/v1/me \
-H "Authorization: Bearer pk_your_key"{
"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 / EndpointsProdutos
/products
requer products:read Lista os produtos do seu espaço de trabalho, do mais recente para o mais antigo, 25 por página. Cada produto inclui o seu setor e um resumo do passaporte mais recente.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| page | integer | Número da página. |
curl "https://myproductpassport.eu/api/v1/products?page=1" \
-H "Authorization: Bearer pk_your_key"{
"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 }
}/products
requer products:write Cria um produto. Devolve 403 se o limite de produtos do plano estiver esgotado.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| name | string | obrigatório | Nome do produto, até 255 caracteres. |
| sku | string | O seu SKU interno, até 100 caracteres. | |
| gtin | string | GTIN-8, 12, 13 ou 14 (apenas dígitos). | |
| brand | string | Marca apresentada no passaporte público. | |
| description | string | Até 2000 caracteres. | |
| category | string | Categoria em texto livre. Por predefinição "general". | |
| sector_id | integer | Um ID de setor, que seleciona o modelo de campos do passaporte. | |
| country_of_origin | string | Código do país, p. ex. "PT". | |
| weight | number | Peso líquido. | |
| weight_unit | string | Um de kg, g, lb, oz. Por predefinição, kg. | |
| materials | array | Objetos {name, percentage 0-100}. | |
| has_packaging | boolean | Adiciona ao passaporte os campos do modelo de embalagem (chaves que começam por pkg_), sob o mesmo código QR. |
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}
]
}'{
"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"
}
}/products/bulk
requer products:write Cria até 100 produtos numa chamada. O lote inteiro é recusado com 403 se exceder o limite de produtos restante. Para catálogos com milhares de produtos, chame este endpoint em ciclo ou use a importação CSV na aplicação.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| products | array | obrigatório | 1 a 100 objetos de produto com os mesmos campos de «Criar um produto» (sem materiais). |
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}
]
}'{
"message": "2 product(s) created.",
"products": [
{ "id": 514, "name": "PSL-BT-122000", "status": "active" },
{ "id": 515, "name": "PSL-BT-123000", "status": "active" }
]
}/products/{id}
requer products:read Devolve um produto com o seu setor e o resumo do passaporte mais recente. 404 se o id não estiver no seu espaço de trabalho.
curl https://myproductpassport.eu/api/v1/products/512 \
-H "Authorization: Bearer pk_your_key"/products/{id}
requer products:write Atualiza parcialmente um produto. Envie apenas os campos que pretende alterar; a lista de campos é igual à de Criar um produto.
curl -X PUT https://myproductpassport.eu/api/v1/products/512 \
-H "Authorization: Bearer pk_your_key" \
-H "Content-Type: application/json" \
-d '{"brand": "Northloom"}'/products/{id}
requer products:write Elimina um produto de forma recuperável. Os passaportes publicados do produto continuam a funcionar, para que os códigos QR impressos nunca fiquem sem página.
curl -X DELETE https://myproductpassport.eu/api/v1/products/512 \
-H "Authorization: Bearer pk_your_key"{ "message": "Product deleted." }08 / EndpointsPassaportes
/passports
requer passports:read Lista os passaportes, do mais recente para o mais antigo, 25 por página, com resumo do produto e todos os campos do passaporte.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| page | integer | Número da página. |
curl https://myproductpassport.eu/api/v1/passports \
-H "Authorization: Bearer pk_your_key"{
"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 }
}/products/{productId}/passports
requer passports:write Gera um rascunho de passaporte para um produto, pré-preenchendo campos a partir dos dados do produto e do modelo do setor. Devolve o rascunho com a sua pontuação de conformidade. Um produto que já tem um passaporte ativo devolve 409 com esse passaporte: corrija-o com PUT /passports/{id}/fields, que mantém o seu endereço e código QR.
curl -X POST https://myproductpassport.eu/api/v1/products/512/passports \
-H "Authorization: Bearer pk_your_key"/passports/{id}
requer passports:read Devolve um passaporte com produto, campos, URL público e GS1 Digital Link.
curl https://myproductpassport.eu/api/v1/passports/96 \
-H "Authorization: Bearer pk_your_key"/passports/{id}/publish
requer passports:publish Publica um rascunho de passaporte, ativando a sua página pública e código QR. Só podem ser publicados rascunhos; tudo o resto devolve 404.
curl -X POST https://myproductpassport.eu/api/v1/passports/96/publish \
-H "Authorization: Bearer pk_your_key"/passports/{id}/archive
requer passports:publish Arquiva um passaporte e retira a sua página pública de circulação.
curl -X POST https://myproductpassport.eu/api/v1/passports/96/archive \
-H "Authorization: Bearer pk_your_key"/passports/bulk-publish
requer passports:publish Publica até 50 rascunhos de passaporte numa chamada e indica o resultado de cada um, para que uma falha nunca interrompa o lote.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| passport_ids | array | obrigatório | 1 a 50 IDs de passaporte. |
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]}'{
"published": 2,
"failed": 1,
"published_ids": [96, 97],
"errors": [
{ "id": 98, "error": "Compliance below the publishing threshold." }
]
}/passports/{id}/successor
requer passports:write Para um produto preparado para reutilização, reaproveitado ou remanufaturado, o Regulamento relativo às baterias (artigo 77.º, n.º 7) exige um novo passaporte ligado ao original. Isto cria um novo registo de produto e um rascunho de passaporte pré-preenchido a partir do publicado, com ligação a ele. O original mantém-se ativo e ambos os passaportes mostram a ligação. Publique o novo com POST /passports/{id}/publish.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| stage | string | obrigatório | prepared_for_reuse, repurposed ou remanufactured. |
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" }'{
"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": []
}
}
}/passports/{id}/fields
requer passports:read Devolve as chaves de campo que o modelo do setor do passaporte pede (obrigatórias e opcionais), os valores atuais e as chaves obrigatórias ainda em falta. Use-o para construir o corpo de PUT /passports/{id}/fields.
curl https://myproductpassport.eu/api/v1/passports/96/fields \
-H "Authorization: Bearer pk_your_key"{
"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", "...": "..." }
}/passports/{id}/fields
requer passports:write Escreve qualquer conjunto de valores de campos num passaporte em rascunho ou publicado: o conjunto completo do anexo XIII para uma bateria, os campos de um modelo setorial ou as suas próprias chaves. Envie apenas as chaves que pretende alterar; um valor null ou vazio remove esse campo. Um passaporte publicado é atualizado no local, o seu endereço e código QR não mudam e as traduções automáticas são regeneradas. A conformidade é novamente pontuada. Um rascunho não é publicado por esta chamada; use POST /passports/{id}/publish.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| fields | object | obrigatório | Mapa de chave de campo para valor. As chaves são letras minúsculas, dígitos e sublinhados; valores até 5000 caracteres. Até 200 chaves por chamada. |
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%"
}
}'{
"message": "3 field(s) changed, 0 removed.",
"changed": ["carbon_footprint", "carbon_footprint_class", "recycled_content"],
"removed": [],
"passport": { "id": 96, "status": "published", "compliance_percentage": 92 }
}/passports/{id}/state-of-health
requer passports:write Envia os dados próprios desta bateria (ponto 4 do Anexo XIII do Regulamento (UE) 2023/1542) para um passaporte publicado, para sistemas BMS e de frotas. Envie qualquer subconjunto dos campos abaixo; a conformidade é reavaliada após a atualização. Estes valores só são mostrados a visitantes aprovados pelo titular do passaporte (artigo 77.º, n.º 2), nunca na página pública. capacity_fade, power_capability e internal_resistance são guardados como leituras atuais desta bateria (current_*), separados dos valores originais do modelo.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| state_of_health | string | p. ex. "97% aos 412 ciclos". | |
| state_of_certified_energy | string | Energia certificada restante (baterias de VE). | |
| battery_status | string | original, repurposed, re-used, remanufactured ou waste. | |
| capacity_fade | string | Perda de capacidade até à data. Guardada como current_capacity_fade. | |
| power_capability | string | Capacidade de potência atual. Guardada como current_power_capability. | |
| internal_resistance | string | Resistência interna medida. Guardada como current_internal_resistance. | |
| use_data | string | Ciclos, eventos negativos, temperatura e estado de carga, até 5000 caracteres. |
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"
}'{
"message": "2 field(s) updated.",
"updated_fields": ["state_of_health", "current_capacity_fade"],
"passport": { "id": 96, "status": "published", "compliance_percentage": 100 }
}/passports/{id}/units
requer passports:write Cada bateria precisa do seu próprio passaporte (Regulamento (UE) 2023/1542, artigo 77.º, n.º 1). Registe até 10 000 baterias de um modelo numa chamada, cada uma com o seu número de série (até 20 letras, dígitos, pontos, hífenes ou sublinhados) e, opcionalmente, manufacturing_date, battery_status e os seus dados do ponto 4 do Anexo XIII. Os números de série existentes são atualizados; os valores que omitir são mantidos. Com um GTIN no produto, o endereço de cada bateria é o seu GS1 Digital Link, /01/{gtin}/21/{serial}. Os dados do ponto 4 só são mostrados a visitantes aprovados pelo titular.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| units[].serial | string | obrigatório | O número de série da bateria. |
| units[].manufacturing_date | string | Mês e ano, p. ex. "2026-09". | |
| units[].battery_status | string | original ou waste. Uma mudança de estado exige os valores medidos nesse momento (anexo XIII, ponto 4, alínea a)); waste exige também responsible_party_type (producer, pro ou waste_operator), responsible_party_name e responsible_party_contact (artigo 77.º, n.º 7). recycled, com recycled_at e recycler_name, põe termo ao passaporte (artigo 77.º, n.º 8). Uma bateria reconvertida, reutilizada ou remanufaturada recebe um novo passaporte: POST /passports/{id}/units/{serial}/successor. | |
| units[].state_of_health | string | Também 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. |
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%"}]}'{ "created": 1, "updated": 0, "skipped": 0, "errors": [] }/passports/{id}/units/{serial}
requer passports:write Para um sistema de gestão de baterias que envia os dados de uma bateria: qualquer um de battery_status, state_of_health, state_of_certified_energy, current_capacity_fade, current_power_capability, current_internal_resistance e use_data. Use GET no mesmo caminho para os ler, ou GET /passports/{id}/units para a lista (per_page até 500).
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"}'{
"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" } }
}/passports/{id}/units/{serial}/snapshots
requer passports:read O anexo XIII, ponto 4, alínea a), exige os valores de desempenho e durabilidade quando a bateria é colocada no mercado e quando o seu estado muda. Essas leituras são mantidas tal como estavam, independentemente do que for enviado depois; envie record_snapshot: true com um PATCH para guardar também uma leitura periódica.
curl https://myproductpassport.eu/api/v1/passports/96/units/KES-00001/snapshots \
-H "Authorization: Bearer pk_your_key"{
"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" }
]
}/passports/{id}/units/{serial}/successor
requer passports:write Artigo 77.º, n.º 7: uma bateria que tenha sido preparada para reutilização, reconvertida ou remanufaturada tem um novo passaporte ligado ao original. Esta ação regista novamente a bateria, com um novo número de série e identificador, num modelo de bateria de segunda vida do seu espaço de trabalho (criado a partir deste modelo, se ainda não existir), liga os dois e mantém os valores medidos na mudança. A bateria original mantém o seu passaporte. Complete e publique o modelo de segunda vida com POST /passports/{id}/publish.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| stage | string | obrigatório | prepared_for_reuse, repurposed ou remanufactured. |
| values | object | obrigatório | Os valores medidos na mudança: pelo menos um de remaining_capacity_ah ou current_capacity_fade, de current_power_capability ou power_fade, de current_internal_resistance ou internal_resistance_increase, e expected_lifetime_cycles_remaining (anexo IV, parte A). |
| serial | string | O novo número de série. Por predefinição, o número de série original seguido de -RU, -RP ou -RM. | |
| measured_at | string | Quando os valores foram medidos. | |
| member_state | string | Código de duas letras do Estado-Membro onde o estado de saúde foi testado (artigo 73.º, n.º 1, alínea a)). | |
| target_passport_id | integer | Um modelo de segunda vida existente deste modelo de bateria, no qual a registar. |
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"}}'{
"data": {
"serial": "KES-00001-RP", "battery_status": "repurposed", "passport_id": 131,
"lineage": { "originals": [{ "serial": "KES-00001", "passport_id": 96, "stage": "repurposed" }], "successors": [] }
}
}/passports/{id}/registry
requer passports:write Guarda no passaporte a submissão ao Registo DPP da UE e o respetivo resultado: estado, ID de correlação, o identificador de registo devolvido pelo Registo e uma ligação opcional para uma cópia de segurança alojada por um prestador de serviços DPP. O registo em si é feito no Registo da Comissão (formulário web ou carregamento de ficheiro); isto mantém o resultado junto do passaporte. GET /passports/{id} devolve o mesmo bloco em registry.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| status | string | not_submitted, submitted, registered ou failed. | |
| product_group | string | Grupo de produtos do registo, por exemplo batteries. | |
| granularity | string | modelo, lote ou artigo. | |
| upi | string | Identificador único do produto como URL https. Por predefinição, o URL do passaporte público. | |
| correlation_id | string | ID de correlação atribuído pelo registo na submissão. | |
| uri | string | Identificador de registo devolvido pelo registo. | |
| backup_url | string | Ligação https para a cópia de segurança alojada por um prestador de serviços DPP. | |
| submitted_at | date | Data de submissão. | |
| registered_at | date | Data de registo. | |
| error | string | Descrição do erro de uma submissão falhada. |
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"
}'{
"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"
}
}
}/passports/{id}/qr
requer passports:read O código QR do passaporte como ficheiro: svg (predefinição), png (com a marca, pronto a imprimir) ou pdf (folha de etiquetas).
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| format | string | svg | png | pdf |
curl "https://myproductpassport.eu/api/v1/passports/96/qr?format=png" \
-H "Authorization: Bearer pk_your_key" -o passport-96.png09 / EndpointsConformidade
/passports/{passportId}/compliance
requer passports:read Executa uma verificação de conformidade em tempo real de um passaporte face aos campos obrigatórios do seu setor e indica exatamente o que falta.
curl https://myproductpassport.eu/api/v1/passports/96/compliance \
-H "Authorization: Bearer pk_your_key"{
"data": {
"passport_id": 96,
"product_name": "Alpine Merino Crew Sweater",
"status": "compliant",
"percentage": 100,
"completed_fields": 12,
"total_fields": 12,
"missing_fields": []
}
}10 / EndpointsSetores
/sectors
Os setores em que um produto pode ser classificado: os setores de sistema da plataforma mais os definidos pelo seu espaço de trabalho. Use o id ao criar produtos e as chaves de campo ao escrever campos do passaporte.
curl https://myproductpassport.eu/api/v1/sectors \
-H "Authorization: Bearer pk_your_key"{
"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
/products/{productId}/documents
requer products:read Declarações de conformidade, relatórios de ensaio e certificados anexados ao produto. Um documento público fica ligado a partir de todos os passaportes publicados do produto.
curl https://myproductpassport.eu/api/v1/products/512/documents \
-H "Authorization: Bearer pk_your_key"{
"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"
}
]
}/products/{productId}/documents
requer products:write Carregamento multipart. PDF, Word, Excel, CSV, texto, PNG e JPEG até 10 MB, no máximo 20 por produto. O texto é extraído em segundo plano.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| file | file | obrigatório | O documento. |
| is_public | boolean | Mostrar no passaporte público (predefinição false). |
curl -X POST https://myproductpassport.eu/api/v1/products/512/documents \
-H "Authorization: Bearer pk_your_key" \
-F "[email protected]" \
-F "is_public=1"/products/{productId}/documents/{id}
requer products:write Define se o documento está ligado a partir do passaporte público.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| is_public | boolean | obrigatório |
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}'/products/{productId}/documents/{id}
requer products:write Remove o ficheiro e a sua ligação ao passaporte.
curl -X DELETE https://myproductpassport.eu/api/v1/products/512/documents/31 \
-H "Authorization: Bearer pk_your_key"{ "message": "Document deleted." }12 / EndpointsCadeia de abastecimento
/products/{productId}/supply-chain
requer products:read Os passos apresentados no passaporte do produto, por ordem.
curl https://myproductpassport.eu/api/v1/products/512/supply-chain \
-H "Authorization: Bearer pk_your_key"/products/{productId}/supply-chain
requer products:write Substitui todos os passos pela lista que enviar, pela ordem enviada. Envie uma lista vazia para a limpar. Tipos de passo: raw_material, processing, manufacturing, assembly, packaging, distribution.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| steps | array | obrigatório | Até 50 passos. |
| steps[].step_type | string | obrigatório | |
| steps[].supplier_name | string | obrigatório | |
| steps[].supplier_location | string | ||
| steps[].supplier_country | string | ISO 3166-1 alpha-2. | |
| steps[].lat / lng | number | ||
| steps[].description | string | ||
| steps[].certifications | array | ||
| steps[].date | date |
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 / EndpointsTraduções
/passports/{id}/translations
requer passports:read Cada valor de campo traduzido por idioma, com a sua origem: auto (automática, feita na publicação) ou manual.
curl https://myproductpassport.eu/api/v1/passports/96/translations \
-H "Authorization: Bearer pk_your_key"{
"data": {
"passport_id": 96,
"available_locales": ["bg", "cs", "da", "de", "..."],
"translations": {
"de": {"care_instructions": {"value": "Kalt waschen", "source": "manual"}}
}
}
}/passports/{id}/translations/{locale}
requer passports:write Define as traduções de um idioma por chave de campo. Uma tradução manual nunca é substituída por tradução automática. Envie uma string vazia para remover uma.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| fields | object | obrigatório | field_key: valor traduzido |
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"}}'{ "message": "1 translation(s) written, 0 removed.", "locale": "de", "written": 1, "removed": 0 }14 / EndpointsIntegridade e exportações
/passports/{id}/integrity
requer passports:read Cada estado publicado do passaporte como um registo encadeado por hash e assinado com Ed25519: impressão digital (SHA-256), valor da cadeia e assinatura. As chaves públicas estão em /.well-known/mpp-integrity-keys.json, pelo que qualquer pessoa pode verificar a cadeia.
curl https://myproductpassport.eu/api/v1/passports/96/integrity \
-H "Authorization: Bearer pk_your_key"{ "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": [] } }/passports/{id}/integrity/{sequence}
requer passports:read O registo completo tal como foi assinado, incluindo o instantâneo: o que o passaporte indicava nesse momento, até ao hash de cada ficheiro anexado.
curl https://myproductpassport.eu/api/v1/passports/96/integrity/1 \
-H "Authorization: Bearer pk_your_key"/passports/{id}/epcis
requer passports:read O passaporte como documento GS1 EPCIS 2.0 JSON-LD: o comissionamento do artigo, cada passo da cadeia de abastecimento como uma observação, as baterias individuais e um passaporte de segunda vida como uma transformação. Os identificadores são URIs GS1 Digital Link quando o produto tem um GTIN.
curl https://myproductpassport.eu/api/v1/passports/96/epcis \
-H "Authorization: Bearer pk_your_key"15 / EndpointsPedidos a fornecedores
/passports/{id}/supplier-requests
requer passports:write Envia a um fornecedor, por email, uma ligação privada para preencher os campos que escolher, no idioma dele. Nada chega ao passaporte até que alguém do seu espaço de trabalho o aprove.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| supplier_name | string | obrigatório | |
| supplier_email | string | obrigatório | |
| field_keys | array | obrigatório | Chaves de campo do modelo do passaporte. |
| locale | string | Idioma do email e do formulário, por exemplo de. | |
| due_at | date | Data limite de resposta; 14 dias se for omitida. | |
| message | string |
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"}'/passports/{id}/supplier-requests
requer passports:read Todos os pedidos do passaporte, com o respetivo estado.
curl https://myproductpassport.eu/api/v1/passports/96/supplier-requests \
-H "Authorization: Bearer pk_your_key"/supplier-requests/{id}
requer passports:read Um pedido com as respostas do fornecedor, a nota e os nomes dos ficheiros anexados.
curl https://myproductpassport.eu/api/v1/supplier-requests/12 \
-H "Authorization: Bearer pk_your_key"16 / EndpointsPós-venda
/passports/{id}/items
requer items:write Dê aos artigos de um produto (qualquer setor exceto baterias, que usam /units) o seu próprio número de série: cada um recebe endereço e código QR próprios, um código de autenticidade oculto para a etiqueta, e pode ser registado pelo proprietário. Envie até 10 000 artigos ou um intervalo. Com um GTIN, o endereço é o GS1 Digital Link /01/{gtin}/21/{serial}.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| items[].serial | string | obrigatório | Até 20 letras, algarismos, pontos, hífenes ou carateres de sublinhado. |
| items[].batch | string | Lote, até 20 caracteres. | |
| items[].manufactured_on | string | Data de fabrico, AAAA-MM-DD. | |
| range | object | Em vez de items: prefix, start, count, digits e batch, por exemplo SN-00001 a SN-00500. |
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"}}'{ "created": 500, "updated": 0, "skipped": 0, "over_limit": 0, "errors": [] }/passports/{id}/items/{serial}
requer items:read Um artigo com endereço, estado, se está registado e até quando dura a garantia, as verificações de autenticidade e o histórico. Uma chave com items:write obtém também o código oculto, para impressão. GET /passports/{id}/items lista-os (filtros status e batch, per_page até 500).
curl https://myproductpassport.eu/api/v1/passports/96/items/SN-00001 \
-H "Authorization: Bearer pk_your_key"{
"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" } ] }
}/passports/{id}/items/{serial}
requer items:write Defina status como stolen ou recalled e a sua página avisa quem o ler, com a sua status_note; um artigo roubado não pode ser registado. retired retira a página do ar. Também pode alterar batch e manufactured_on.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| status | string | active, stolen, recalled ou retired. | |
| status_note | string | Mostrado na página do artigo, até 500 caracteres. |
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."}'/owner-registrations
requer aftersales:read Pessoas que registaram os seus produtos: nome, e-mail, país, data de compra, vendedor, datas de garantia e se aceitaram novidades e ofertas (marketing_consent=1 lista só esses). Registos ativos por predefinição; status=pending, transferred ou ended para os outros; since= para alterações após uma data.
curl "https://myproductpassport.eu/api/v1/owner-registrations?marketing_consent=1&since=2026-10-01" \
-H "Authorization: Bearer pk_your_key"/service-requests
requer aftersales:read Reparações, pedidos de garantia, recolhas, peças sobresselentes e perguntas enviados a partir dos seus passaportes, os mais recentes primeiro, com filtros status e type. GET /service-requests/{reference} acrescenta a conversa.
curl "https://myproductpassport.eu/api/v1/service-requests?status=new" \
-H "Authorization: Bearer pk_your_key"/service-requests/{reference}/replies
requer aftersales:write A sua resposta é enviada ao cliente por e-mail com uma ligação para a página do pedido, no idioma dele. internal: true acrescenta uma nota que só a sua equipa vê. PATCH /service-requests/{reference} com um status fá-lo avançar (o cliente é avisado quando está em curso, resolvido ou fechado).
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| body | string | obrigatório | A resposta, até 5000 caracteres. |
| internal | boolean | Uma nota para a sua equipa em vez de uma resposta. | |
| status | string | new, in_progress, waiting, resolved ou closed. |
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 / EndpointsEdições em massa e imagens
/products/bulk-fields
requer products:write Define um dado de produto ou um campo do passaporte em até 5000 produtos. mode é set, fill (apenas onde estiver vazio) ou clear. Até 100 produtos são atualizados no próprio pedido; conjuntos maiores são colocados em fila (202).
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| product_ids | array | obrigatório | |
| target | string | obrigatório | product | field |
| key | string | obrigatório | |
| value | string | ||
| mode | string | set | fill | clear |
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"}'{ "data": { "changed": 2, "skipped": 1, "errors": [] } }/products/{id}/images
requer products:write Carregamento multipart de um JPG, PNG ou WebP (até 15MB, 8 por produto). A primeira imagem é a capa do passaporte público.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| image | file | obrigatório | |
| alt | string | Descrição da imagem. |
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"/products/{id}/images/order
requer products:write Indique image_ids pela ordem pretendida; a primeira passa a ser a capa.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| image_ids | array | obrigatório |
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]}'/products/{id}/images/{imageId}
requer products:write Remove a imagem e o respetivo ficheiro.
curl -X DELETE https://myproductpassport.eu/api/v1/products/12/images/31 \
-H "Authorization: Bearer pk_your_key"18 / EndpointsWebhooks
/webhooks
requer webhooks:manage Os endpoints registados para o seu espaço de trabalho. Os segredos não estão incluídos aqui; obtenha um endpoint para ver o respetivo segredo.
curl https://myproductpassport.eu/api/v1/webhooks \
-H "Authorization: Bearer pk_your_key"/webhooks
requer webhooks:manage Regista um URL HTTPS público para um ou mais eventos. A resposta inclui o segredo de assinatura. Anfitriões privados ou internos são recusados.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| url | string | obrigatório | |
| events | array | obrigatório | Qualquer um dos eventos indicados abaixo. |
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"]}'{
"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"
}
}/webhooks/{id}
requer webhooks:manage curl https://myproductpassport.eu/api/v1/webhooks/3 \
-H "Authorization: Bearer pk_your_key"/webhooks/{id}
requer webhooks:manage Altere o URL ou os eventos, ou pause e retome o endpoint. Retomar repõe a contagem de falhas; um endpoint é pausado automaticamente após 10 entregas falhadas consecutivas.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| url | string | ||
| events | array | ||
| is_active | boolean |
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}'/webhooks/{id}/test
requer webhooks:manage Coloca em fila uma entrega webhook.test para poder verificar o recetor e o código de assinatura.
curl -X POST https://myproductpassport.eu/api/v1/webhooks/3/test \
-H "Authorization: Bearer pk_your_key"{ "message": "Test delivery queued." }/webhooks/{id}/deliveries
requer webhooks:manage Entregas recentes, da mais recente para a mais antiga, com o estado HTTP devolvido pelo seu endpoint e os primeiros 500 caracteres do corpo da resposta.
| Parâmetro | Tipo | Descrição | |
|---|---|---|---|
| per_page | integer | Até 100. |
curl https://myproductpassport.eu/api/v1/webhooks/3/deliveries \
-H "Authorization: Bearer pk_your_key"/webhooks/{id}
requer webhooks:manage curl -X DELETE https://myproductpassport.eu/api/v1/webhooks/3 \
-H "Authorization: Bearer pk_your_key"{ "message": "Webhook endpoint deleted." }19 / EventosWebhooks
Em vez de consultar periodicamente, registe um endpoint de webhook na aplicação (página Webhooks, disponível a partir do plano Starter) e a MyProductPassport enviará JSON por POST para o seu URL à medida que os eventos acontecem:
| Evento | Dispara quando |
|---|---|
| product.created | É criado um produto (aplicação, API ou importação CSV) |
| product.updated | Um produto é atualizado |
| product.deleted | Um produto é eliminado |
| passport.created | Um passaporte é gerado |
| passport.published | Um passaporte fica ativo |
| passport.archived | Um passaporte é arquivado |
| supplier_request.submitted | Um fornecedor envia as informações que pediu |
| owner.registered | Um proprietário confirma o seu registo |
| owner.transferred | Um artigo passa para um novo proprietário registado |
| service_request.created | Um cliente envia um pedido de assistência a partir de um passaporte |
| service_request.updated | Um pedido de assistência recebe uma resposta ou um novo estado |
| item.status_changed | Um artigo é assinalado como roubado, recolhido ou retirado, ou a marcação é removida |
| item.verification_failed | Uma leitura segura falha, os códigos errados acumulam-se ou um número de série aparece em demasiados locais |
| webhook.test | Envia uma entrega de teste a partir da aplicação |
Cada entrega é um envelope JSON: um ID de entrega (o mesmo ID é reenviado nas novas tentativas, para poder eliminar duplicados), o evento, o número da tentativa, um carimbo temporal e os dados do evento. Os eventos de passaporte incluem o uuid e o URL público do passaporte, pelo que raramente precisa de um segundo pedido:
{
"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"}
}
}Os cabeçalhos incluem o nome do evento, o ID da entrega, um carimbo temporal Unix e uma assinatura HMAC do corpo em bruto, para que possa verificar que veio de nós e rejeitar repetições:
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 com qualquer 2xx no prazo de 10 segundos. Tudo o resto é repetido cinco vezes ao longo de cerca de 90 minutos (30 s, 1 min, 5 min, 15 min, 1 h); após 10 falhas consecutivas o endpoint é pausado até o voltar a ativar.
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $endpointSecret);
abort_unless(hash_equals($expected, $request->header('X-MPP-Signature')), 401);