How to build QR check-in without becoming an archive of passports
Every self check-in system collects identity documents. Very few of them have a plan for deleting those documents, which is the part that turns a convenience feature into a liability.
The easy half
Self check-in is straightforward to describe. Before arrival the guest gets a link. They open it on their phone, fill in the details the law requires, photograph their ID, sign, and pay whatever is outstanding. On arrival there is nothing left to do at the desk.
The mechanics are equally straightforward. A per-booking token addresses the session — no account, no password, because asking a guest to register an account before they can check in defeats the point. The link stays valid for a short window after the stay ends, so a guest can still fetch their receipt, and then it stops working.
A link is a credential, so treat it as one
An unguessable URL is the only thing standing between a stranger and a booking's guest list, and that has consequences for design.
Rate limiting is the first. Document scanning and field suggestions are the expensive operations, and they are also the ones worth abusing, so both are throttled per guest per hour — in Boris, twelve document scans and an hour-long throttle window. The point is not to inconvenience a guest who genuinely retakes a blurry photo three times; it is to make bulk automated use of a leaked link pointless.
The second consequence is that tokens must be revocable in bulk. If links are ever exposed, there has to be a way to invalidate every one already handed out, and it needs to be a deliberate, auditable operation rather than an undocumented database update.
The hard half: deleting the documents
Here is the part most implementations skip. You collect a photograph of somebody's passport because the law requires you to file their stay. Once you have filed it, the legal basis for holding the image is gone. Keeping it "just in case" is not caution — it is an unlawful retention, and it converts a routine feature into the single most damaging thing in your database if it is ever breached.
So deletion cannot be a setting. In Boris the reconciliation job destroys document photographs the moment the stay is filed with the authority, and at 23:59 on the arrival day regardless of whether filing succeeded. It removes them from disk and from the database. There is no toggle to soften it, because a toggle would be a request to accumulate passports.
Two details matter in the implementation. Deletion has to cover both the file and the row — an orphaned row with a path is still a record that a document existed, and an orphaned file is worse. And a refused or failed request must never trigger destruction: the guest who uploads a photo the system rejects should be able to try again, so only a completed path deletes.

Extraction is a convenience, not a source of truth
Reading the document with OCR to pre-fill name, date of birth, document number and nationality removes most of the typing, and typing on a phone is where guests give up. But extracted values are suggestions. They have to be presented as editable fields the guest confirms, because an OCR misread that silently becomes a legal filing is a worse outcome than a guest typing their own surname.
What the desk still has to handle
Self check-in never reaches one hundred per cent, and a system that assumes it does will strand people. Guests arrive without having opened the link. Payments fail. A door provider is down at the wrong moment. Each of those needs a path that a member of staff can complete manually, and each of those manual completions still has to produce the same filing, the same tax record and the same execution trail as the automatic path — otherwise the compliance gap is simply moved rather than closed.
The jobs are not optional
An online check-in flow is not self-contained. The invitation is queued rather than sent inline, so without a job draining that queue the links are never delivered and nothing reports an error — the rows simply accumulate. Payments whose webhook was missed need settling. Cash-paid tourist tax needs completing when a provider was unavailable. And the documents need destroying.
If you take one thing from this: the failure mode of a check-in system is silence. Nothing crashes. Links just do not arrive, and photographs just do not get deleted, and both of those look exactly like a system working normally.
