Traceability labels

The secondary labels staff print and stick on a container, with the printed file attached and a group id per print run.

When a container is opened or a preparation is made, staff print a label and stick it on: what it is, where it came from, when it was opened, when it has to go. These are the secondary shelf-life labels, the ones an inspector turns over in their hand — and this collection is the record of each one that was printed, with the printed file itself attached.

CollectionScopeWhat a record is
traceability-labelstraceability-labels:readOne label that was printed, and the file that was printed.

It shares the snapshot envelope: id, deleted, capturedAt, receivedAt, sequence and the rest sit around the data below.

traceability-labels

FieldTypeMeaning
timestampstring, requiredWhen the label was printed, epoch milliseconds as a string.
supplierstring | nullWho supplied what the label is stuck on. Free text.
partnumber | nullUndocumented. A decimal number, not an integer — read the note below before using it.
commentarystring | nullA note typed at print time. Free text.
groupIdstring | nullThe print run this label belongs to.
userIdstring | nullThe staff member who printed it, when the app kept one.
assetobject, requiredThe file that was printed. Read the next section.
{
  "id": "0c6a4f2b-9e17-4d50-8b3c-1f7d5a2e9046",
  "collection": "traceability-labels",
  "deleted": false,
  "capturedAt": "1789786412903",
  "receivedAt": "1789786500117",
  "sequence": "2048",
  "data": {
    "timestamp": "1789786380000",
    "supplier": "Metro",
    "part": 1.5,
    "commentary": "Bac 3, ouvert ce matin",
    "groupId": "5e8b1c47-2a90-4f63-b1d8-6c04e7a3f215",
    "userId": "b3f7c1a0-5d42-4e88-9a16-7c0e2d4b9f31",
    "asset": {
      "objectKey": "restaurants/36eaa3fa/labels/c58d10b7e4a9",
      "status": "uploaded",
      "contentType": "image/jpeg",
      "byteLength": 48210,
      "sha256": "3c9e0b7a41d85f2e06b93c8a7d140e5b29f6a83c1d07e4b5a9c26f80d3e17b4a"
    }
  }
}

supplier is a name, not a reference. It is text, not the id of a supplier, and nothing keeps the two in step: a supplier renamed in the catalogue does not rewrite labels printed last month. Match on it if you must, but treat a match as a guess and a miss as normal.

The file

Every label carries one: data.asset says a file exists, and the bytes come from the assets endpoint.

GET /v1/restaurants/{restaurantId}/collections/traceability-labels/records/{recordId}/assets

It answers with signed URLs valid for fifteen minutes, each carrying its own authorisation so the download needs no header. The full rules — what the response looks like, why sha256 lets you skip a download, why you store the bytes and not the link — are on the collections page. Two things are worth saying here anyway.

asset describes the file; only the endpoint hands it over. It carries objectKey, status, contentType, byteLength and sha256, but no URL — a link that never expired would be a permanent unauthenticated way into a restaurant's records. Branch on status: uploaded means the bytes landed and were verified, pending means a device is still sending them, and a pending asset is deliberately absent from the assets endpoint rather than broken.

A printed label is not necessarily an image. Read the contentType the assets endpoint gives you rather than assuming a photograph, and do not name everything .jpg on the way into your own store.

Labels printed together

groupId is the field that turns a stream of labels back into something a person would recognise. When staff print a batch — several labels for several containers of the same preparation, in one go — every label of that run carries the same groupId. Group on it before you display anything: one run is one event in a timeline, not eight.

part is the field we cannot yet tell you the meaning of, and we would rather say so than have you guess wrong. It is a decimal number, not a counter, which rules out the obvious reading of "label 3 of 8" and suggests a portion or a quantity — but nothing in the schema states it, so we are not going to pretend. Carry it through untouched, show it raw if you must, and ask us if your integration depends on it: the answer is one conversation with the people who built the label screen.

Both are nullable. A label printed on its own can arrive with neither, and that is a single-label run rather than a broken record: fall back to the envelope id and show it alone.

Last updated 2026-09-20.