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.
| Collection | Scope | What a record is |
|---|---|---|
deliveries | deliveries:read | One goods-in check, with a temperature reading per product. |
delivery-pictures | delivery-pictures:read | One 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
| Field | Type | Meaning |
|---|---|---|
timestamp | string, required | When the check happened, epoch milliseconds as a string. |
isCompliant | boolean, required | The staff member's verdict on the delivery as a whole. |
supplierDeliveriesId | string | null | The supplier the goods came from: the id of a suppliers record. |
temperatureRecords | array | null | One entry per product measured. See below. |
nonComplianceReasons | string[] | null | Why the delivery was refused or accepted with reservation. Free text chosen by the staff member; empty when compliant. |
correctiveActions | string[] | null | What was done about it. Empty when nothing was needed. |
commentary | string | null | Free-text note. Often null. |
userId | string | null | The staff member who received it, when the app recorded one. |
temperatureRecords[]
| Field | Type | Meaning |
|---|---|---|
product | string | What was measured, as the staff member named it. Never empty. |
lotNumber | string | null | The batch or lot, when it was captured. |
value | number | null | The 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.
| Field | Type | Meaning |
|---|---|---|
timestamp | string, required | When the picture was taken, epoch milliseconds as a string. |
deliveryId | string | null | The deliveries record it belongs to. |
part | number | null | Position of this record inside a picture the app stored in several parts. Carry it through rather than interpreting it. |
groupId | string | null | Ties those parts together. Records sharing a groupId are the same picture. |
asset | object, required | Names 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.