Deliveries

Goods-in checks and the photographs taken at reception: two collections, every field, and what they mean on the shop floor.

A delivery is one goods-in check: a member of staff receiving an order, recording temperatures, and deciding whether to accept it. It is the record a food-safety inspector asks for. The pictures taken at reception are a second collection beside it.

CollectionScopeWhat a record is
deliveriesdeliveries:readOne goods-in check, with a temperature reading per product.
delivery-picturesdelivery-pictures:readOne photograph taken during a delivery, pointing back at it.

Both are ordinary collections: the same snapshot envelope around data, the same endpoints, the same cursor, the same 90-day rule. They carry the delivery history the app still held when they opened, not only what was recorded since.

deliveries

FieldTypeMeaning
timestampstring, requiredWhen the check happened, epoch milliseconds as a string.
isCompliantboolean, requiredThe staff member's verdict on the delivery as a whole.
supplierDeliveriesIdstring | nullThe supplier the goods came from: the id of a suppliers record.
temperatureRecordsarray | nullOne entry per product measured. See below.
nonComplianceReasonsstring[] | nullWhy the delivery was refused or accepted with reservation. Free text chosen by the staff member; empty when compliant.
correctiveActionsstring[] | nullWhat was done about it. Empty when nothing was needed.
commentarystring | nullFree-text note. Often null.
userIdstring | nullThe staff member who received it, when the app recorded one.

temperatureRecords[]

FieldTypeMeaning
productstringWhat was measured, as the staff member named it. Never empty.
lotNumberstring | nullThe batch or lot, when it was captured.
valuenumber | nullThe reading. null when the product was logged without a measurement.
unit"C"Always Celsius. See below.

Temperatures are always Celsius. A restaurant whose app records in Fahrenheit still sends Fahrenheit readings, and they are converted when they arrive, before they are stored. unit is "C" on every entry, so a consumer never has to convert or guess.

{
  "id": "8f2c1b04-0d5a-4b7e-9f31-6ad2c0e77a51",
  "collection": "deliveries",
  "deleted": false,
  "capturedAt": "1787932805120",
  "receivedAt": "1787932911004",
  "sequence": "88",
  "data": {
    "timestamp": "1787932800000",
    "isCompliant": false,
    "supplierDeliveriesId": "supplier-7",
    "temperatureRecords": [
      { "product": "Poulet fermier", "lotNumber": "L2291", "value": 6.4, "unit": "C" },
      { "product": "Farine T55", "lotNumber": null, "value": null, "unit": "C" }
    ],
    "nonComplianceReasons": ["Température trop élevée"],
    "correctiveActions": ["Produit refusé", "Fournisseur prévenu"],
    "commentary": "Camion en retard, rupture de chaîne du froid probable",
    "userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
  }
}

delivery-pictures

A label, a damaged pallet, a probe against a display: the pictures are the evidence behind isCompliant. Each one is a record that points at its delivery, and it carries a file, so the bytes come from the assets endpoint.

FieldTypeMeaning
timestampstring, requiredWhen the picture was taken, epoch milliseconds as a string.
deliveryIdstring | nullThe deliveries record it belongs to.
partnumber | nullPosition of this record inside a picture the app stored in several parts. Carry it through rather than interpreting it.
groupIdstring | nullTies those parts together. Records sharing a groupId are the same picture.
assetobject, requiredNames the file: objectKey and status always, plus contentType, byteLength and sha256 once it is uploaded.
{
  "id": "c61e0a7d-35b2-4f89-a1d4-7e90b2c45f18",
  "collection": "delivery-pictures",
  "deleted": false,
  "capturedAt": "1787932861240",
  "receivedAt": "1787932990517",
  "sequence": "143",
  "data": {
    "timestamp": "1787932860000",
    "deliveryId": "8f2c1b04-0d5a-4b7e-9f31-6ad2c0e77a51",
    "part": 4,
    "groupId": "b4d81f0a-c2e7-4a55-9d10-6f3e8a2b7c91",
    "asset": {
      "objectKey": "delivery-pictures/b4d81f0a/4.jpg",
      "status": "uploaded",
      "contentType": "image/jpeg",
      "byteLength": 902450,
      "sha256": "9f2a…"
    }
  }
}

The bytes are a second call, against the record's own id:

GET /v1/restaurants/{restaurantId}/collections/delivery-pictures/records/{recordId}/assets

It answers with signed URLs valid for fifteen minutes, exactly as described on the collections page. Ask on any part of a picture and you get the same file: the API resolves the group for you, so there is no need to work out which part holds it.

To show the photographs of one delivery, walk delivery-pictures and keep the records whose deliveryId is that delivery's id, one per groupId.

Reading it correctly

isCompliant is the record, not a computation. It is what the person receiving the delivery decided, and it can disagree with what you would conclude from the temperatures alone: a reading taken on a surface probe, a product with its own threshold, a judgement call. Present it as their verdict. If you want your own, compute it beside theirs and label it as yours.

Free-text fields are free text. nonComplianceReasons, correctiveActions and product are typed by staff during service, in the language of the restaurant, with the spelling of a busy Tuesday. Do not build an enum from them, do not key a join on them, and do not assume French.

value can be null. A product logged without a reading is normal. It is often a dry good. Treat null as "not measured", never as 0.

Timestamps are strings. timestamp is a decimal string of epoch milliseconds, because the whole BackResto platform stores timestamps that way. Number(timestamp) is safe today and for the next few hundred thousand years, but do not let a JSON parser coerce it silently and then write it back with precision lost.

A picture can arrive after its delivery. A phone uploads photographs when it can, sometimes minutes after the check itself. A delivery with no picture yet may simply have one still on its way; walk again later before concluding it has none.

Last updated 2026-09-29.