Erros e resultados de digitalização
Esta é a página de consulta para o tratamento de falhas: o corpo do erro devolvido por todos os endpoints, os códigos que justificam ramificações e — mais importante — as tabelas canónicas de resultados das digitalizações. Uma “ausência de correspondência” é um resultado, não uma falha de transporte, e ainda assim chega com um estado de erro HTTP. O código que trata todos os estados que não sejam 2xx como erros irá comunicar interrupções que nunca ocorreram.
Os esquemas específicos de cada endpoint encontram-se na referência da API. Os próprios fluxos encontram-se em Identificadores e no guia de início rápido.
O formato de erro
Seção intitulada “O formato de erro”Todos os pedidos que falham devolvem o mesmo objeto JSON:
{ "code": "IDENTIFIER_NOT_FOUND", "message": "No match in the 3 searched teams", "status": 404, "detail": { "outcome": "no_match", "teamsSearched": 3, "scan": { "scanId": "…", "fingerprintId": "…", "dustId": null } }}| Campo | Tipo | Significado |
|---|---|---|
code | string | Código estável e legível por máquina. Crie ramificações com base neste campo. Nunca analise message. |
message | string | Texto legível por pessoas, localizado de acordo com Dust-Ctx-Locale. A redação muda; os códigos não. |
status | number | Reflete o estado HTTP. |
detail | object, opcional | Contexto específico do erro: detalhes da validação, recibo da digitalização, classificação do resultado e identificadores de conflitos. |
status e o estado HTTP coincidem sempre, pelo que pode criar ramificações com base em qualquer um deles. Todas as respostas — de sucesso ou falha — também incluem um cabeçalho x-request-id. Registe-o; o suporte utiliza-o para localizar o seu pedido exato.
Códigos por classe
Seção intitulada “Códigos por classe”Pedido e autorização
Seção intitulada “Pedido e autorização”| Código | Estado | Quando |
|---|---|---|
INVALID_REQUEST | 400 | Corpo, consulta ou cabeçalho malformado. Os detalhes da validação encontram-se em detail. |
INVALID_DATA | 400 | O pedido foi analisado, mas os valores não podem ser utilizados (por exemplo, um conteúdo de identificação que o serviço de digitalização se recusou a ler). |
UNAUTHORIZED | 401 | Token bearer ausente, expirado ou inválido. |
FORBIDDEN | 403 | O contexto está autenticado, mas não pode efetuar esta ação. |
ATTRIBUTION_REQUIRED | 403 | A política de atribuição da Conta de serviço é required e a escrita não incluiu Dust-Ctx-Declared-Actor. |
ORG_ID_REQUIRED / TEAM_ID_REQUIRED | 400 | Falta um cabeçalho de contexto num endpoint com âmbito definido. |
NOT_FOUND / NO_DATA_FOUND | 404 | Nenhum registo desse tipo está visível neste contexto. |
RATE_LIMITED | 429 | Aguarde progressivamente e tente novamente. |
THREAD_DATA_CONFLICT | 409 | Conflito de concorrência otimista: o seu expectedUpdatedAt está desatualizado. Volte a ler e a aplicar. |
COMPOSITE_TAG_CONFLICT | 409 | Conflito de Etiqueta — um DUST já se encontra noutra Etiqueta ou está vinculado noutro local, uma Posição do Rolo está ocupada ou está a ser removido o último Identificador de uma Etiqueta. detail.reason indica qual destas situações ocorreu. |
UNKNOWN_ERROR / SERVICE_ERROR | 500 | Falha do lado do servidor. Tente novamente com espera progressiva; inclua o identificador do pedido se a falha persistir. |
Identificadores e digitalização
Seção intitulada “Identificadores e digitalização”| Código | Estado | Significado |
|---|---|---|
IDENTIFIER_NOT_FOUND | 404 | Uma ausência de correspondência definitiva: todas as partições pesquisadas responderam e não foi encontrada qualquer correspondência. |
IDENTIFIER_NOT_BOUND | 404 | O Identificador existe, mas não está vinculado a nenhum Registo (apenas acessível através de uma identificação por tagId). |
IDENTIFIER_ALREADY_BOUND | 409 | Vinculação recusada — esse Identificador (ou a respetiva Etiqueta) já se encontra noutro Registo. detail.compositeTagId identifica a Etiqueta. |
IDENTIFIER_VERIFY_FAILED | 500 | A verificação de um único Identificador não encontrou correspondência ou o Identificador indicado não está vinculado a esse Registo. |
SCAN_AMBIGUOUS_MATCH | 409 | Dois ou mais DUSTs inscritos distintos corresponderam e ambos estão vinculados no âmbito pesquisado. Não é possível repetir a tentativa com a mesma captura. |
SCAN_SEARCH_INCOMPLETE | 503 | Algumas partições responderam “sem correspondência”, mas não foi possível pesquisar outras. Isto não é uma ausência de correspondência — tente novamente. |
SCAN_LOW_KEYPOINTS / SCAN_NO_KEYPOINTS | 400 | A própria captura foi rejeitada: contém muito pouco detalhe utilizável. Volte a digitalizar; não tente novamente com a mesma imagem. |
SCAN_IDENTICAL_SCAN | 400 | A imagem enviada contém exatamente os mesmos bytes de uma captura anterior. Efetue uma nova captura. |
SCAN_EXTRACTION_FAILURE | 500 | A extração falhou numa imagem que, de outro modo, foi aceite. |
SCAN_ROUTING_UNAVAILABLE | 503 | A operação não está disponível para esta organização (por exemplo, devido a um módulo que não está ativado) ou a respetiva rota está indisponível. |
SCAN_BACKEND_UNAVAILABLE | 503 | O backend de digitalização está temporariamente indisponível. A captura está correta — tente novamente, não volte a digitalizar. |
Resultados canónicos da identificação
Seção intitulada “Resultados canónicos da identificação”POST /api/v1/tags/identify tem oito resultados. Três são 200; os restantes chegam com estados de erro e continuam a ser respostas. Esta tabela é a fonte única tanto para integrações humanas como de agentes — a mesma tabela aparece nas skills dice-api-integration e dust-go-connect-integration.
| Resultado | HTTP | Corpo | O que significa | O que fazer |
|---|---|---|---|---|
| Registo identificado | 200 | { type: "identified", identified: { tag, thread, … }, scan? } | Foi encontrada correspondência com exatamente um Identificador vinculado. | Abrir o Registo. scan.dustId é o DUST resolvido. |
| Vários candidatos | 200 | { type: "matches", matches: [ … ], scan? } | Foi encontrada correspondência com mais de um Identificador vinculado ou é necessário desambiguar a correspondência. | Mostrar os candidatos e voltar a identificar por tagId (tagType: "ANY"). scan.dustId é null; cada candidato inclui o seu próprio valor. |
| Etiqueta não vinculada | 200 | { type: "label", label: { label, tags }, scan? } | A digitalização foi resolvida para um membro de uma Etiqueta no inventário da sua Equipa que ainda não está vinculada a nenhum Registo. | Disponibilizar a vinculação da Etiqueta. Não é uma ausência de correspondência. |
| Sem correspondência | 404 | code: "IDENTIFIER_NOT_FOUND", detail.outcome: "no_match" | Todas as partições pesquisadas responderam e não foi encontrada qualquer correspondência. detail.teamsSearched indica o âmbito. | Mostrar “não encontrado”. Não comunicar uma falha do serviço. O recibo encontra-se em detail.scan. |
| Pesquisa incompleta | 503 | code: "SCAN_SEARCH_INCOMPLETE", detail.outcome: "search_incomplete" | Algumas partições responderam “sem correspondência”; não foi possível aceder a outras. detail.teamsSearched, detail.teamsUnreachable, detail.orgsUnreachable. | Tentar novamente. Nunca apresentar este resultado como “não encontrado” — o item pode muito bem estar inscrito. |
| Correspondência ambígua | 409 | code: "SCAN_AMBIGUOUS_MATCH", detail.outcome: "ambiguous", detail.candidates, detail.boundCandidates, detail.attempts | Foi encontrada uma correspondência fiável com dois ou mais DUSTs vinculados. A plataforma pesquisou a mesma captura duas vezes antes de devolver este resultado. | Apresentar o resultado com o scan.scanId e contactar a DUST Identity. Uma nova captura do mesmo item não resolverá a situação. |
| Captura rejeitada | 400 | code: "SCAN_LOW_KEYPOINTS" / "SCAN_NO_KEYPOINTS" / "SCAN_IDENTICAL_SCAN", detail.outcome: "quality_reject" | Não foi possível utilizar a imagem. A rejeição por qualidade prevalece sobre todos os outros resultados das partições. | Pedir ao operador que volte a digitalizar. A imagem é conservada como Digitalização rejeitada; detail.scan.fingerprintId é null. |
| Identificador não vinculado | 404 | code: "IDENTIFIER_NOT_BOUND" | Ocorre apenas numa identificação por tagId (tagType: "ANY"): o Identificador existe, mas não tem Registo. | Disponibilizar a respetiva vinculação. |
detail.outcome é a classificação utilizada pelo servidor e é estável: no_match, search_incomplete, ambiguous, quality_reject. Crie primeiro ramificações com base em code e consulte detail.outcome quando precisar de uma distinção mais específica.
Criar ramificações com base num resultado de identificação
Seção intitulada “Criar ramificações com base num resultado de identificação”// Runs on your SERVER (it holds the bearer token).const response = await fetch(`${apidUrl}/api/v1/tags/identify`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Dust-Ctx-Org-Id": organizationId }, body: form,});const body = await response.json();
if (response.ok) { switch (body.type) { case "identified": return { kind: "thread", thread: body.identified.thread }; case "matches": return { kind: "candidates", candidates: body.matches }; case "label": return { kind: "unbound-label", label: body.label }; default: throw new Error(`Unknown identify result type: ${body.type}`); }}
switch (body.code) { case "IDENTIFIER_NOT_FOUND": // An answer, not an outage. return { kind: "no-match", scanId: body.detail?.scan?.scanId ?? null }; case "SCAN_SEARCH_INCOMPLETE": case "SCAN_BACKEND_UNAVAILABLE": return { kind: "retry", scanId: body.detail?.scan?.scanId ?? null }; case "SCAN_LOW_KEYPOINTS": case "SCAN_NO_KEYPOINTS": case "SCAN_IDENTICAL_SCAN": return { kind: "rescan", scanId: body.detail?.scan?.scanId ?? null }; case "SCAN_AMBIGUOUS_MATCH": return { kind: "ambiguous", scanId: body.detail?.scan?.scanId ?? null }; default: throw new Error(`${body.code}: ${body.message}`);}Resultados da verificação
Seção intitulada “Resultados da verificação”POST /api/v1/tags/verify comporta-se de forma diferente consoante o número de Identificadores candidatos enviados em tags, porque um candidato constitui uma pergunta de sim/não e vários constituem uma pesquisa:
Comprimento de tags | Correspondência | Sem correspondência |
|---|---|---|
| Exatamente um | 200 com { tag, scan? } | IDENTIFIER_VERIFY_FAILED (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 em massa que falha é uma chamada HTTP bem-sucedida com success: false. Consulte sempre success quando enviar mais de um candidato e nunca deduza a autenticidade apenas a partir de response.ok.
tags é obrigatório em todas as verificações. É uma matriz de objetos, não de identificadores:
[{ "tagId": "8f2b…", "tagType": "DUST" }]Os recibos de digitalização persistem após uma falha
Seção intitulada “Os recibos de digitalização persistem após uma falha”Todas as operações que enviam uma imagem — extração, vinculação, identificação, verificação e análise de adulteração — devolvem um recibo de digitalização que identifica o que foi armazenado:
{ "scanId": "…", "fingerprintId": "…", "dustId": "…" }- Em caso de sucesso, encontra-se no nível superior como
scan. - Num resultado negativo que tenha sido armazenado, encontra-se em
detail.scan— uma falta de correspondência na verificação, uma ausência de correspondência na identificação, uma vinculação recusada por duplicação ou uma rejeição por qualidade (na qualfingerprintIdénull, porque não foi extraído nada utilizável).
Capture scanId em ambos os casos. É a identidade estável da captura entre migrações de algoritmos e é o que o suporte necessita para consultar a imagem associada a um resultado contestado. Apenas uma imagem que a plataforma não tenha conseguido descodificar de todo não armazena nada e, nesse caso, não existe recibo.
const receipt = response.ok ? body.scan : body.detail?.scan;if (receipt) await recordScan(receipt.scanId, receipt.fingerprintId, receipt.dustId);dustId é o que a plataforma lhe devolveu, nunca uma correspondência interna não processada: é null numa falta de correspondência, numa ausência de correspondência, numa extração, numa análise de adulteração e numa identificação que devolveu vários candidatos.
Expiração e renovação de tokens
Seção intitulada “Expiração e renovação de tokens”Os tokens bearer têm uma duração curta e não existe qualquer token de renovação — é necessário voltar a trocar a credencial. Um token expirado resulta num 401 UNAUTHORIZED normal, indistinguível de um token revogado, pelo que deve tratar ambos da mesma forma:
- Renove proativamente.
GET /api/auth/tokendevolveexpiresIn(segundos) eexpiresAt(ISO 8601) sempre que o token contém uma declaração de expiração. Volte a efetuar a troca com alguma margem (60 segundos é confortável); nunca codifique uma duração fixa. - Tente novamente uma vez após um
401. Tanto o desvio do relógio como a revogação durante a validade resultam neste estado. Uma renovação seguida de uma nova tentativa é o adequado; um ciclo não é. - Emita um token por pedido a partir de uma cache, não apenas uma vez no arranque do processo, para que um trabalho que dure mais do que um token não falhe a meio.
A implementação completa encontra-se em Autenticação → Expiração e renovação de tokens.
Recomendações para novas tentativas
Seção intitulada “Recomendações para novas tentativas”| Situação | Tentar novamente o mesmo pedido? | Notas |
|---|---|---|
401 UNAUTHORIZED | Sim, uma vez, depois de voltar a trocar a credencial | Mais do que uma vez significa que a própria credencial está errada. |
429 RATE_LIMITED | Sim, com espera progressiva | |
503 SCAN_SEARCH_INCOMPLETE / SCAN_BACKEND_UNAVAILABLE | Sim — a captura está correta | Não obrigue o operador a voltar a digitalizar. |
503 SCAN_ROUTING_UNAVAILABLE | Não | A operação não está disponível para esta organização; contacte a DUST Identity. |
400 SCAN_LOW_KEYPOINTS / SCAN_NO_KEYPOINTS / SCAN_IDENTICAL_SCAN | Não — volte a digitalizar | Os mesmos bytes voltarão a ser rejeitados. |
404 IDENTIFIER_NOT_FOUND | Não | É uma resposta. |
409 SCAN_AMBIGUOUS_MATCH | Não | A tentativa já foi repetida no lado do servidor; detail.attempts indica-o. |
409 THREAD_DATA_CONFLICT | Voltar a ler, aplicar novamente e depois escrever | Não repita o pedido sem verificar — iria substituir as alterações de outra pessoa. |
5xx UNKNOWN_ERROR | Sim, com espera progressiva, para leituras idempotentes | Nas escritas, verifique se a escrita foi aplicada antes de tentar novamente. |
Consulte também
Seção intitulada “Consulte também”- Convenções dos pedidos — cabeçalhos, paginação e localização.
- Identificadores — as operações de digitalização que produzem estes resultados.
- Autenticação e chaves de API — credenciais e duração dos tokens.
- Referência da API — esquemas de resposta específicos de cada endpoint.