BiomPIN
A BiomPIN is a code such as lunar-rocket-731904 that opens an encrypted copy of a result. Share it with a colleague, use it with the ESCRS calculator, or keep it in browser History to reopen the result later.
Create and open a share
Section titled “Create and open a share”The web app requests a BiomPIN automatically for single reports. For datasets, Add to history controls whether shares are created. The CLI also creates shares by default; use --no-pin to turn this off.
The REST API leaves sharing off unless you request it:
curl --fail-with-body https://biomapi.com/api/v1/biom/process \ -F "file=@report.pdf" \ -F "biompin=true" \ -o result.jsonRead the code from biompin.pin. If storage is unavailable, processing can still succeed with biompin: null.
A full code opens at https://biomapi.com/pin/lunar-rocket-731904. For API retrieval:
curl --fail-with-body \ 'https://biomapi.com/api/v1/biom/retrieve?biom_pin=lunar-rocket-731904' \ -o retrieved.jsonThe code above is an example. Replace it with a code returned by your own request. The Browser SDK provides public retrieval and sharing helpers.
What is shared
Section titled “What is shared”Before storage, BiomAPI removes data.patient.name and data.patient.id. The original processing response still contains them. Other fields, including date of birth, examination date, measurements, and any notes, remain in the encrypted result.
Removing initials and ID is not complete anonymization. Check the remaining fields before sharing, particularly free-text notes. Anyone with the complete PIN can retrieve the result while it remains available.
Browser-local identity context
Section titled “Browser-local identity context”The web app can restore initials and ID from its local History. A link may also include them separately in a URL fragment:
https://biomapi.com/pin/lunar-rocket-731904#biomctx=<base64url-json>Ordinary HTTP requests do not include the fragment. Page scripts and anyone receiving the complete link can decode it. Treat the complete URL as patient-identifying data.
The web app selects available identity by default. Choose Anonymous beside the BiomPIN heading to omit this fragment from copied links and QR codes. This does not remove other fields from the stored report.
For integrators, version 1 encodes this shape as UTF-8 JSON in base64url:
{ "v": 1, "patient_name": "SD", "patient_id": "SYN-001"}Use the SDK’s identity helpers to create and consume context. Keep identifiers out of query parameters, retrieval requests, and analytics.
Wrong PINs and expiry
Section titled “Wrong PINs and expiry”The default lifetime is 31 days. Use the returned expires_at value for the actual deadline. You cannot retrieve an expired share. New shares trigger storage cleanup, and retrieval also checks expiry.
Three wrong numeric PIN attempts against an existing share permanently delete it by default. The threshold request returns 429; subsequent requests return 404. A correct retrieval does not extend the share’s lifetime.
Download JSON for records you need to retain. Browser History holds a shortcut and local context, not a permanent copy of the measurements. Clearing History does not delete the server record.
Encryption and its limits
Section titled “Encryption and its limits”A code has two parts: the word pair identifies the stored record, and the six digits are used to derive its encryption key. BiomAPI does not persist the numeric PIN in BiomPIN storage.
| Component | Implementation |
|---|---|
| Key derivation | Argon2id, with 3 iterations, 32 MiB memory, and parallelism 1 |
| Salt | First 16 bytes of the SHA-256 hash of the share ID |
| Encryption | AES-256-GCM with a random 12-byte nonce |
| Online guessing protection | Record deletion at the configured failed-attempt threshold |
The service sees unencrypted data while processing and decrypting a request. Stored data is encrypted. Anyone with a database copy can still try to guess PINs offline.
Argon2 makes each guess more expensive. Online limits and deletion cannot protect a copy already taken from storage.
Retrieval responses use Cache-Control: no-store. Integrations should not put them in shared or persistent response caches. The db_id identifies the storage instance and helps integrations discard History entries from a replaced database.
See the Privacy policy for processing destinations, browser storage, and retention.
