Documents
The restaurant's own document store — certificates, procedures, reports — each record a filed file with its own media type.
Every restaurant keeps paper beside the checks: supplier certificates, cleaning procedures, the last inspection report, a signed plan. The app gives them a place to file it, and this collection is that filing cabinet — one record per document, each one pointing at the file itself.
| Collection | Scope | What a record is |
|---|---|---|
drive-files | drive-files:read | One document filed in the restaurant's document store. |
It shares the snapshot envelope: id, deleted,
capturedAt, receivedAt, sequence and the rest sit around the data
below.
drive-files
| Field | Type | Meaning |
|---|---|---|
s3Key | string, required | Where the document sits in the store. A key, not a URL. Up to 1024 characters. |
name | string, required | The file name as the restaurant sees it. |
sizeBytes | number, required | Size of the document in bytes. |
contentType | string | null | The media type the app recorded. Can be missing. |
asset | object | The file. Read the next section. |
{
"id": "a94c7e51-3f60-4b2d-8e17-05c9d3a6f482",
"collection": "drive-files",
"deleted": false,
"capturedAt": "1789743015220",
"receivedAt": "1789743098644",
"sequence": "97",
"data": {
"s3Key": "drive/fournisseurs/attestation-metro-2026.pdf",
"name": "Attestation Metro 2026.pdf",
"sizeBytes": 184320,
"contentType": "application/pdf",
"asset": {
"objectKey": "restaurants/36eaa3fa/drive/a17c93be4f02",
"status": "uploaded",
"contentType": "application/pdf",
"byteLength": 184320,
"sha256": "9f2a7c41e8b0d5364a1f8e29b7c30d5e6f14a8b29c7d0e3f5a6b1c8d9e0f2a3b"
}
}
}
There is no timestamp in data. When the document was filed is capturedAt
on the envelope, like every other collection.
The file is the point
Elsewhere the record is the information and the file is evidence. Here it is the other way round: five fields describe a document whose content is the whole reason anyone reads this collection. So you will almost always follow the record to the bytes.
GET /v1/restaurants/{restaurantId}/collections/drive-files/records/{recordId}/assets
Signed URLs valid for fifteen minutes, each carrying its own authorisation. The collections page has the rules, and two of them matter more here than anywhere else:
sha256lets you skip a download. It is the digest of the bytes. A certificate that has not changed since your last walk does not need fetching again, and documents are the largest things this API will hand you.- Fetch now, store the bytes, never the link. Fifteen minutes is long enough to download and short enough that a URL in your database is a dead link by morning.
asset describes the file; only the endpoint hands it over. It carries
objectKey, status, contentType, byteLength and sha256 — enough to
decide whether you want the bytes, and no URL, because a URL that never expired
would be a permanent unauthenticated link to a restaurant's paperwork.
status is the field to branch on. It is uploaded once the bytes have landed
and been verified, and pending while a device is still sending them. A
pending asset is absent from the assets endpoint, which is correct rather than
broken: ask again later instead of treating it as a missing document. asset is
also the one field here that can be absent altogether — a record filed with no
file yet.
These are not pictures
A cleaning proof is a photograph. A document is whatever the restaurant filed: a PDF certificate, an Excel or CSV temperature export, a Word procedure, a scan someone took with their phone. All of them turn up here.
Read contentType rather than assuming one. It is nullable in the record —
the app does not always have it — so when it is null, take the contentType
from the asset instead; that one is the media type of the object that is
actually stored, and it is the one to trust when the two disagree. A client
that renders everything as an image, or saves everything as .pdf, breaks on
the first spreadsheet.
Do not derive the type from name or s3Key either. An extension is a
convention, not a guarantee, and both fields are free text from a person
naming a file on a tablet.
Filing them on your side
s3Key is a key, not an address. It identifies the object in the store —
it has no scheme, no host and no leading slash, and you cannot fetch it. Every
byte you get comes from the assets endpoint.
Key on the envelope id, not on name. Nothing stops two documents being
called Attestation 2026.pdf, in the same restaurant, filed a year apart.
sizeBytes is worth reading before you download. It is the cheapest way to
decide whether to pull a 40 MB scan on a mobile connection. The stored object's
own byteLength, on the asset, is the authoritative one.
A tombstone takes the file with it. deleted: true means the document was
removed in the app, and its assets stop being listed — if you needed that
certificate, you needed the bytes. See
the envelope page for how tombstones behave.