For AI assistants and scripts
Put the paperwork in the archive without touching a browser.
A QRchive sticker turns a physical thing into a permanent document archive. Scan the sticker, and the manuals, photos, reports and records that belong to that thing are there — for whoever is standing in front of it next.
Filling an archive after a job is the tedious part, and it is the part an agent is good at. This page is how yours does it. Everything below works today, with no sign-in and no keys: an agent that has the sticker’s address has everything it needs.
$49 CAD per archive, one time. No subscription. Unlocking an archive is always done by a person in a browser. Nothing here can spend your money.
Start from the sticker’s address
Every sticker carries a public address:
https://qrchive.ca/docs/QR-123456-AB7CD
└──┬───┘ └─┬─┘
code tokenThose two values are all the calls below need. The token’s alphabet leaves out 0, O, 1, I and L, so it survives being read off a printed sticker.
What your agent can and cannot do
On an archive that has been unlocked and still accepts additions from anyone, an agent with no credentials can add files, list the sections inside, and check whether the archive is unlocked yet.
It cannot sign in as the owner, edit the archive’s written details, create sections, or pay for anything. Those need the owner’s browser session. Scoped keys for machines are something we may build; nothing here promises we will.
Adding a file
Three calls. The middle one goes straight to storage, not to us.
1. POST https://qrchive.ca/api/upload/request
{ "qrCodeId": "QR-123456",
"fileName": "as-built.pdf",
"fileSize": 482118,
"fileType": "application/pdf" }
→ { "success": true,
"uploadUrl": "https://…", ← good for 15 minutes
"objectKey": "…",
"expiresAt": "…" }
2. PUT the raw bytes to uploadUrl
Content-Type: application/pdf
(no QRchive headers — the URL carries its own signature)
3. POST https://qrchive.ca/api/upload/confirm
{ "r2ObjectKey": "<objectKey from step 1>",
"qrCodeId": "QR-123456",
"fileName": "as-built.pdf",
"fileSize": 482118,
"fileType": "application/pdf" }
→ { "success": true, "fileId": "…" }Step 3 is not optional. Without it the bytes sit in storage and never join the archive.
Or just send an email
Every archive has its own address, built from the same two values:
qr-123456-ab7cd@in.qrchive.caAnything that can send mail can file documents. Attachments go through the same checks as an upload. Ten messages per hour per archive.
The published endpoints
Four, and only four. Each one is a promise we intend to keep, which is why the list is short.
| Endpoint | What it does | Who may call it |
|---|---|---|
| POST /api/upload/request | Ask for a short-lived URL to send one file to storage. | None, for an unlocked archive that accepts additions from anyone. |
| POST /api/upload/confirm | Tell QRchive the file finished sending, so it joins the archive. | None, same rule as the request step. |
| GET /api/public/folders | List the sections inside an unlocked archive. | None; needs the code and its 5-character token. |
| GET /api/qr/{qrCodeId}/status | Check whether an archive has been unlocked yet. | None; needs the code and its 5-character token. |
Machine-readable description: /api/openapi.json (OpenAPI 3.1). Short summary for models: /llms.txt.
Limits
- Accepted types:
pdf jpg jpeg png heic heif webp xlsx docx csv mov mp4 - 50 MB per file; 500 MB for video.
- Contents are checked against the type the name claims. A mismatch is rejected and the bytes are deleted.
- Files count against the archive’s storage allowance (1 GB is included).
- 500 upload requests per hour per address; 10 emails per hour per archive.
- A private archive, or one whose owner has turned additions off, refuses anonymous uploads.
Errors
Every documented endpoint fails the same shape:
{
"success": false,
"error": { "message": "Storage limit reached (1024 MB)…",
"code": "STORAGE_FULL" },
"code": "STORAGE_FULL"
}Worth branching on: INVALID_FILE_TYPE, FILE_TOO_LARGE, MAGIC_BYTE_MISMATCH, STORAGE_FULL, NOT_ACTIVATED, RATE_LIMIT_EXCEEDED. The first three will never succeed on a retry of the same file. The last one will, after the Retry-After seconds.
What QRchive does not do
QRchive runs no AI. It does not read, sort, summarise, or answer questions about what it holds. It keeps your documents and hands them back when the sticker is scanned. Bring your own agent — that is the whole idea.
Questions
support@qrchive.ca. If you are building something against these endpoints, tell us — what gets used is what gets kept.