Guia da API de Identificadores
Um identificador liga uma marcação física a um Registo: uma etiqueta DUST, um código QR, um código de barras, um símbolo Data Matrix, um chip NFC ou um código de texto impresso. Depois de vinculado, uma digitalização no terreno é resolvida para o registo digital. O espaço de nomes da API é /api/v1/tags — uma designação legada que se mantém nos caminhos e esquemas; esta documentação utiliza identificador no texto.
Esquemas completos de pedidos/respostas: referência da API. Todos os resultados que cada operação pode produzir — incluindo os que chegam como erros HTTP — estão reunidos numa tabela em Erros e resultados de digitalização.
Resumo das operações
Seção intitulada “Resumo das operações”| Operação | Método e caminho | Semântica |
|---|---|---|
| Extrair | POST /api/v1/tags/extract | Analisar uma captura DUST para obter uma impressão digital canónica, sem vincular |
| Vincular | POST /api/v1/tags/bind | Associar um identificador a um Registo |
| Identificar | POST /api/v1/tags/identify | Pesquisar: que Registo corresponde a esta digitalização? |
| Verificar | POST /api/v1/tags/verify | Comparar uma digitalização com os identificadores de um Registo específico |
| Desvincular | POST /api/v1/tags/unbind | Separar um identificador do respetivo Registo |
| Definir texto | POST /api/v1/tags/text | Mudar o nome/a descrição de um identificador vinculado |
| Atualizar | POST /api/v1/tags/update | Ciclo de vida: privacidade, arquivar/restaurar (o valor e o tipo são imutáveis) |
Identificar ou verificar: identificar responde a «o que é isto?» — pesquisa os Registos visíveis para si (com âmbito definido por searchTeamIds) e devolve a correspondência, se existir. Verificar responde a «este é o item que afirma ser?» — indica um threadId e os identificadores candidatos vinculados ao mesmo, e a API confirma ou nega. Utilize a verificação para decisões de autenticação e a identificação para pesquisas.
Duas famílias de conteúdos
Seção intitulada “Duas famílias de conteúdos”Os endpoints de digitalização aceitam multipart/form-data, e a estrutura de data depende do tipo de identificador:
tagType | data | Origem |
|---|---|---|
DUST | Uma imagem — uma parte de ficheiro binário ou um URL de dados em base64 (data:image/jpeg;base64,…) | Uma captura ótica DUST proveniente de um scanner |
QR, BAR_CODE, DATA_MATRIX, NFC | O conteúdo descodificado da cadeia (ou o ID hexadecimal NFC) | Qualquer leitor de símbolos |
TEXT | O código legível por pessoas impresso, tal como uma pessoa o lê | Introdução pelo teclado ou inscrição de uma Etiqueta |
Uma captura DUST é uma fotografia da etiqueta, não um valor descodificado — o servidor extrai a impressão digital. As capturas provêm de hardware de digitalização DUST: consulte Integrar com o DUST Go para efetuar capturas em dispositivos móveis e o React Scanner para obter um componente Web pronto a integrar que processa todos os modos.
Em corpos multipart, os campos estruturados (options, tags, searchTeamIds) são transmitidos como cadeias JSON.
Identificadores de texto
Seção intitulada “Identificadores de texto”TEXT é o código legível por pessoas impresso num item ou numa Etiqueta — um número de série como AB00017. Não existe qualquer símbolo para descodificar, pelo que o valor é introduzido manualmente (ou provém do registo de inscrição de uma Etiqueta) e é guardado exatamente como foi introduzido. Uma vez que o leitor é uma pessoa, TEXT é o único tipo que a plataforma compara sem distinguir maiúsculas de minúsculas: identificar ou verificar com ab00017 encontra um AB00017 vinculado. Todos os outros tipos são comparados byte a byte.
Tal como os valores de QR, código de barras, Data Matrix e NFC, um código de texto pode ser copiado e não possui unicidade intrínseca — o mesmo código pode aparecer legitimamente em vários Registos ou em todas as Etiquetas de um Rolo. Um valor repetido nunca é rejeitado; o Rolo limita-se a comunicar as repetições como aviso.
Extrair uma captura DUST
Seção intitulada “Extrair uma captura DUST”A extração analisa uma captura para obter uma impressão digital canónica e devolve a respetiva qualidade — útil para conferir uma captura antes da inscrição ou para preparar uma vinculação:
curl -fsS "$APID_URL/api/v1/tags/extract" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "data=@scan.jpeg" \ -F 'options={"enrollmentSessionId":"3d5e…"}'A resposta é { id, qualityScore, annotatedImage?, forensics?, scan? } — id é o ID de uma impressão digital que pode vincular posteriormente sem voltar a carregar a imagem (ver abaixo). options também inclui metadados da captura (dispositivo, ótica, geolocalização) que a plataforma guarda com a digitalização.
O recibo da digitalização
Seção intitulada “O recibo da digitalização”Todas as operações que enviam uma imagem — extração, vinculação, identificação, verificação e análise de adulteração — devolvem um objeto scan que indica o que foi guardado:
{ "scanId": "…", "fingerprintId": "…", "dustId": "…" }scanIdestá sempre presente depois de a imagem ser guardada. É a identidade estável da captura e o valor a conservar caso registe as operações de digitalização do seu lado.fingerprintIdestá presente quando a extração foi bem-sucedida (caso contrário, énull).dustIdestá presente quando a operação lhe devolveu um DUST: o identificador criado por uma vinculação, confirmado por uma verificação ou resolvido por uma identificação. Énullnuma falta de correspondência, num resultado sem correspondência, numa extração, numa análise de adulteração (nesse caso, o identificador foi fornecido por si e não resolvido pela imagem) e numa identificação que tenha devolvido vários candidatos (cada candidato inclui o seu próprio identificador).
Uma falta de correspondência numa verificação e a ausência de correspondência numa identificação mantêm o respetivo estado e código de erro e incluem o mesmo recibo em detail.scan — a digitalização foi guardada apesar de o resultado ser negativo. O mesmo acontece com uma captura rejeitada por motivos de qualidade — por ter poucos pontos-chave utilizáveis ou nenhum — independentemente do código de erro comunicado pela operação (/tags/extract responde com SCAN_EXTRACTION_FAILURE; a identificação expõe SCAN_LOW_KEYPOINTS/SCAN_NO_KEYPOINTS; a verificação responde com o habitual IDENTIFIER_VERIFY_FAILED): a imagem é conservada e o respetivo recibo tem fingerprintId: null, porque não foi possível extrair nada utilizável. Apenas uma imagem que a plataforma não conseguiu descodificar de todo não é guardada nem tem recibo.
Vincular um identificador a um Registo
Seção intitulada “Vincular um identificador a um Registo”POST /api/v1/tags/bind aceita três estruturas, diferenciadas por tagType e pelo conteúdo:
curl -fsS "$APID_URL/api/v1/tags/bind" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "threadId=$THREAD_ID" \ -F "tagType=DUST" \ -F "tagDescription=Inbound receiving scan" \ -F "data=@scan.jpeg" \ -F 'options={"enrollmentSessionId":"3d5e…"}'# QR, BAR_CODE, DATA_MATRIX, NFC: the decoded contentscurl -fsS "$APID_URL/api/v1/tags/bind" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "threadId=$THREAD_ID" \ -F "tagType=QR" \ -F "data=https://example.com/item/SZ3J-11-ZJ17"# TEXT: the printed code as a person reads itcurl -fsS "$APID_URL/api/v1/tags/bind" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "threadId=$THREAD_ID" \ -F "tagType=TEXT" \ -F "data=AB00017"# Reuse a fingerprint from a prior /extract — no image re-uploadcurl -fsS "$APID_URL/api/v1/tags/bind" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "threadId=$THREAD_ID" \ -F "tagType=DUST" \ -F "fingerprintId=$FINGERPRINT_ID"options.enrollmentSessionId é opcional numa vinculação DUST. Forneça um UUID gerado pelo cliente — o mesmo durante toda uma execução — quando várias capturas fizerem parte do mesmo conjunto, como uma estação de inscrição a processar um lote ou uma captura de um item a partir de vários ângulos; a plataforma agrupa essas digitalizações nessa sessão. Omita-o por completo para uma vinculação pontual. As vinculações de imagens DUST também podem devolver a captura anotada com options.returnAnnotatedImage: true.
Vincular uma Etiqueta
Seção intitulada “Vincular uma Etiqueta”Se o identificador digitalizado pertencer a uma Etiqueta propriedade da Equipa do Registo (consulte Etiquetas), a vinculação não cria um identificador independente. Vincula a Etiqueta completa: todos os identificadores membros ativos são associados ao Registo numa única operação, e a resposta inclui label (a Etiqueta, o respetivo Rolo e a posição) e boundTags (todos os membros vinculados), além do tag habitual, que corresponde ao membro digitalizado. Transmita activateLabel: true para tornar também identificáveis os identificadores DUST da Etiqueta durante a vinculação; esta opção é facultativa. Uma Etiqueta já vinculada a outro Registo devolve IDENTIFIER_ALREADY_BOUND com detail.compositeTagId.
Identificar um Registo a partir de uma digitalização
Seção intitulada “Identificar um Registo a partir de uma digitalização”curl -fsS "$APID_URL/api/v1/tags/identify" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "tagType=DUST" \ -F "data=@scan.jpeg" \ -F 'searchTeamIds=["'"$TEAM_ID"'"]'const result = await client.tags.identify({ tagType: "DUST", data: scanBlob, searchTeamIds: [teamId],});A identificação também aceita conteúdos de valor (tagType de QR/BAR_CODE/DATA_MATRIX/NFC com os data descodificados ou TEXT com o código impresso, comparado sem distinguir maiúsculas de minúsculas) ou apenas um ID de identificador (tagType: "ANY" com tagId).
O que a identificação pode devolver
Seção intitulada “O que a identificação pode devolver”Uma correspondência devolve 200 com o identificador correspondente e o respetivo Registo. Uma ausência de correspondência é um estado de erro, não um 200 com um resultado vazio: uma ausência definitiva de correspondência é 404 IDENTIFIER_NOT_FOUND, enquanto uma pesquisa que não pôde ser concluída é 503 SCAN_SEARCH_INCOMPLETE — uma situação diferente que não pode ser apresentada a um operador como «não encontrado». Ambas incluem o recibo da digitalização em detail.scan.
A tabela canónica dos oito resultados — Registo identificado, vários candidatos, Etiqueta não vinculada, nenhuma correspondência, pesquisa incompleta, correspondência ambígua, captura rejeitada e identificador não vinculado — com o estado, código e resposta correta do cliente para cada um, encontra-se em Erros e resultados de digitalização → Resultados canónicos da identificação. Ramifique com base em code e leia detail.outcome (no_match, search_incomplete, ambiguous, quality_reject) quando precisar da distinção mais específica.
Todos os identificadores devolvidos que pertençam a uma Etiqueta incluem tag.label (a respetiva Etiqueta, Rolo e posição). Quando a digitalização corresponde a um membro de uma Etiqueta não vinculada no inventário da Equipa ativa, o resultado é { type: "label", label: { label, tags } }: ainda não existe um Registo, mas são devolvidos a Etiqueta e os respetivos identificadores membros, para que um cliente possa disponibilizar a respetiva vinculação (consulte Etiquetas).
Escolher o âmbito da pesquisa
Seção intitulada “Escolher o âmbito da pesquisa”searchTeamIds é uma matriz JSON de UUIDs de Equipas (uma cadeia JSON em corpos multipart). Se for omitido, a identificação pesquisa exatamente uma Equipa: a indicada por Dust-Ctx-Team-Id, que, por sua vez, tem como predefinição a Equipa raiz da organização.
Os IDs não são arbitrários. As Equipas da mesma organização às quais pertence estão sempre incluídas no âmbito; uma Equipa de uma organização parceira só fica acessível através de uma Ligação ativa que permita o fluxo dos respetivos dados para si. Tudo o resto é silenciosamente removido do âmbito, em vez de provocar a falha do pedido, pelo que um âmbito aparentemente amplo pode resultar numa pesquisa restrita. Obtenha os IDs válidos em vez de os codificar diretamente:
GET /api/v1/teams— as Equipas da sua organização às quais a sua credencial pertence ({ teams: [{ teamId, orgId, name, … }], total }).GET /api/v1/teams/connected— as Equipas parceiras nas quais pode pesquisar, sob a forma de registos de Ligação que identificam as duas Equipas ligadas.
Verificar uma digitalização relativamente a um Registo
Seção intitulada “Verificar uma digitalização relativamente a um Registo”A verificação é a primitiva de autenticação: perante uma digitalização recente, um threadId e os tags candidatos já vinculados a esse Registo, é bem-sucedida se qualquer candidato corresponder.
tags é obrigatório e é uma matriz de objetos — cada um com { "tagId": "…", "tagType": "…" } — e não uma matriz de cadeias de IDs. Num corpo multipart, é enviado como uma cadeia JSON:
curl -fsS "$APID_URL/api/v1/tags/verify" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -F "threadId=$THREAD_ID" \ -F "tagType=DUST" \ -F "data=@scan.jpeg" \ -F 'tags=[{"tagId":"'"$TAG_ID"'","tagType":"DUST"}]'const form = new FormData();form.set("threadId", threadId);form.set("tagType", "DUST");form.set("data", scanBlob);form.set("tags", JSON.stringify([{ tagId, tagType: "DUST" }]));Origem dos IDs candidatos
Seção intitulada “Origem dos IDs candidatos”Os valores de tagId são os identificadores já vinculados ao Registo que está a conferir. Leia-os a partir do Registo: GET /api/v1/threads/{thread_id} devolve-os em thread.tags, cada um com o respetivo tagId e tagType. Assim, uma verificação típica obtém o Registo, filtra os respetivos identificadores pelo tipo que acabou de capturar e envia-os como lista de candidatos:
const record = await getThread(threadId); // GET /api/v1/threads/{thread_id}const candidates = (record.thread.tags ?? []) .filter((tag) => tag.tagType === "DUST") .map((tag) => ({ tagId: tag.tagId, tagType: tag.tagType }));Enviar um identificador que não esteja vinculado a esse Registo faz com que a verificação falhe, em vez de permitir a correspondência com outra entidade.
Interpretar o resultado
Seção intitulada “Interpretar o resultado”O número de candidatos altera a estrutura da resposta, o que constitui o erro de integração mais frequente neste caso:
Comprimento de tags | Correspondência | Sem correspondência |
|---|---|---|
| Exatamente um | 200 com { tag, scan? } | IDENTIFIER_VERIFY_FAILED (HTTP 500), recibo em detail.scan |
| Dois ou mais | 200 com { success: true, verifiedTag, attemptedCount, failedCount, scan? } | 200 com { success: false, attemptedCount, failedCount, error, scan? } |
Assim, uma verificação com vários candidatos que falhe é uma chamada HTTP bem-sucedida com success: false. Nunca trate response.ok como prova de autenticidade — leia success sempre que enviar mais de um candidato. Consulte Erros e resultados de digitalização → Resultados da verificação.
Gerir identificadores vinculados
Seção intitulada “Gerir identificadores vinculados”Estes são endpoints JSON simples; todos exigem o tagId e o threadId do Registo ao qual o identificador está vinculado:
POST /api/v1/tags/text— definirnamee/oudescription.POST /api/v1/tags/update— definirname,description,isPrivateearchivedAt(um carimbo de data/hora ISO arquiva o identificador;nullrestaura-o). O valor e o tipo do identificador são imutáveis — volte a vinculá-lo.POST /api/v1/tags/unbind— separar o identificador do Registo.
Análise de adulteração
Seção intitulada “Análise de adulteração”Em /api/v1/tamper, uma Análise de adulteração compara uma nova digitalização de um identificador DUST com a referência capturada quando este foi vinculado e regista o que foi medido. A API devolve apenas medições e evidências — não existe, em qualquer ponto da interface, nenhum número de resumo, intervalo, limiar ou campo de resultado atribuído pela plataforma, e alignmentOutcome indica exclusivamente se foi possível comparar as duas digitalizações (quando não foi possível, as medições não são comparáveis, o que não constitui uma afirmação sobre o identificador).
| Operação | Método e caminho |
|---|---|
| Executar uma Análise | POST /api/v1/tamper/analyses — codificação de formulário: threadId, tagId e exatamente um de data ou queryFingerprintId |
| Registar uma Observação | POST /api/v1/tamper/observations — { analysisId, result } |
| Listar as Análises de um Registo | GET /api/v1/tamper/analyses?threadId=… (opcionalmente tagId, limit) |
| Obter uma Análise | GET /api/v1/tamper/analyses/{analysis_id} |
| Obter um mapa de bits do resultado | GET /api/v1/tamper/analyses/{analysis_id}/artifacts/{name} |
A execução de uma Análise recebe um corpo multipart/form-data ou application/x-www-form-urlencoded com threadId, tagId e exatamente um dos seguintes:
data— a própria digitalização DUST, como ficheiro ou imagem codificada em base64. O serviço efetua a extração.queryFingerprintId— o ID de uma impressão digital que já possua, proveniente dePOST /api/v1/tags/extract(acima), caso tenha efetuado a extração separadamente.
O envio de ambos, ou de nenhum, é rejeitado. Em qualquer caso, uma captura DUST normal é uma entrada válida — não existe um caminho de captura separado para a análise de adulteração. Se não for possível ler a digitalização enviada, o pedido falha e não é registada nenhuma Análise.
Uma Observação de adulteração é a única conclusão que a plataforma guarda e é emitida por uma pessoa: result assume um dos valores consistent, expected, inconsistent ou unknown, não possui predefinição e é obrigatório. expected regista o desgaste normal do caso de utilização e do substrato do identificador. As Observações são imutáveis e têm autoria atribuída; uma nova nunca substitui uma anterior, e as leituras devolvem toda a série (observations, da mais recente para a mais antiga), em vez de um único resultado atual. Não derive um resultado das métricas nem reduza a série a um único valor na sua própria IU.
Uma Análise inclui metrics (um objeto transmitido sem alterações com as frações de cobertura e as contagens de marcadores do algoritmo), markerPoints opcionais e artifactNames. Cada conjunto de coordenadas de marcadores encontra-se no espaço de píxeis da respetiva digitalização — componha-os num único referencial aplicando metrics.transformation_matrix aos pontos da consulta. Os mapas de bits do resultado são conteúdo protegido: obtenha-os através do endpoint de artefactos, que volta a autorizar cada pedido e devolve bytes que não podem ser colocados em cache.
Etiquetas
Seção intitulada “Etiquetas”Uma Etiqueta (nome na interface: composite tag, espaço de nomes /api/v1/composite-tags) é uma etiqueta física que contém um ou mais identificadores de qualquer tipo; DUST não é obrigatório. As Etiquetas ocupam uma posição num Rolo (collection.kind = "reel", identificado pelo respetivo UUID; o seu name é o número impresso no rolo ou qualquer título e nunca é único). Os Rolos podem ser arquivados numa Coleção de etiquetas (kind = "reel_collection"), uma pasta que nunca é enviada. O expectedIdentifiers de um Rolo indica quantos Identificadores de cada tipo uma Etiqueta completa desse Rolo contém, no formato [{ "tagType", "count" }] (por predefinição, um TEXT, um DUST e um QR; um count igual a 0 na entrada significa que o tipo não é esperado). Trata-se de uma indicação para estações de inscrição, não de uma restrição, e o sinalizador complete de uma Etiqueta significa que contém pelo menos esse número de Identificadores ativos de cada tipo esperado.
| Operação | Método e caminho |
|---|---|
| Listar/criar Coleções de etiquetas | GET, POST /api/v1/composite-tags/collections; PATCH …/collections/{collection_id} |
| Listar Rolos | GET /api/v1/composite-tags/reels?collectionId=…&unfiled=…&transferred=any|only|hide&q=… |
| Criar um Rolo | POST /api/v1/composite-tags/reels — { name, description?, collectionId?, expectedIdentifiers? } |
| Obter/atualizar um Rolo | GET, PATCH /api/v1/composite-tags/reels/{reel_collection_id} (mudar o nome, a composição esperada e collectionId para o mover; null deixa-o sem coleção) |
| Criar uma Etiqueta | POST /api/v1/composite-tags/reels/{reel_collection_id}/labels (multipart) |
| Adicionar/remover um identificador membro | POST /api/v1/composite-tags/{composite_tag_id}/identifiers (multipart); DELETE …/identifiers/{tag_id} |
| Listar/obter Etiquetas | GET /api/v1/composite-tags?reelCollectionId=…&bound=any|only|unbound&transferred=…&q=…; GET …/{composite_tag_id} |
| Resolver uma Etiqueta por um valor de membro | POST /api/v1/composite-tags/resolve — { tagType, value, reelCollectionId? } (TEXT é comparado sem distinguir maiúsculas de minúsculas); a resposta inclui detail (primeira correspondência) e candidates[] (todas as correspondências, pela ordem das posições quando é fornecido um Rolo) |
| Mover ou cortar Etiquetas | POST /api/v1/composite-tags/move; efetuar uma verificação prévia com POST /api/v1/composite-tags/move/preview |
| Vincular/desvincular uma Etiqueta | POST /api/v1/composite-tags/{composite_tag_id}/bind — { threadId, options?: { indexing: "default" } }; POST …/unbind |
| Vincular em massa um Intervalo do rolo | POST /api/v1/composite-tags/reels/{reel_collection_id}/bulk-bind — { fromPosition, toPosition, threadIds, activate?, dryRun? } |
| Arquivar/restaurar uma Etiqueta | POST …/{composite_tag_id}/archive, POST …/unarchive |
| Ativar | POST …/{composite_tag_id}/activate; POST /api/v1/composite-tags/reels/{reel_collection_id}/activate (em segundo plano) |
| Ativar identificadores DUST independentes | POST /api/v1/tags/activate — { tagIds[] } (até 200); um resultado por identificador, apenas progressivo |
Criar um Rolo e inscrever Etiquetas
Seção intitulada “Criar um Rolo e inscrever Etiquetas”curl -fsS "$APID_URL/api/v1/composite-tags/reels" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -H "Dust-Ctx-Team-Id: $DUST_TEAM_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "0030", "expectedIdentifiers": [{ "tagType": "TEXT", "count": 1 }, { "tagType": "DUST", "count": 1 }, { "tagType": "QR", "count": 1 }] }'A resposta é { reel }, um resumo do Rolo com contagens a zero. Conserve reel.collectionId; este identifica o Rolo. A criação de um Rolo cria sempre um novo: não existe reutilização pelo nome.
Cada Etiqueta corresponde a um pedido multipart. Forneça, no máximo, uma imagem DUST como data; todos os outros membros são transmitidos através de identifiers, uma matriz JSON de entradas { tagType, value }, ou { tagType: "DUST", fingerprintId } para um DUST adicional que já tenha sido extraído com POST /api/v1/tags/extract. humanReadable e qrValue são formas abreviadas de indicar um membro TEXT e um membro QR. Por predefinição, position corresponde à posição livre seguinte no Rolo.
curl -fsS "$APID_URL/api/v1/composite-tags/reels/$REEL_COLLECTION_ID/labels" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -H "Dust-Ctx-Team-Id: $DUST_TEAM_ID" \ -F "position=1" \ -F "data=@scan.jpeg" \ -F 'identifiers=[{"tagType":"TEXT","value":"AB00001"},{"tagType":"QR","value":"https://v.example/ab00001"}]' \ -F 'options={"indexing":"none"}'Tem de resultar pelo menos um identificador. Uma resposta bem-sucedida tem outcome: "created"; uma nova tentativa com a mesma marcação DUST na mesma posição é reconciliada como outcome: "already_enrolled". Um DUST que já esteja noutra Etiqueta ou já se encontre vinculado devolve 409 COMPOSITE_TAG_CONFLICT. Os valores TEXT ou QR repetidos nunca são rejeitados: o Rolo comunica-os em warnings, pois alguns rolos repetem legitimamente um valor.
options.indexing seleciona o modo de indexação DUST da imagem em data: default (identificável), a menos que solicite none (Apenas verificação). Normalmente, as estações de inscrição autónomas efetuam a inscrição em modo Apenas verificação e ativam posteriormente; a ativação indexa cada DUST e executa a verificação de duplicados da plataforma, pelo que uma Etiqueta cujo DUST duplique outro já indexado é comunicada e ignorada.
O fluxo equivalente com o cliente tipado é:
const created = await client.compositeTags.createReel({ name: "0030" });
const form = new FormData();form.set("position", "1");form.set("data", scanBlob);form.set("identifiers", JSON.stringify([{ tagType: "TEXT", value: "AB00001" }]));await client.compositeTags.createLabel(created.reel.collectionId, form);
const state = await client.compositeTags.getReel(created.reel.collectionId);await client.compositeTags.activateReel(created.reel.collectionId);Mover e cortar
Seção intitulada “Mover e cortar”POST /api/v1/composite-tags/move recebe uma source, um target e um expectedCount opcional.
Existem três estruturas de origem:
{ compositeTagIds }— Etiquetas selecionadas manualmente, movidas pela ordem indicada.{ reelCollectionId, fromPosition, toPosition? }— um intervalo de posições tipado (um corte); por predefinição,toPositioncorresponde à última posição do Rolo.{ fromCompositeTagId, toCompositeTagId }— um corte delimitado por digitalizações: a primeira e a última Etiqueta do intervalo, por qualquer ordem. O servidor lê as respetivas posições sob bloqueio; ambas têm de ser Etiquetas ativas no mesmo Rolo (caso contrário,endpoints_on_different_reels,endpoint_archivedouendpoint_not_on_reelemdetail.reason). Resolva cada Etiqueta a partir de um valor digitalizado com/resolve(limitado ao Rolo, para que um código impresso repetido seja apresentado como várioscandidatesque o autor da chamada terá de desambiguar) ou, no caso de um DUST ativado, comPOST /api/v1/tags/identify.
O target é { reelCollectionId } ou { newReel: { name, description?, collectionId?, expectedIdentifiers? } } (um Rolo novo herda a composição do Rolo de origem quando nenhuma é indicada).
Todas as Etiquetas ativas de um intervalo são movidas; as posições que contenham uma Etiqueta arquivada ou enviada, ou que não contenham qualquer Etiqueta, são lacunas que permanecem no Rolo de origem. As posições são mantidas quando todas estiverem livres no destino; caso contrário, todo o lote é acrescentado após a última posição do destino, pela ordem da origem. A resposta apresenta moved[] e, no caso de uma origem por intervalo ou delimitada por digitalizações, cut: { sourceReel, fromPosition, toPosition, count, boundCount, boundPositions, gaps[] }.
expectedCount torna a contagem contratual: quando é indicado, o movimento é recusado com 400 INVALID_REQUEST e detail.reason: "count_mismatch" (expected, actual, fromPosition, toPosition), a menos que sejam movidas exatamente esse número de Etiquetas ativas.
POST /api/v1/composite-tags/move/preview aceita a mesma source, um target opcional e expectedCount, não altera nada e devolve span, count, boundCount, a primeira (first) e a última (last) Etiquetas do lote, predictedOutcome (kept_positions/appended/null), countMatches e suggestedLast — a Etiqueta mais adiante no Rolo que permitiria cumprir expectedCount quando o intervalo é demasiado curto. É uma sugestão para o operador digitalizar, nunca aplicada pelo servidor. A verificação prévia está disponível para membros; o movimento exige um administrador da Equipa ou da Organização.
Vincular em massa um Intervalo do rolo
Seção intitulada “Vincular em massa um Intervalo do rolo”POST /api/v1/composite-tags/reels/{reel_collection_id}/bulk-bind vincula as Etiquetas nas posições fromPosition..toPosition (inclusive) aos threadIds, por ordem: a k-ésima posição ao k-ésimo Registo. A operação é estrita e executada na totalidade ou não é executada: o intervalo tem de abranger exatamente threadIds.length posições (toPosition é obrigatório e não é derivado, para que o autor da chamada indique o intervalo que verificou na bobina), com um máximo de 500 pares por chamada, e todas as posições têm de conter uma Etiqueta ativa e não vinculada. O servidor nunca ignora uma posição, pois tal deslocaria silenciosamente todos os emparelhamentos seguintes.
Transmita dryRun: true para efetuar a verificação prévia sem vincular. A estrutura da resposta é igual nos dois casos:
outcome—"bound"após uma vinculação real,"preflight"numa simulação.rows[]— uma por emparelhamento:index,position,compositeTagId(nullpara uma posição vazia),labelName,textValue(o membroTEXTda Etiqueta, ou seja, o código impresso),threadId,threadName,threadDescription.blockers[]ewarnings[]—{ kind, index, position, compositeTagId?, threadId?, tagType?, existing? }.activation—"queued","not_requested","already_active"ou"no_dust".reel— o resumo do Rolo com as contagens atualizadas.
Tipos de impedimento: position_empty, label_archived, label_transferred, label_bound, label_no_identifiers, identifier_bound_elsewhere, identifier_in_other_team_label, thread_not_owned, thread_unavailable, thread_in_transfer, thread_not_editable, thread_repeated. Tipos de aviso: label_incomplete (uma Etiqueta com menos Identificadores do que o Rolo espera) e thread_has_label (o Registo já contém uma Etiqueta; existing[] identifica-as). Os avisos nunca impedem uma vinculação.
Uma confirmação com qualquer impedimento falha com 409 COMPOSITE_TAG_CONFLICT; detail inclui os mesmos rows, blockers e warnings que uma simulação, pelo que um cliente só tem de analisar uma estrutura. Um intervalo cujo comprimento seja diferente de threadIds.length produz 400 INVALID_REQUEST.
Autoridade: associação à Equipa do Rolo e permissão de edição em cada Registo. Um Registo que o autor da chamada não possa editar constitui um impedimento thread_not_editable nessa linha, em vez de provocar a rejeição de todo o pedido, e todos os Registos têm de pertencer à Equipa do Rolo — um Registo apenas partilhado com a Equipa produz thread_not_owned.
Com activate: true, a vinculação é confirmada primeiro e, em seguida, uma tarefa em segundo plano ativa exatamente as marcações DUST das Etiquetas vinculadas; uma Etiqueta cuja ativação falhe permanece vinculada e no modo Apenas verificação. Consulte periodicamente counts.identifiableCount do Rolo para acompanhar o progresso.
# Preflightcurl -fsS "$APID_URL/api/v1/composite-tags/reels/$REEL_COLLECTION_ID/bulk-bind" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -H "Dust-Ctx-Team-Id: $DUST_TEAM_ID" \ -H "Content-Type: application/json" \ --data '{ "fromPosition": 1, "toPosition": 3, "threadIds": ["'$THREAD_1'", "'$THREAD_2'", "'$THREAD_3'"], "dryRun": true }'
# Commit, activating the bound Labels afterwardscurl -fsS "$APID_URL/api/v1/composite-tags/reels/$REEL_COLLECTION_ID/bulk-bind" \ -H "Authorization: Bearer $DUST_TOKEN" \ -H "Dust-Ctx-Org-Id: $DUST_ORG_ID" \ -H "Dust-Ctx-Team-Id: $DUST_TEAM_ID" \ -H "Content-Type: application/json" \ --data '{ "fromPosition": 1, "toPosition": 3, "threadIds": ["'$THREAD_1'", "'$THREAD_2'", "'$THREAD_3'"], "activate": true }'Com o cliente tipado:
const preview = await client.compositeTags.bulkBind(reelCollectionId, { fromPosition: 1, toPosition: threadIds.length, threadIds, dryRun: true,});if (preview.blockers.length === 0) { await client.compositeTags.bulkBind(reelCollectionId, { fromPosition: 1, toPosition: threadIds.length, threadIds, activate: true, });}A vinculação deixa exatamente os eventos que N vinculações individuais deixariam: um evento bind por identificador membro, cada um com o Registo, o identificador e a Etiqueta como alvos, todos com o mesmo ID de operação.
Vincular, desvincular e enviar
Seção intitulada “Vincular, desvincular e enviar”Uma Etiqueta é vinculada como um todo: POST …/{composite_tag_id}/bind associa a Etiqueta e todos os identificadores membros ativos ao Registo; options.indexing: "default" também a ativa. O mesmo acontece quando utiliza o POST /api/v1/tags/bind normal com qualquer identificador membro (consulte Vincular uma Etiqueta), que é o que fazem os scanners. A vinculação exige permissão de edição no Registo e que a Equipa seja proprietária da Etiqueta, e o Registo tem de pertencer à mesma Equipa: um identificador membro digitalizado para um Registo partilhado consigo por outra Equipa é recusado (409 COMPOSITE_TAG_CONFLICT, reason: "label_owned_by_other_team"), em vez de ser vinculado como uma cópia independente. POST …/unbind separa a Etiqueta e todos os respetivos membros.
A propriedade da Equipa e da Organização provém exclusivamente dos cabeçalhos de contexto, e o criador provém do token de portador verificado. A leitura e a ativação de Etiquetas exigem associação à Equipa. A criação de Rolos, inscrição, movimentação e arquivo são permitidos a um administrador autenticado da Equipa ou da Organização, ou a uma Conta de Serviço com âmbito de Organização que seja membro da Equipa selecionada; uma Conta de Serviço não pode beneficiar da autoridade de administrador da Organização.
Nos Envios, um Rolo é um item do manifesto ({ kind: "reel", collectionId }) e é enviado na totalidade, mas apenas quando todas as suas Etiquetas não estiverem vinculadas. Uma Etiqueta vinculada é enviada com o respetivo Registo e nunca inclui o respetivo Rolo no Envio. Os Rolos e as Etiquetas enviados continuam legíveis no lado do remetente, com transferredAt definido; filtre-os com transferred=only ou transferred=hide.
Consulte Etiquetas e Rolos para conhecer o fluxo de trabalho DICE.
Páginas relacionadas
Seção intitulada “Páginas relacionadas”- Erros e resultados de digitalização — as tabelas canónicas de resultados da identificação e da verificação e como conservar um recibo de digitalização em caso de falha
- Integrar com o DUST Go — capturar digitalizações DUST em dispositivos móveis
- React Scanner — um componente de captura pronto a copiar
- Guia da API de Registos — os registos aos quais os identificadores são vinculados
- Referência da API — esquemas completos, incluindo opções de metadados de captura