# Documents

> The restaurant's own document store (certificates, procedures, reports), each record a filed file with its own media type.

Source: https://developers.backresto.com/en/docs/drive-files

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](https://developers.backresto.com/en/docs/collections): `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. |

```json
{
  "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": "9f2a…"
    }
  }
}
```

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.

```http
GET /v1/restaurants/{restaurantId}/collections/drive-files/records/{recordId}/assets
```

Signed URLs valid for **fifteen minutes**, each carrying its own authorisation.
[The collections page](https://developers.backresto.com/en/docs/collections) has the rules, and two of them
matter more here than anywhere else:

- **`sha256` lets 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](https://developers.backresto.com/en/docs/collections) for how tombstones behave.
