Zum Inhalt springen

Leitfaden zur Identifiers API

Eine Kennung verbindet eine physische Markierung mit einem Datensatz: ein DUST-Tag, einen QR-Code, einen Barcode, ein Data-Matrix-Symbol, einen NFC-Chip oder einen gedruckten Textcode. Nach der Verknüpfung wird ein Scan vor Ort dem digitalen Datensatz zugeordnet. Der API-Namespace lautet /api/v1/tags – eine veraltete Benennung, die in Pfaden und Schemas fortbesteht; in diesen Dokumenten wird im Fließtext Kennung verwendet.

Vollständige Anfrage-/Antwortschemas: API-Referenz. Jedes Ergebnis, das die einzelnen Operationen liefern können – einschließlich jener, die als HTTP-Fehler zurückgegeben werden –, ist einmal unter Fehler und Scanergebnisse tabellarisch aufgeführt.

OperationMethode & PfadSemantik
ExtrahierenPOST /api/v1/tags/extractEine DUST-Aufnahme in einen kanonischen Fingerabdruck umwandeln, ohne ihn zu verknüpfen
VerknüpfenPOST /api/v1/tags/bindEine Kennung einem Datensatz zuordnen
IdentifizierenPOST /api/v1/tags/identifySuchen: Welcher Datensatz stimmt mit diesem Scan überein?
VerifizierenPOST /api/v1/tags/verifyEinen Scan mit den Kennungen eines bestimmten Datensatzes vergleichen
Verknüpfung lösenPOST /api/v1/tags/unbindEine Kennung von ihrem Datensatz trennen
Text festlegenPOST /api/v1/tags/textEine verknüpfte Kennung umbenennen bzw. neu beschreiben
AktualisierenPOST /api/v1/tags/updateLebenszyklus: Datenschutz, Archivieren/Wiederherstellen (Wert und Typ sind unveränderlich)

Identifizieren oder verifizieren: Die Identifizierung beantwortet die Frage „Was ist das?“ – sie durchsucht die für Sie sichtbaren Datensätze (eingegrenzt durch searchTeamIds) und gibt gegebenenfalls die Übereinstimmung zurück. Die Verifizierung beantwortet die Frage „Ist dies das Objekt, das es zu sein vorgibt?“ – Sie geben eine threadId und die damit verknüpften möglichen Kennungen an, und die API bestätigt oder verneint die Übereinstimmung. Verwenden Sie die Verifizierung für Authentifizierungsentscheidungen und die Identifizierung zum Nachschlagen.

Scan-Endpunkte akzeptieren multipart/form-data; die Struktur von data hängt vom Kennungstyp ab:

tagTypedataHerkunft
DUSTEin Bild – ein binärer Dateiteil oder eine Base64-Daten-URL (data:image/jpeg;base64,…)Eine optische DUST-Aufnahme von einem Scanner
QR, BAR_CODE, DATA_MATRIX, NFCDer decodierte Zeichenfolgeninhalt (oder die hexadezimale NFC-ID)Ein beliebiger Symbolscanner
TEXTDer gedruckte, menschenlesbare Code in der Form, in der eine Person ihn liestTastatureingabe oder Registrierung eines Etiketts

Eine DUST-Aufnahme ist ein Foto des Tags, kein decodierter Wert – der Server extrahiert den Fingerabdruck. Aufnahmen stammen von DUST-Scanhardware: Informationen zur mobilen Aufnahme finden Sie unter Integration mit DUST Go, und der React Scanner ist eine direkt einsetzbare Webkomponente, die alle Modi unterstützt.

In Multipart-Nutzdaten werden strukturierte Felder (options, tags, searchTeamIds) als JSON-Zeichenfolgen übergeben.

TEXT ist der menschenlesbare Code, der auf einen Gegenstand oder ein Etikett gedruckt ist – beispielsweise eine Seriennummer wie AB00017. Es gibt kein zu decodierendes Symbol; der Wert wird daher eingegeben (oder stammt aus dem Registrierungsdatensatz eines Etiketts) und exakt wie eingegeben gespeichert. Da eine Person den Code liest, ist TEXT der einzige Typ, bei dem die Plattform ohne Beachtung der Groß-/Kleinschreibung nach Übereinstimmungen sucht: Bei der Identifizierung oder Verifizierung mit ab00017 wird ein verknüpftes AB00017 gefunden. Bei jedem anderen Typ erfolgt der Abgleich Byte für Byte.

Wie QR-, Barcode-, Data-Matrix- und NFC-Werte kann auch ein Textcode kopiert werden und besitzt keine eigene Eindeutigkeit – derselbe Code kann berechtigterweise auf mehreren Datensätzen oder auf jedem Etikett einer Etikettenrolle vorkommen. Ein wiederholter Wert wird nicht abgelehnt; die Etikettenrolle meldet Wiederholungen lediglich als Warnung.

Beim Extrahieren wird eine Aufnahme in einen kanonischen Fingerabdruck umgewandelt und dessen Qualität zurückgegeben. Dies ist hilfreich, um eine Aufnahme vor der Registrierung zu prüfen oder eine Verknüpfung vorzubereiten:

Terminal-Fenster
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…"}'

Die Antwort lautet { id, qualityScore, annotatedImage?, forensics?, scan? } – id ist eine Fingerabdruck-ID, die Sie später verknüpfen können, ohne das Bild erneut hochzuladen (siehe unten). options enthält außerdem Aufnahmemetadaten (Gerät, Optik, Geolokalisierung), die von der Plattform zusammen mit dem Scan gespeichert werden.

Jede Operation, die ein Bild übermittelt – Extrahieren, Verknüpfen, Identifizieren, Verifizieren und Manipulationsanalyse –, gibt ein scan-Objekt zurück, das angibt, was gespeichert wurde:

{ "scanId": "…", "fingerprintId": "…", "dustId": "…" }
  • scanId ist immer vorhanden, sobald das Bild gespeichert wurde. Sie ist die stabile Identität der Aufnahme und der Wert, den Sie aufbewahren sollten, wenn Sie Scanvorgänge auf Ihrer Seite erfassen.
  • fingerprintId ist vorhanden, wenn die Extraktion erfolgreich war (andernfalls null).
  • dustId ist vorhanden, wenn die Operation Ihnen eine DUST-Kennung zurückgegeben hat: die durch eine Verknüpfung erstellte Kennung, eine durch eine Verifizierung bestätigte Kennung oder eine durch eine Identifizierung aufgelöste Kennung. Bei einer Nichtübereinstimmung, keiner Übereinstimmung, einer Extraktion oder einer Manipulationsanalyse ist der Wert null (die dortige Kennung haben Sie angegeben; sie wurde nicht anhand des Bildes aufgelöst). Das gilt auch für eine Identifizierung, die mehrere Kandidaten zurückgibt, da jeder Kandidat seine eigene Kennung enthält.

Bei einer fehlgeschlagenen Verifizierungsübereinstimmung und einer Identifizierung ohne Übereinstimmung bleiben der bestehende Fehlerstatus und Fehlercode erhalten; derselbe Beleg wird unter detail.scan mitgeführt – der Scan wurde gespeichert, obwohl das Ergebnis negativ war. Dasselbe gilt für eine wegen ihrer Qualität abgelehnte Aufnahme – zu wenige oder keine nutzbaren Schlüsselpunkte –, unabhängig davon, welchen Fehlercode die jeweilige Operation dafür meldet (/tags/extract antwortet mit SCAN_EXTRACTION_FAILURE, die Identifizierung liefert SCAN_LOW_KEYPOINTS / SCAN_NO_KEYPOINTS, und die Verifizierung antwortet mit dem üblichen IDENTIFIER_VERIFY_FAILED): Das Bild wird aufbewahrt, und sein Beleg enthält fingerprintId: null, da nichts Nutzbares daraus extrahiert wurde. Nur wenn die Plattform ein Bild überhaupt nicht decodieren konnte, wird nichts gespeichert und kein Beleg erstellt.

POST /api/v1/tags/bind akzeptiert drei anhand von tagType und den Nutzdaten unterscheidbare Formen:

Terminal-Fenster
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…"}'

options.enrollmentSessionId ist bei einer DUST-Verknüpfung optional. Geben Sie eine vom Client erzeugte UUID an – dieselbe für einen gesamten Durchlauf –, wenn mehrere Aufnahmen zusammengehören, etwa wenn eine Registrierungsstation einen Stapel verarbeitet oder ein Objekt aus mehreren Blickwinkeln aufgenommen wird; die Plattform gruppiert diese Scans dann unter dieser Sitzung. Lassen Sie die Angabe bei einer einmaligen Verknüpfung vollständig weg. Bei DUST-Bildverknüpfungen kann mit options.returnAnnotatedImage: true außerdem die kommentierte Aufnahme zurückgegeben werden.

Wenn die gescannte Kennung zu einem Etikett gehört, dessen Eigentümer das Team des Datensatzes ist (siehe Etiketten), erstellt die Verknüpfung keine einzelne Kennung. Stattdessen wird das gesamte Etikett verknüpft: Jede aktive Mitgliedskennung wird in einer einzigen Operation an den Datensatz angefügt. Die Antwort enthält zusätzlich zum üblichen tag, also dem von Ihnen gescannten Mitglied, auch label (das Etikett, seine Etikettenrolle und seine Position) sowie boundTags (alle verknüpften Mitglieder). Übergeben Sie activateLabel: true, um im Rahmen der Verknüpfung auch die DUST-Kennungen des Etiketts identifizierbar zu machen; dies ist optional. Ist ein Etikett bereits mit einem anderen Datensatz verknüpft, wird IDENTIFIER_ALREADY_BOUND mit detail.compositeTagId zurückgegeben.

Terminal-Fenster
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"'"]'

Die Identifizierung akzeptiert auch Wertnutzdaten (tagType gleich QR/BAR_CODE/DATA_MATRIX/NFC mit den decodierten data oder TEXT mit dem gedruckten Code, der ohne Beachtung der Groß-/Kleinschreibung abgeglichen wird) sowie eine alleinstehende Kennungs-ID (tagType: "ANY" mit tagId).

Ein Treffer gibt 200 mit der übereinstimmenden Kennung und ihrem Datensatz zurück. Ein Fehlschlag hat einen Fehlerstatus und ist keine 200-Antwort mit einem leeren Ergebnis: Eine definitive Nichtübereinstimmung ist 404 IDENTIFIER_NOT_FOUND, während eine Suche, die nicht abgeschlossen werden konnte, 503 SCAN_SEARCH_INCOMPLETE ergibt – eine andere Situation, die einer Bedienperson nicht als „nicht gefunden“ angezeigt werden darf. Beide enthalten den Scanbeleg unter detail.scan.

Die kanonische Tabelle aller acht Ergebnisse – identifizierter Datensatz, mehrere Kandidaten, unverknüpftes Etikett, keine Übereinstimmung, unvollständige Suche, mehrdeutige Übereinstimmung, abgelehnte Aufnahme und nicht verknüpfte Kennung – einschließlich Status, Code und korrekter Clientreaktion finden Sie unter Fehler und Scanergebnisse → Kanonische Identifizierungsergebnisse. Verzweigen Sie anhand von code, und lesen Sie detail.outcome (no_match, search_incomplete, ambiguous, quality_reject), wenn Sie die genauere Unterscheidung benötigen.

Jede zurückgegebene Kennung, die zu einem Etikett gehört, enthält tag.label (ihr Etikett, ihre Etikettenrolle und ihre Position). Wenn der Scan mit einem Mitglied eines unverknüpften Etiketts im Bestand des aktiven Teams übereinstimmt, lautet das Ergebnis { type: "label", label: { label, tags } }: Es gibt noch keinen Datensatz, aber das Etikett und seine Mitgliedskennungen werden zurückgegeben, sodass ein Client die Verknüpfung anbieten kann (siehe Etiketten).

searchTeamIds ist ein JSON-Array von Team-UUIDs (in Multipart-Nutzdaten eine JSON-Zeichenfolge). Wenn Sie es weglassen, durchsucht die Identifizierung genau ein Team: das durch Dust-Ctx-Team-Id angegebene Team, wobei standardmäßig das Stammteam der Organisation verwendet wird.

Die IDs sind nicht beliebig. Teams derselben Organisation, denen Sie angehören, liegen immer im Umfang; das Team einer Partnerorganisation ist nur über eine aktive Verbindung erreichbar, die den Datenfluss zu Ihnen zulässt. Alles andere wird stillschweigend aus dem Umfang entfernt, statt die Anfrage fehlschlagen zu lassen. Ein scheinbar großer Umfang kann daher nur eine kleine Menge durchsuchen. Ermitteln Sie die gültigen IDs, statt sie fest zu codieren:

  • GET /api/v1/teams – die Teams in Ihrer Organisation, denen Ihre Anmeldedaten zugeordnet sind ({ teams: [{ teamId, orgId, name, … }], total }).
  • GET /api/v1/teams/connected – die Partnerteams, die Sie durchsuchen dürfen, als Verbindungsdatensätze, in denen die beiden verknüpften Teams genannt sind.

Die Verifizierung ist das grundlegende Authentifizierungsverfahren: Anhand eines neuen Scans, einer threadId und der bereits mit diesem Datensatz verknüpften möglichen tags ist sie erfolgreich, wenn ein Kandidat übereinstimmt.

tags ist erforderlich und ein Array von Objekten – jeweils { "tagId": "…", "tagType": "…" } –, kein Array aus ID-Zeichenfolgen. In Multipart-Nutzdaten wird es als JSON-Zeichenfolge gesendet:

Terminal-Fenster
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" }]));

Die tagId-Werte sind die bereits mit dem zu prüfenden Datensatz verknüpften Kennungen. Lesen Sie sie aus dem Datensatz: GET /api/v1/threads/{thread_id} gibt sie in thread.tags zurück, jeweils mit tagId und tagType. Eine typische Verifizierung ruft daher den Datensatz ab, filtert seine Kennungen nach dem soeben aufgenommenen Typ und sendet sie als Kandidatenliste:

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 }));

Wenn Sie eine Kennung senden, die nicht mit diesem Datensatz verknüpft ist, schlägt die Verifizierung fehl, statt eine Übereinstimmung mit etwas anderem zu finden.

Die Anzahl der Kandidaten verändert die Antwortstruktur, was hier der mit Abstand häufigste Integrationsfehler ist:

Länge von tagsÜbereinstimmungKeine Übereinstimmung
Genau einer200 mit { tag, scan? }IDENTIFIER_VERIFY_FAILED (HTTP 500), Beleg unter detail.scan
Zwei oder mehr200 mit { success: true, verifiedTag, attemptedCount, failedCount, scan? }200 mit { success: false, attemptedCount, failedCount, error, scan? }

Eine Verifizierung mehrerer Kandidaten ohne Übereinstimmung ist somit ein erfolgreicher HTTP-Aufruf, der success: false enthält. Behandeln Sie response.ok niemals als Nachweis der Authentizität – lesen Sie immer success, wenn Sie mehr als einen Kandidaten senden. Siehe Fehler und Scanergebnisse → Verifizierungsergebnisse.

Dies sind einfache JSON-Endpunkte; sie alle erfordern sowohl die tagId als auch die threadId des Datensatzes, mit dem die Kennung verknüpft ist:

  • POST /api/v1/tags/text – name und/oder description festlegen.
  • POST /api/v1/tags/update – name, description, isPrivate und archivedAt festlegen (ein ISO-Zeitstempel archiviert die Kennung; null stellt sie wieder her). Wert und Typ der Kennung sind unveränderlich – führen Sie stattdessen eine erneute Verknüpfung durch.
  • POST /api/v1/tags/unbind – die Kennung vom Datensatz trennen.

Unter /api/v1/tamper vergleicht eine Manipulationsanalyse einen neuen Scan einer DUST-Kennung mit der bei ihrer Verknüpfung erstellten Referenzaufnahme und erfasst die ermittelten Messwerte. Die API gibt ausschließlich Messwerte und Nachweise zurück – es gibt auf der gesamten Oberfläche weder eine zusammenfassende Zahl noch ein Band, einen Schwellenwert oder ein von der Plattform erstelltes Ergebnisfeld. alignmentOutcome gibt ausschließlich an, ob die beiden Scans überhaupt verglichen werden konnten. Wenn dies nicht möglich war, sind die Messwerte nicht vergleichbar; dies ist keine Aussage über die Kennung.

OperationMethode & Pfad
Eine Analyse ausführenPOST /api/v1/tamper/analyses – formularcodiert: threadId, tagId und genau eines von data oder queryFingerprintId
Eine Beobachtung erfassenPOST /api/v1/tamper/observations – { analysisId, result }
Analysen eines Datensatzes auflistenGET /api/v1/tamper/analyses?threadId=… (optional tagId, limit)
Eine Analyse abrufenGET /api/v1/tamper/analyses/{analysis_id}
Eine Ergebnis-Bitmap abrufenGET /api/v1/tamper/analyses/{analysis_id}/artifacts/{name}

Zum Ausführen einer Analyse wird eine multipart/form-data- oder application/x-www-form-urlencoded-Nutzdatenstruktur mit threadId, tagId und genau einer der folgenden Angaben benötigt:

  • data – der DUST-Scan selbst als Datei oder Base64-codiertes Bild. Der Dienst extrahiert ihn für Sie.
  • queryFingerprintId – eine Fingerabdruck-ID, die Sie bereits über POST /api/v1/tags/extract (siehe oben) erhalten haben, falls Sie sie separat extrahiert haben.

Werden beide oder keine der Angaben gesendet, wird die Anfrage abgelehnt. In beiden Fällen ist eine gewöhnliche DUST-Aufnahme eine gültige Eingabe – für die Manipulationsanalyse gibt es keinen separaten Aufnahmepfad. Kann der übermittelte Scan nicht gelesen werden, schlägt die Anfrage fehl und es wird keine Analyse erfasst.

Eine Manipulationsbeobachtung ist die einzige Schlussfolgerung, die von der Plattform gespeichert wird, und sie wird von einer Person verfasst: result ist entweder consistent, expected, inconsistent oder unknown, besitzt keinen Standardwert und ist erforderlich. expected erfasst die für den Anwendungsfall und das Trägermaterial der Kennung normale Abnutzung. Beobachtungen sind unveränderlich und einer Person zugeordnet; eine neue Beobachtung ersetzt niemals eine frühere, und Lesevorgänge geben die gesamte Reihe (observations, neueste zuerst) statt eines einzelnen aktuellen Ergebnisses zurück. Leiten Sie kein Ergebnis aus den Messwerten ab und reduzieren Sie die Reihe in Ihrer eigenen Benutzeroberfläche nicht auf einen einzelnen Wert.

Eine Analyse enthält metrics (ein unverändert weitergereichtes Objekt mit den Abdeckungsanteilen und Markerzahlen des Algorithmus), optionale markerPoints und artifactNames. Die Markerkoordinatensätze befinden sich jeweils im Pixelraum ihres eigenen Scans – führen Sie sie in einem Koordinatensystem zusammen, indem Sie metrics.transformation_matrix auf die Abfragepunkte anwenden. Ergebnis-Bitmaps sind geschützte Inhalte: Rufen Sie sie über den Artefaktendpunkt ab, der jede Anfrage erneut autorisiert und nicht zwischenspeicherbare Bytes zurückgibt.

Ein Etikett (Bezeichnung im Übertragungsformat: composite tag, Namespace /api/v1/composite-tags) ist ein physisches Etikett mit einer oder mehreren Kennungen beliebigen Typs; DUST ist nicht erforderlich. Etiketten befinden sich an einer Position auf einer Etikettenrolle (collection.kind = "reel", identifiziert durch ihre UUID; ihr name ist die gedruckte Rollennummer oder ein beliebiger Titel und niemals eindeutig). Etikettenrollen können in einer Etikettensammlung (kind = "reel_collection") abgelegt werden, einem Ordner, der niemals versendet wird. expectedIdentifiers einer Etikettenrolle gibt in der Form [{ "tagType", "count" }] an, wie viele Kennungen jedes Typs ein vollständiges Etikett darauf enthält (standardmäßig eine TEXT-, eine DUST- und eine QR-Kennung; ein Eingabewert count von 0 bedeutet, dass der Typ nicht erwartet wird). Dies ist ein Hinweis für Registrierungsstationen, keine Einschränkung. Das complete-Flag eines Etiketts bedeutet, dass es mindestens die erwartete Anzahl aktiver Kennungen jedes Typs besitzt.

OperationMethode & Pfad
Etikettensammlungen auflisten/erstellenGET, POST /api/v1/composite-tags/collections; PATCH …/collections/{collection_id}
Etikettenrollen auflistenGET /api/v1/composite-tags/reels?collectionId=…&unfiled=…&transferred=any|only|hide&q=…
Eine Etikettenrolle erstellenPOST /api/v1/composite-tags/reels – { name, description?, collectionId?, expectedIdentifiers? }
Eine Etikettenrolle abrufen/aktualisierenGET, PATCH /api/v1/composite-tags/reels/{reel_collection_id} (umbenennen, erwartete Zusammensetzung, collectionId zum Verschieben; null entfernt sie aus dem Ordner)
Ein Etikett erstellenPOST /api/v1/composite-tags/reels/{reel_collection_id}/labels (Multipart)
Eine Mitgliedskennung hinzufügen/entfernenPOST /api/v1/composite-tags/{composite_tag_id}/identifiers (Multipart); DELETE …/identifiers/{tag_id}
Etiketten auflisten/abrufenGET /api/v1/composite-tags?reelCollectionId=…&bound=any|only|unbound&transferred=…&q=…; GET …/{composite_tag_id}
Ein Etikett anhand eines Mitgliedswerts auflösenPOST /api/v1/composite-tags/resolve – { tagType, value, reelCollectionId? } (TEXT wird ohne Beachtung der Groß-/Kleinschreibung abgeglichen); die Antwort enthält detail (erste Übereinstimmung) und candidates[] (alle Übereinstimmungen, bei Angabe einer Etikettenrolle nach Position sortiert)
Etiketten verschieben oder abtrennenPOST /api/v1/composite-tags/move; Vorabprüfung mit POST /api/v1/composite-tags/move/preview
Ein Etikett verknüpfen/Verknüpfung lösenPOST /api/v1/composite-tags/{composite_tag_id}/bind – { threadId, options?: { indexing: "default" } }; POST …/unbind
Einen Rollenbereich massenverknüpfenPOST /api/v1/composite-tags/reels/{reel_collection_id}/bulk-bind – { fromPosition, toPosition, threadIds, activate?, dryRun? }
Ein Etikett archivieren/wiederherstellenPOST …/{composite_tag_id}/archive, POST …/unarchive
AktivierenPOST …/{composite_tag_id}/activate; POST /api/v1/composite-tags/reels/{reel_collection_id}/activate (im Hintergrund)
Einzelne DUST-Kennungen aktivierenPOST /api/v1/tags/activate – { tagIds[] } (bis zu 200); ein Ergebnis je Kennung, nur vorwärtsgerichtet

Eine Etikettenrolle erstellen und Etiketten registrieren

Abschnitt betitelt „Eine Etikettenrolle erstellen und Etiketten registrieren“
Terminal-Fenster
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 }] }'

Die Antwort lautet { reel }, eine Zusammenfassung der Etikettenrolle mit Zählerständen von null. Bewahren Sie reel.collectionId auf; damit wird die Etikettenrolle identifiziert. Beim Erstellen einer Etikettenrolle wird immer eine neue erstellt: Eine Wiederverwendung anhand des Namens findet nicht statt.

Jedes Etikett wird mit einer eigenen Multipart-Anfrage erstellt. Geben Sie höchstens ein DUST-Bild als data an; jedes weitere Mitglied wird über identifiers übergeben, ein JSON-Array mit Einträgen der Form { tagType, value }, oder als { tagType: "DUST", fingerprintId } für eine weitere DUST-Kennung, die bereits über POST /api/v1/tags/extract extrahiert wurde. humanReadable und qrValue sind Kurzformen für ein TEXT- bzw. ein QR-Mitglied. position verwendet standardmäßig die nächste freie Position auf der Etikettenrolle.

Terminal-Fenster
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"}'

Es muss mindestens eine Kennung entstehen. Eine erfolgreiche Antwort enthält outcome: "created"; ein erneuter Versuch mit derselben DUST-Markierung an derselben Position wird als outcome: "already_enrolled" abgeglichen. Ist eine DUST-Kennung bereits einem anderen Etikett zugeordnet oder bereits verknüpft, wird 409 COMPOSITE_TAG_CONFLICT zurückgegeben. Wiederholte TEXT- oder QR-Werte werden niemals abgelehnt: Die Etikettenrolle meldet sie stattdessen unter warnings, da manche Etikettenrollen berechtigterweise einen Wert wiederholen.

options.indexing wählt den DUST-Indexierungsmodus für das Bild in data: default (identifizierbar), sofern Sie nicht none (nur verifizierbar) anfordern. Unbeaufsichtigte Registrierungsstationen registrieren in der Regel zunächst nur verifizierbare Kennungen und aktivieren sie später. Bei der Aktivierung wird jede DUST-Kennung indexiert und die Duplikatprüfung der Plattform ausgeführt. Ein Etikett, dessen DUST-Kennung eine bereits indexierte Kennung dupliziert, wird daher gemeldet und übersprungen.

Der entsprechende Ablauf mit dem typisierten Client lautet:

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);

POST /api/v1/composite-tags/move akzeptiert eine source, ein target und einen optionalen expectedCount.

Es gibt drei Formen für die Quelle:

  • { compositeTagIds } – einzeln ausgewählte Etiketten, die in der angegebenen Reihenfolge verschoben werden.
  • { reelCollectionId, fromPosition, toPosition? } – ein typisierter Positionsbereich (ein abgetrennter Bereich); toPosition verwendet standardmäßig die letzte Position der Etikettenrolle.
  • { fromCompositeTagId, toCompositeTagId } – ein durch Scans begrenzter abgetrennter Bereich: das erste und letzte Etikett des Abschnitts, in beliebiger Reihenfolge. Der Server liest ihre Positionen unter einer Sperre; beide müssen aktive Etiketten auf derselben Etikettenrolle sein (andernfalls steht endpoints_on_different_reels, endpoint_archived oder endpoint_not_on_reel in detail.reason). Lösen Sie jedes Etikett anhand eines gescannten Werts mit /resolve auf. Grenzen Sie die Suche dabei auf die Etikettenrolle ein, damit ein wiederholter gedruckter Code als mehrere candidates erscheint, zwischen denen der Aufrufer unterscheiden kann. Bei einer aktivierten DUST-Kennung können Sie alternativ POST /api/v1/tags/identify verwenden.

Das target ist { reelCollectionId } oder { newReel: { name, description?, collectionId?, expectedIdentifiers? } } (eine neue Etikettenrolle übernimmt die Zusammensetzung der Quellrolle, wenn keine angegeben wird).

Jedes aktive Etikett innerhalb eines Abschnitts wird verschoben; Positionen mit einem archivierten oder versendeten Etikett oder ganz ohne Etikett sind Lücken, die auf der Quellrolle verbleiben. Die Positionen bleiben erhalten, wenn jede davon auf dem Ziel frei ist; andernfalls wird der gesamte Stapel in der Reihenfolge der Quelle an die letzte Position des Ziels angehängt. Die Antwort listet moved[] auf und enthält bei einer Bereichsquelle oder einer durch Scans begrenzten Quelle außerdem cut: { sourceReel, fromPosition, toPosition, count, boundCount, boundPositions, gaps[] }.

Mit expectedCount wird die Anzahl zum verbindlichen Wert: Ist die Angabe vorhanden, wird das Verschieben mit 400 INVALID_REQUEST und detail.reason: "count_mismatch" (expected, actual, fromPosition, toPosition) abgelehnt, sofern nicht genau so viele aktive Etiketten verschoben würden.

POST /api/v1/composite-tags/move/preview akzeptiert dieselbe source, ein optionales target und expectedCount, ändert nichts und gibt span, count, boundCount, das first und last Etikett des Stapels, predictedOutcome (kept_positions / appended / null), countMatches und suggestedLast zurück – das weiter hinten auf der Etikettenrolle liegende Etikett, mit dem expectedCount erfüllt würde, wenn der Abschnitt zu kurz ist. Es ist lediglich ein Vorschlag an die Bedienperson, welches Etikett gescannt werden sollte, und wird vom Server niemals angewendet. Die Vorschau erfordert die Mitgliedsstufe; für das Verschieben ist ein Team- oder Organisationsadministrator erforderlich.

POST /api/v1/composite-tags/reels/{reel_collection_id}/bulk-bind verknüpft die Etiketten an den Positionen fromPosition..toPosition (einschließlich) der Reihe nach mit threadIds: die k-te Position mit dem k-ten Datensatz. Die Operation erfolgt vollständig oder gar nicht und ist strikt: Der Bereich muss genau threadIds.length Positionen umfassen (toPosition ist erforderlich und wird nicht abgeleitet, sodass der Aufrufer den auf der Spule verifizierten Bereich ausdrücklich angibt), pro Aufruf sind höchstens 500 Paare zulässig, und jede Position muss ein aktives, unverknüpftes Etikett enthalten. Der Server überspringt niemals eine Position, da dadurch jedes nachfolgende Paar unbemerkt verschoben würde.

Übergeben Sie dryRun: true, um eine Vorabprüfung ohne Verknüpfung auszuführen. Die Antwortstruktur ist in beiden Fällen identisch:

  • outcome – "bound" nach einer tatsächlichen Verknüpfung, "preflight" bei einem Probelauf.
  • rows[] – ein Eintrag je Paarung: index, position, compositeTagId (null bei einer leeren Position), labelName, textValue (das TEXT-Mitglied des Etiketts, also der gedruckte Code), threadId, threadName, threadDescription.
  • blockers[] und warnings[] – { kind, index, position, compositeTagId?, threadId?, tagType?, existing? }.
  • activation – "queued", "not_requested", "already_active" oder "no_dust".
  • reel – die Zusammenfassung der Etikettenrolle mit aktualisierten Zählerständen.

Arten von Blockierungen: 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. Arten von Warnungen: label_incomplete (ein Etikett mit weniger Kennungen, als von der Etikettenrolle erwartet werden) und thread_has_label (der Datensatz trägt bereits ein Etikett; existing[] nennt diese). Warnungen verhindern eine Verknüpfung niemals.

Ein Übernahmeversuch mit mindestens einer Blockierung schlägt mit 409 COMPOSITE_TAG_CONFLICT fehl; detail enthält dieselben rows, blockers und warnings wie ein Probelauf, sodass ein Client immer nur eine Struktur verarbeiten muss. Unterscheidet sich die Länge eines Bereichs von threadIds.length, wird 400 INVALID_REQUEST zurückgegeben.

Berechtigung: Teammitgliedschaft für die Etikettenrolle sowie Bearbeitungsberechtigung für jeden Datensatz. Ein Datensatz, den der Aufrufer nicht bearbeiten darf, erzeugt für die betreffende Zeile die Blockierung thread_not_editable, statt die gesamte Anfrage unmittelbar abzulehnen. Außerdem muss jeder Datensatz Eigentum des Teams der Etikettenrolle sein – ein lediglich mit dem Team geteilter Datensatz ergibt thread_not_owned.

Bei activate: true wird zunächst die Verknüpfung übernommen; anschließend aktiviert ein einzelner Hintergrundauftrag genau die DUST-Markierungen der verknüpften Etiketten. Ein Etikett, dessen Aktivierung fehlschlägt, bleibt verknüpft und nur verifizierbar. Fragen Sie den Wert counts.identifiableCount der Etikettenrolle ab, um den Fortschritt zu verfolgen.

Terminal-Fenster
# Preflight
curl -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 afterwards
curl -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 }'

Mit dem typisierten Client:

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,
});
}

Die Verknüpfung hinterlässt genau die Ereignisse, die N einzelne Verknüpfungen erzeugen würden: ein bind-Ereignis je Mitgliedskennung, das jeweils den Datensatz, die Kennung und das Etikett als Ziele enthält; alle teilen dieselbe Operations-ID.

Ein Etikett wird als Ganzes verknüpft: POST …/{composite_tag_id}/bind fügt das Etikett und jede aktive Mitgliedskennung an den Datensatz an; mit options.indexing: "default" wird es außerdem aktiviert. Dasselbe geschieht, wenn Sie das gewöhnliche POST /api/v1/tags/bind mit einer beliebigen Mitgliedskennung aufrufen (siehe Ein Etikett verknüpfen), wie es Scanner tun. Für die Verknüpfung sind eine Bearbeitungsberechtigung für den Datensatz und das Eigentum des Teams am Etikett erforderlich; zudem muss der Datensatz Eigentum desselben Teams sein. Wird eine Mitgliedskennung auf einen Datensatz gescannt, den ein anderes Team mit Ihnen geteilt hat, wird dies abgelehnt (409 COMPOSITE_TAG_CONFLICT, reason: "label_owned_by_other_team"), statt die Kennung als einzelne Kopie zu verknüpfen. POST …/unbind trennt das Etikett und alle seine Mitglieder vom Datensatz.

Das Eigentum von Team und Organisation wird ausschließlich aus Kontext-Headern abgeleitet, und der Ersteller aus dem verifizierten Bearer-Token. Zum Lesen und Aktivieren von Etiketten ist eine Teammitgliedschaft erforderlich. Das Erstellen von Etikettenrollen sowie das Registrieren, Verschieben und Archivieren ist für angemeldete Team- oder Organisationsadministratoren oder für ein organisationsweit gültiges Servicekonto zulässig, das Mitglied des ausgewählten Teams ist; ein Servicekonto kann die Berechtigung eines Organisationsadministrators nicht übernehmen.

In Sendungen ist eine Etikettenrolle ein Manifestobjekt ({ kind: "reel", collectionId }) und wird vollständig versendet, jedoch nur, solange jedes Etikett darauf unverknüpft ist. Ein verknüpftes Etikett wird mit seinem Datensatz versendet und zieht niemals seine Etikettenrolle in die Sendung hinein. Versendete Etikettenrollen und Etiketten bleiben auf der Absenderseite lesbar, wobei transferredAt gesetzt ist; filtern Sie sie mit transferred=only oder transferred=hide.

Informationen zum DICE-Workflow finden Sie unter Etiketten und Etikettenrollen.