Guia do publicador
Publique seus produtos
Publicar no prodid é colocar dois arquivos na web e um registro no DNS. No seu próprio domínio não há cadastro nem chave para guardar: o domínio é a credencial, e você altera ou retira o que publica alterando os arquivos.
Como vai publicar?
Identidade e hospedagem são coisas separadas. Sua identidade é um domínio que você controla; onde os documentos são servidos é um detalhe que você pode mudar depois sem mudar sua identidade nem nenhum identificador que o prodid atribuiu aos seus produtos. Três caminhos, e todos produzem exatamente os mesmos registros.
Caminho 1
Você consegue servir arquivos no seu próprio domínio.
Sirva o documento de descoberta no domínio e publique um registro TXT que nomeie o próprio domínio.
- Identidade
- o domínio
- Confiança
- verified
Caminho 2
Você tem um domínio mas não consegue servir arquivos nele.
Publique num slug hospedado e aponte um registro TXT do seu domínio para esse host.
- Identidade
- o domínio, provado por DNS
- Confiança
- verified
Caminho 3
Você não tem domínio nenhum.
Publique num slug hospedado. Adicione um domínio depois sem perder nada.
- Identidade
- o host do slug
- Confiança
- unverified
Os caminhos 2 e 3 usam o serviço de publicação hospedado em <slug>.prodid.org. Entre em publish.prodid.org com um link enviado ao seu e-mail, crie um site, envie seu arquivo e conecte um domínio se tiver. Você pode exportar tudo ou excluir o site lá a qualquer momento.
Caminho 1
Publique no seu próprio domínio
Dois arquivos e um registro DNS. Uma plataforma que publica em nome de lojas faz o mesmo no domínio de cada uma, então cada loja mantém a própria identidade e o próprio nível de confiança.
Sirva o documento de descoberta
Um arquivo, num caminho fixo, listando onde estão seus feeds de produto:
https://acme.example/.well-known/prodid.json.well-known/prodid.jsonapplication/json{ "$type": "org.prodid.feed", "version": 1, "publisher": { "name": "Acme Tekstil", "contact": "data@acme.example" }, "license": "CC0-1.0", "feeds": ["https://acme.example/prodid/items.ndjson"] }O exemplo de spec/fixtures/v1/examples/prodid.json, gerado a partir do próprio arquivo. $typeObrigatório: sim- Sempre org.prodid.feed.
versionObrigatório: sim- 1. Um documento com 0 é aceito por rastreamentos que começam antes de 2027-01-26 00:00 UTC e recusado depois, como negativo definitivo.
publisher.nameObrigatório: sim- O nome que uma pessoa deve ver ao lado das suas afirmações.
publisher.contactObrigatório: não- Um e-mail que alguém realmente lê. É para onde o índice escreve quando sua fonte entra em lapse, e é o único aviso que você recebe.
licenseObrigatório: sim- Identificador SPDX que cobre as informações dos seus feeds, como CC0-1.0.
feedsObrigatório: sim- Até 100 URLs https, todas no mesmo host deste documento.
domainObrigatório: ao delegar- O domínio pelo qual este documento fala. Obrigatório sempre que se chega ao documento por um registro TXT que nomeia outro host, e então deve ser igual a esse domínio. Opcional quando o próprio domínio serve o documento, e, se presente, ainda precisa bater.
Sirva por HTTPS na porta padrão, com certificado válido, como
application/json, ou qualquerapplication/…+json. Não redirecione para outro host: o único redirecionamento que o rastreador segue é deacme.exampleparawww.acme.example.Sirva o feed
Um feed é NDJSON: um objeto JSON completo por linha, UTF-8, separado por quebra de linha. Sem array em volta, sem vírgulas entre as linhas. Assim um feed de dois milhões de produtos é lido linha a linha, e uma linha ruim custa só essa linha, não o resto.
prodid/items.ndjsonapplication/x-ndjson{"$type":"org.prodid.item","key":"TJ-2041-NVY-M","brand":"Acme","name":"Trail Jacket","lang":"en","group":"TJ-2041","variant":{"color":"navy","size":"M"},"identifiers":[{"scheme":"gtin","value":"09506000134352"},{"scheme":"mpn","value":"TJ-2041-NVY-M"}],"markets":["TR","DE"],"properties":{"material":"100% recycled polyester","madeIn":"TR","weight":{"value":480,"unit":"g"}},"media":[{"url":"https://acme.example/img/tj2041-navy.webp","license":"CC-BY-4.0","kind":"image"}]} {"$type":"org.prodid.item","key":"TJ-2041-NVY-L","brand":"Acme","name":"Trail Jacket","lang":"en","group":"TJ-2041","variant":{"color":"navy","size":"L"},"identifiers":[{"scheme":"gtin","value":"09506000134406"},{"scheme":"mpn","value":"TJ-2041-NVY-L"}],"markets":["TR","DE"],"properties":{"material":"100% recycled polyester","madeIn":"TR","weight":{"value":505,"unit":"g"}},"media":[{"url":"https://acme.example/img/tj2041-navy.webp","license":"CC-BY-4.0","kind":"image"}]} {"$type":"org.prodid.item","key":"TJ-2041-OLV-M","brand":"Acme","name":"Trail Jacket","lang":"en","group":"TJ-2041","variant":{"color":"olive","size":"M"},"identifiers":[{"scheme":"gtin","value":"09506000134413"},{"scheme":"mpn","value":"TJ-2041-OLV-M"}],"markets":["TR"],"properties":{"material":"100% recycled polyester","madeIn":"TR","weight":{"value":480,"unit":"g"}},"media":[{"url":"https://acme.example/img/tj2041-olive.webp","license":"CC-BY-4.0","kind":"image"}]}Três variantes de um produto, de spec/fixtures/v1/examples/items.ndjson. Elas compartilham um group, então o índice monta com elas uma família de três variantes. Feeds ficam no mesmo host do documento que os lista. Um documento de descoberta que nomeia um feed em outro host é rejeitado inteiro, não em parte: você perde a fonte toda, não um feed, e isso conta como negativo definitivo, então dispara o relógio de lapse descrito abaixo. Servir o JSON do seu site e o NDJSON de outro hostname de CDN é uma vontade normal e não é suportada na v1. Coloque os dois num host só.
A primeira dessas linhas, formatada para leitura:
um registro org.prodid.item{ "$type": "org.prodid.item", "key": "TJ-2041-NVY-M", "brand": "Acme", "name": "Trail Jacket", "lang": "en", "group": "TJ-2041", "variant": { "color": "navy", "size": "M" }, "identifiers": [ { "scheme": "gtin", "value": "09506000134352" }, { "scheme": "mpn", "value": "TJ-2041-NVY-M" } ], "markets": ["TR", "DE"], "properties": { "material": "100% recycled polyester", "madeIn": "TR", "weight": { "value": 480, "unit": "g" } }, "media": [{ "url": "https://acme.example/img/tj2041-navy.webp", "license": "CC-BY-4.0", "kind": "image" }] }$typeObrigatório: sim- Sempre org.prodid.item.
keyObrigatório: sim- Seu nome estável para este registro dentro do feed. Publicar a mesma key de novo substitui o anterior.
brandObrigatório: sim- A marca como aparece no produto. Ela é normalizada antes de delimitar um mpn, então ARÇELİK e Arçelik são uma marca, não duas.
nameObrigatório: sim- O nome do produto, sem os eixos de variante.
identifiersObrigatório: sim- Pelo menos um { scheme, value }, e pelo menos um que o índice consiga guardar. Valores não têm espaços nas pontas e não são vazios. Um gtin deve ter 8, 12, 13 ou 14 dígitos com dígito verificador correto e não ser só zeros; um mpn precisa de uma brand que normalize para algo, porque é nesse escopo que ele é único; um gtin de circulação restrita é mantido, mas só como o seu próprio rcn. Um registro sem nada que possa ser guardado não identifica nada e é ignorado.
langObrigatório: não- Tag BCP 47 do texto legível deste registro.
groupObrigatório: não- Sua própria chave de agrupamento. Itens que a compartilham são variantes de uma mesma família.
variantObrigatório: não- Os eixos que distinguem este item dentro do grupo: cor, tamanho, capacidade.
categoryObrigatório: não- Código de brick GS1 GPC, escrito gpc: seguido de oito dígitos.
marketsObrigatório: não- Códigos ISO 3166-1 alfa-2 dos mercados onde este item é vendido.
propertiesObrigatório: não- Strings, números, booleanos, listas ou { value, unit } para uma medida.
mediaObrigatório: não- Até 20 URLs https, cada uma com um kind e uma licença SPDX da lista aceita. Ao contrário dos feeds, podem estar em qualquer host.
Envie itens planos. Você nunca monta famílias ou variantes nem envia um
opid: o índice deriva o primeiro degroupe atribui o segundo. Se você já gera um feed do Google Merchant,groupé o seuitem_group_id.Duas coisas sobre códigos de barras que vale saber antes de exportar. Um
gtinsó de zeros não é código de barras, é um marcador de catálogo, e um registro com ele é rejeitado como se tivesse dígito verificador errado. Um número de circulação restrita, as faixas de uso interno da loja, é guardado e atribuído a você, mas não identifica nada globalmente, então nunca funde seu produto com o de outra pessoa e/01/não o resolve.Reivindique a identidade no DNS
Com os arquivos no ar, publique um registro que nomeie o seu próprio domínio como host.
_prodid.acme.example TXT_prodid.acme.example. IN TXT "v=prodid0; host=acme.example"Ele aponta exatamente para o que a descoberta teria encontrado de qualquer jeito, então nada muda nos seus dados. O que muda é o que alguém com acesso só de inclusão ao seu DNS consegue fazer. Sem registro, um que essa pessoa adicione toma sua identidade em silêncio, porque o DNS vence o arquivo. Com o seu registro já lá, um segundo faz a descoberta falhar com mais de um registro: um lapse visível, notificado e recuperável.
Nunca delegue
_prodida um fornecedor. Acesso de escrita a_prodid.<domain>é controle da sua identidade, exatamente como no DKIM ou num desafio ACME DNS-01. Um domínio com DNS compartilhado é uma identidade compartilhada. Dê o feed a uma agência, não o registro.Coloque os arquivos no ar antes do registro, não depois: um registro que aponta para um documento que ainda não existe é uma descoberta que falhou. Os valores são lidos sem diferenciar maiúsculas, e um ponto final não tem problema, então
ACME.Example.eacme.examplesão o mesmo host.Avise o índice da mudança
Opcional. Todo domínio conhecido é rastreado de novo numa agenda, e um ping só antecipa o próximo rastreamento.
pedir ao índice para rodar a descoberta agoracurl -X POST https://prodid.org/ping \ -H 'content-type: application/json' \ -d '{"domain": "acme.example"}' HTTP/1.1 202 Accepted Content-Type: application/json {"status":"accepted"}{"domains": [...]}aceita até 1000 de uma vez; é assim que uma plataforma apresenta cada loja que hospeda. Não há chave para enviar, porque o ping não dá a quem chama nenhum poder sobre o conteúdo, e202é tudo o que ele responde. Não diz se o domínio era conhecido, se algo foi encontrado nem se outra pessoa deu ping nele um minuto antes. Um429só quer dizer que você passou do seu próprio limite de requisições, e os erros voltam comoapplication/problem+json. O que aconteceu com o seu domínio aparece no status da sua fonte, não no ping.
Caminho 2
Delegue a hospedagem, mantenha a identidade
Muitos fabricantes têm um domínio e não conseguem colocar um arquivo nele. O feed fica hospedado em outro lugar e o domínio é provado por DNS, então a identidade da fonte continua sendo o domínio e o nível de confiança continua verified. Crie um site em publish.prodid.org, informe seu domínio e ele mostra o registro exato a adicionar e o verifica para você.
Como fica
Um catálogo enviado a um slug hospedado
, digamos
acme.prodid.org, que serve tanto o documento de descoberta quanto o feed.Um registro TXT no domínio que é seu
, nomeando esse host. Um host, nunca uma URL, então um registro nunca consegue mandar o rastreador para um endereço qualquer.
_prodid.acme.example TXT_prodid.acme.example. IN TXT "v=prodid0; host=acme.prodid.org"Um documento que nomeia o seu domínio de volta.
O DNS diz meu documento está lá; o documento diz eu falo por esse domínio. Um documento delegado sem
domainé rejeitado: ausência nunca é lida como consentimento, e é isso que impede alguém de apontar um registro para o feed de outra pessoa.acme.prodid.org/.well-known/prodid.jsonapplication/json{ "$type": "org.prodid.feed", "version": 1, "domain": "acme.example", "publisher": { "name": "Acme Tekstil", "contact": "data@acme.example" }, "license": "CC0-1.0", "feeds": ["https://acme.prodid.org/feeds/items.ndjson"] }De spec/fixtures/v1/examples/prodid.delegated.json. A única diferença para o caminho 1 é o campo domain, e aqui ele é obrigatório. Crie o seu site
O publicador hospedado só escreve
domainno documento depois de ver o seu registro TXT ele mesmo, então não existe um momento em que um documento reivindica um domínio que não pediu isso.
Caminho 3
Publique sem domínio
Crie o seu site
Um produtor sem domínio nenhum publica num slug hospedado,
<slug>.prodid.org, com o próprio nome. Reserve um em publish.prodid.org. A identidade da fonte é o host do slug e o nível de confiança éunverified, porque nada foi provado sobre um domínio. Os registros são registros de verdade: identificadores, resolução, atribuição.A maioria dos publicadores nessa situação já mantém um arquivo de produtos do Google Merchant, então o mapeamento de um desses para registros
org.prodid.itemestá escrito na especificação, coluna por coluna, junto com o que ele descarta de propósito: preço, disponibilidade, frete e condição pertencem a um vendedor num dia, não ao produto. Vale ler Importar um feed do Merchant antes de exportar: o publish.prodid.org converte o CSV ou TSV que você envia exatamente com esse mapeamento. Quatro pontos dele decidem como sua planilha precisa ser:- Quatro colunas viram eixos de variante:
color,size,materialepattern, as que um comprador escolhe dentro de um mesmoitem_group_id.gender,age_group,size_typeesize_systemcontinuam propriedades comuns: descrevem o grupo todo, e como eixos dividiriam um produto em vários na primeira vez que alguém escrevesse um deles de dois jeitos. - Um atributo repetido é separado por vírgula ou tem cabeçalho repetido, por arquivo, não por célula. Uma célula só é dividida nas vírgulas quando o cabeçalho dela aparece uma vez no arquivo todo; repita o cabeçalho e cada célula abaixo é lida inteira. É a única forma de levar um valor com vírgula, e é uma decisão que você toma uma vez para o arquivo. Vale para
additional_image_link,product_type,product_highlight,product_detailecertification; todo o resto, inclusive umadescriptioncheia de vírgulas, é lido inteiro de qualquer jeito. - Um
product_detailnunca sobrescreve nada. O subatributo do meio vira a chave da propriedade, o nome da seção é descartado e o primeiro valor de uma chave vence. Um detail posterior com a mesma chave, ou um que caia numa chave que o mapeamento já gerou, é descartado e relatado com a sua linha, então uma coluna de detail nunca redefine em silêncio o que o resto da linha disse. - É preciso declarar uma licença de mídia. O formato Merchant não tem coluna para isso e nada é ingerido sem licença, então uma importação declara um único identificador SPDX aceito cobrindo todas as imagens e documentos do arquivo. Uma coluna
licensesua substitui isso linha a linha, e um arquivo cuja licença declarada não é aceita gera registros sem mídia, e não registros com falha.
Uma linha que não pode virar registro (sem identificador utilizável, com um GTIN cujo dígito verificador falha) é ignorada e relatada pelo número da linha na planilha, contando o cabeçalho como linha 1, então uma linha ruim custa só essa linha e não a importação. Há um arquivo pronto para você se comparar em /spec/fixtures/merchant: um CSV, os registros que ele deve gerar e a linha que deve ser ignorada.
O que importa numa decisão de hoje é o que acontece depois. Adicionar um registro TXT num domínio que você adquirir, nomeando esse mesmo host, transforma o slug no domínio no próximo rastreamento: a mesma fonte, os mesmos registros, todo
opidmantido, com a confiança subindo deunverifiedparaverified. Seus identificadoresskusão vinculados à própria fonte, não ao nome dela, então sobrevivem à mudança. No publish.prodid.org é o mesmo campo de domínio que o caminho 2 usa.- Quatro colunas viram eixos de variante:
Verifique o seu domínio
Terminou de publicar? Introduza o seu domínio. O índice é solicitado a analisá-lo agora e você chega à página de estado em tempo real.
Antes de ir ao ar
Confira seus arquivos antes do ping
prodid-batch check valida seu documento de descoberta e cada feed exatamente como o índice faria, sem token e sem perguntar nada ao índice. Ele roda a partir de um clone do repositório com Bun 1.4.4. Passe os próprios arquivos: um caminho terminado em .json é lido como um documento, qualquer outro como feed NDJSON.
git clone https://github.com/productdevbook/prodid
cd prodid
bun install --frozen-lockfile
curl -fsSo prodid.json https://acme.example/.well-known/prodid.json
curl -fsSo items.ndjson https://acme.example/prodid/items.ndjson
bun apps/batch/src/cli.ts check prodid.json items.ndjson
prodid.json: ok, 1 record
items.ndjson: ok, 3 recordsUm arquivo sem problemas imprime ok e o número de registros que o índice tiraria dele. Senão, imprime uma linha por problema, como items.ndjson:12: message com a linha do feed onde está, e sai com código diferente de zero. Ele lê os arquivos, não o seu DNS nem o seu servidor, então o registro TXT, o content type e os cabeçalhos de cache da lista acima continuam sendo seus para conferir.
As regras contra as quais um registro é validado estão na especificação, os schemas são servidos em /spec/schemas/v1, e /spec/fixtures/v1 tem vetores legíveis por máquina para testar seu exportador antes que alguém o rastreie.
A especificação é publicada apenas em inglês, e o texto em inglês é o normativo.
Status: Spec v1. O índice e o publicador hospedado rodam em prodid.org. Qualquer pessoa pode publicar, no próprio domínio ou hospedado. Os formatos de arquivo desta página são os que o índice lê quando você dá ping nele.
Referência
Vale saber antes de tudo, porque decide qual dos três caminhos abaixo é o seu. A descoberta começa do zero a cada rastreamento, primeiro pelo DNS, e nada do caminho até seus dados é lembrado entre rastreamentos.
Primeiro
Um registro DNS TXT em
_prodid.acme.exampleSe houver um registro
v=prodid0, só ele é seguido, mesmo que nomeie o seu próprio domínio. O registro nomeia um host; o documento está sempre emhttps://<host>/.well-known/prodid.json.Só se não houver esse registro
https://acme.example/.well-known/prodid.jsonO documento no próprio domínio. Quem serve o domínio por HTTPS fala por ele.
O DNS vem primeiro porque é a prova mais forte: quem consegue colocar um arquivo num host nem sempre é o dono do domínio, e o dono precisa poder passar por cima disso. É também por isso que vale escrever o registro mesmo quando você serve o arquivo; caminho 1, passo 3 explica o que isso garante.
Exatamente um registro, e nada atrás dele. Mais de um registro v=prodid0 nesse nome é um erro, não uma escolha entre eles, e um único malformado ou longo demais também é erro. Não há plano B: se existe um registro e ele não funciona, a descoberta termina ali em vez de mandar o rastreador olhar o seu domínio. Se for trocar de host, substitua o registro; nunca adicione um segundo. A gramática, com vetores de teste, está na especificação.
O que conta como resposta. HTTP 200 depois de no máximo um redirecionamento, um content type JSON, um corpo que valida contra o schema do feed e um domain que nomeia o domínio sendo descoberto. Um site que responde caminhos desconhecidos com uma página HTML e 200 não está respondendo, nem um documento servido como text/html.
Confiança é uma propriedade da fonte, não de uma afirmação. Diz o que foi provado sobre quem está falando, e nada sobre se uma informação específica está correta. Quem usa os dados decide o que fazer com isso.
| Nível | Significado |
|---|---|
| authoritative | Controle do domínio provado e propriedade da marca confirmada. |
| verified | Controle do domínio provado, pelo registro TXT ou pelo domínio servindo o documento. |
| unverified | Um slug hospedado sem domínio, uma importação de conjunto de dados ou uma contribuição da comunidade. |
Só uma fonte cuja identidade é um domínio pode ser mais do que unverified. verified vem do rastreamento. authoritative não, porque nenhum rastreamento prova quem é dono de uma marca: o operador do índice concede, e só com evidência.
A evidência é o seu prefixo de empresa GS1.
O prefixo de empresa GS1 dos GTINs que sua fonte publica sob a marca deve estar licenciado para a organização que controla o seu domínio, como mostra a consulta pública “Verified by GS1”. A URL dessa consulta é guardada com a concessão como evidência.
Uma concessão nomeia uma marca, e cada uma pode ser revogada.
A marca é registrada na forma normalizada. Uma fonte pode ter concessões para várias marcas, e o operador revoga cada uma separadamente.
Uma concessão não sobrevive à prova que a sustenta.
Sua fonte é
authoritativeexatamente enquanto o controle do domínio estiver provado, ela não estiver lapsed e tiver ao menos uma concessão não revogada. Perca a prova de domínio ou entre em lapse, e ela cai na hora para o que a prova restante sustenta (verifiedenquanto em lapse, menos se a prova de domínio também sumiu) sem ninguém fazer nada. Ela volta a serauthoritativeassim que as três condições valerem de novo.Ela cobre a fonte, não a marca.
Confiança continua sendo propriedade da fonte: uma concessão para uma marca torna
authoritativetoda afirmação da sua fonte, inclusive sobre marcas para as quais ela não tem concessão.
Para pedir, publique primeiro no seu próprio domínio e depois faça o pedido pelo formulário, informando seu domínio, a marca e uma consulta Verified by GS1 de um dos GTINs dela. O operador confere no Verified by GS1 os GTINs que sua fonte publica sob essa marca. O pedido é público.
Publicar um registro com uma key que já existe substitui o anterior. Não há endpoint de atualização, porque o feed é o estado.
Uma key que some de um feed que o rastreador baixou inteiro marca suas afirmações sobre ela como retiradas. A entidade e o identificador ficam: os links de outras pessoas continuam funcionando, assim como as afirmações de outras fontes.
Quando um rastreamento lê um documento que não nomeia mais uma das suas URLs de feed, todo registro ativo daquele feed é retirado na hora, como se todas as keys tivessem sumido, e a URL não é mais buscada. A tolerância de sete dias descrita abaixo não vale aqui: remover uma URL é você dizendo que o arquivo acabou, e o índice acredita em você. Listá-la de novo depois a traz de volta, lida do zero. Sirva o documento com um ETag se puder: um 304 quer dizer que a lista não mudou, então nada é desativado.
Uma linha com mais de 64 KiB, que não dá para interpretar ou inválida é ignorada e contada. Como a key de uma linha ignorada é desconhecida, um feed com linhas ignoradas não retira nada por sete dias. Depois disso, keys ausentes são retiradas normalmente. A contagem é pública, então um feed perdendo linhas em silêncio não fica em silêncio.
Um rastreamento só dá certo quando tudo o que o documento lista foi lido: um documento aceitável, e cada feed nele respondendo 200 ou 304. Um feed com timeout não faz você perder os outros (os que responderam são ingeridos, e nada é retirado num rastreamento que falhou), mas o rastreamento conta como falha de transporte, e feeds_failed mostra isso no seu status. Um documento perfeitamente saudável na frente de uma URL de feed morta de vez entra em lapse no mesmo relógio de sete dias de um domínio que parou de responder, e perde o catálogo trinta dias depois. Uma URL de feed que você não serve mais deve sair do documento, não ficar largada.
Um negativo definitivo, ou seja, uma descoberta que termina sem documento aceitável (sem registro e sem documento; um registro malformado, longo demais ou duplicado; ou um documento que não é 200, não é JSON, não é válido, não concorda mais sobre domain ou lista um feed fora do seu host), coloca a fonte em lapse na hora. Uma falha de transporte (timeout de DNS, 5xx, 429, limite atingido, no documento ou em qualquer feed) não muda nada sozinha, mas sete dias seguidos em que toda tentativa termina assim também colocam você em lapse, então servir erros para sempre não é um jeito de congelar suas afirmações.
Esse benefício da dúvida pertence a um host, não a você. Ele só vale num host em que sua fonte já foi verificada. Num host em que ela nunca foi verificada (um slug novo, um host para onde você acabou de apontar _prodid, tudo nos caminhos 2 e 3), qualquer falha, timeout e 5xx incluídos, é negativo definitivo e coloca você em lapse na hora. É de propósito: senão uma fonte verificada poderia apontar o registro para um host que não controla e descobrir, pelo lapse começar hoje ou daqui a uma semana, se esse host está no ar. Trocar de host não custa nada por causa disso. O primeiro rastreamento bem-sucedido no host novo limpa tudo, e um lapse continua recuperável durante os 30 dias antes de qualquer retirada.
Uma fonte em lapse não recebe afirmações novas, aparece como lapsed para os leitores, e o seu publisher.contact é avisado. Um rastreamento de uma fonte em lapse não grava nada até dar certo por completo; só então o lapse é removido. Depois de 30 dias seguidos de lapse, seus registros e as afirmações ativas deles são retirados juntos e ficam como histórico. Esses 30 dias são sua janela de recuperação, e é por isso que o endereço de contato precisa ser lido por alguém.
Voltar não exige mudar nada. Sirva o mesmo documento e o mesmo feed de sempre e tudo o que você publica é afirmado de novo no instante em que a descoberta dá certo, tenha mudado um byte ou não: enquanto não guarda nada ativo seu, o índice abre mão de requisições condicionais, então um arquivo sem mudança nunca é motivo para continuar retirado.
Toda afirmação que um leitor vê carrega seen_at: não quando a informação foi publicada pela primeira vez em algum lugar, mas desde quando esta fonte afirma este valor sem parar. Ele sobrevive a todo novo rastreamento que encontra o mesmo valor, e esse é o objetivo. Não sobrevive a uma retirada. Deixe sua fonte em lapse por mais de 30 dias e a data de cada informação que você publica recomeça no dia em que você voltar, porque durante o intervalo ninguém verificável estava por trás delas. As linhas retiradas ficam, então ?history=1 mostra o intervalo em vez de escondê-lo; o que um leitor vê está na especificação.
/source/acme.example é onde você vê que algo está errado: o resultado do último rastreamento, qual caminho a descoberta seguiu, quantos registros mudaram, quantas linhas foram ignoradas, quantos feeds não puderam ser lidos e se você está em lapse e desde quando. Ela só informa o que o seu domínio publica e quando o índice olhou, nunca quem pediu um rastreamento.
{
"$type": "org.prodid.source",
"version": 1,
"name": "acme.example",
"kind": "domain",
"trust": "verified",
"verified_by": "dns-txt",
"verified_at": "2026-09-14T09:12:03Z",
"lapsed": false,
"license": "CC0-1.0",
"last_crawl": {
"at": "2026-09-19T06:00:11Z",
"via": "dns-txt",
"document_url": "https://acme.prodid.org/.well-known/prodid.json",
"outcome": "success",
"http_status": 200,
"records_seen": 3,
"records_changed": 1,
"lines_skipped": 0,
"feeds_failed": 0,
"media_failed": 0
}
}O tipo é decidido lendo os bytes; o seu Content-Type é uma dica. Seis tipos são guardados e nada mais: JPEG, PNG, GIF, WebP e AVIF como image, PDF como document. Sem SVG, sem HTML, sem arquivos compactados, sem arquivos do Office: uma ficha técnica vai em PDF. O tipo detectado e o kind da entrada precisam bater, ou a entrada é ignorada.
| O quê | Limite |
|---|---|
| Uma imagem | 20 MiB |
| Um documento | 50 MiB |
| Um download de mídia | 60 s |
| Entradas de mídia num registro | 20 |
A licença é verificada como texto antes de qualquer download, e precisa ser exatamente um de sete identificadores SPDX: os que deixam qualquer pessoa redistribuir o arquivo como está, que é o que o índice faz com ele:
CC0-1.0 CC-BY-4.0 CC-BY-SA-4.0 CC-BY-ND-4.0
CC-BY-3.0 CC-BY-SA-3.0 CC-BY-ND-3.0Tudo aqui é por entrada. Uma entrada recusada, grande demais ou inacessível custa só essa entrada: seu registro nunca é inválido por causa da mídia, as outras afirmações valem e nenhuma falha de mídia coloca você em lapse. Ela é contada em media_failed e tentada de novo no próximo rastreamento desse registro. Uma coisa funciona ao contrário dos feeds: a regra do mesmo host não vale aqui, então suas imagens podem ficar numa CDN. O que é ingerido e a lista de licenças explicam o porquê.
Varejistas, registros, conjuntos de dados abertos e colaboradores são fontes como qualquer outra. As afirmações deles são atribuídas a eles e nunca sobrescrevem as suas; onde vocês discordam, as duas afirmações ficam visíveis lado a lado com suas fontes.