Files API
Overzicht
De Files-API host bestanden bij qr3 en levert hiervoor een stabiele URL. De QR-code verwijst naar deze URL — het bestand daarachter kun je op elk moment vervangen zonder de code opnieuw te hoeven afdrukken.
Basis-URL: https://qr3.app/v1/files
Optioneel koppel je een bestand via code_id aan een code. Dit is de basis voor de landingspagina per code, die alle openbare bestanden van een code toont.
Ondersteunde typen worden gecontroleerd via magic bytes, niet op basis van de bestandsnaam: PDF, PNG, JPEG, WebP, MP4, glTF/GLB, JSON. Een .pdf die geen PDF is, wordt geweigerd.
Rollen
| Operatie | Vereist | Krijgt 403 |
|---|---|---|
Alle GET | elke rol | — |
POST /upload, PUT /:id | schrijfrol | viewer |
DELETE /:id | verwijderrol | viewer, contributor |
De uitzondering is contributor: deze rol mag aanmaken en wijzigen, maar niets verwijderen.
Bestand uploaden
POST /v1/files/upload
Verwacht multipart/form-data.
| Veld | Verplicht | Beschrijving |
|---|---|---|
file | Ja | Het bestand |
code_id | Nee | Koppelen aan een code (moet bij de Workspace horen) |
visibility | Nee | private (standaard) of public |
curl -X POST https://qr3.app/v1/files/upload \ -H "Authorization: Bearer qr3_sk_..." \ -F "code_id=qr_a1b2c3d4" \ -F "visibility=public"const form = new FormData();form.append('file', fileInput.files[0]);form.append('code_id', 'qr_a1b2c3d4');form.append('visibility', 'public');
const res = await fetch('https://qr3.app/v1/files/upload', { method: 'POST', headers: { Authorization: 'Bearer qr3_sk_...' }, body: form, // Content-Type NICHT selbst setzen — der Boundary fehlt sonst});Response (HTTP 201):
{ "data": { "id": "file_a1b2c3d4", "code_id": "qr_a1b2c3d4", "filename": "datenblatt.pdf", "mime_type": "application/pdf", "size_bytes": 284913, "hash_sha256": "9f86d081884c7d65…", "visibility": "public", "status": "active", "created_at": "2026-03-14T12:00:00.000Z", "download_url": "https://qr3.app/v1/files/file_a1b2c3d4/download", "public_url": "https://qr3.app/f/file_a1b2c3d4" }, "meta": { "request_id": "req_abc123" }}public_url is alleen ingesteld bij visibility: "public" en status: "active". Het adres vereist geen login en is direct geschikt als doel-URL van een QR-code.
Bestanden oplijsten
GET /v1/files
Query: code_id en visibility, beide optioneel. Retourneert de actieve bestanden van de Workspace, de nieuwste eerst.
curl "https://qr3.app/v1/files?code_id=qr_a1b2c3d4" \ -H "Authorization: Bearer qr3_sk_..."Response (HTTP 200):
{ "data": [ { "id": "file_a1b2c3d4", "…": "…" } ], "meta": { "request_id": "req_abc123", "file_count": 3, "total_size_bytes": 812004 }}Bestandsinformatie ophalen
GET /v1/files/:id
Retourneert de metadata inclusief download_url (en public_url bij openbare bestanden). Leesbaar voor alle rollen.
Bestand downloaden
GET /v1/files/:id/download
Streamt de inhoud als Content-Disposition: attachment met Cache-Control: private, no-store — de reactie is dus altijd de actuele status, in tegenstelling tot de gecachte openbare /f/:id-URL.
404 kan op twee manieren optreden: het bestand bestaat niet in de Workspace (of is verwijderd), of het bestaat wel, maar het opgeslagen object ontbreekt.
Bestand vervangen
PUT /v1/files/:id
Vervangt de inhoud en behoudt de id — en daarmee het openbare /f/:id- en het download_url-adres. Een reeds gedrukte QR-code blijft geldig.
curl -X PUT https://qr3.app/v1/files/file_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..." \visibility, code_id en created_at blijven behouden; filename, mime_type, size_bytes en hash_sha256 worden bijgewerkt. De abonnementslimiet per bestand geldt net als bij de upload, de Workspace-opslaglimiet wordt getoetst aan het verschil. De limiet “bestanden per code” geldt niet, er wordt immers geen bestand toegevoegd.
Bestand verwijderen
DELETE /v1/files/:id
Soft-delete: Het bestand verdwijnt direct uit de lijst, is niet meer opvraagbaar en wordt — indien openbaar — niet meer via /f/:id geleverd.
Response (HTTP 200):
{ "data": { "id": "file_a1b2c3d4", "deleted": true }, "meta": { "request_id": "req_abc123" }}Limieten
| Abonnement | Max. per bestand |
|---|---|
| Free | 5 MB |
| Pro | 25 MB |
| Business | 100 MB |
| Agency | 100 MB |
| Enterprise | 250 MB |
Daarnaast geldt er per abonnement een maximaal aantal bestanden per code en een totale opslagruimte per Workspace. De upload-ratelimit ligt op 100 uploads per uur per Workspace.
Fouten
| Status | Wanneer |
|---|---|
| 400 | Onbekende of niet-overeenkomende bestandssignatuur, ongeldige multipart-body |
| 401 | Geen of ongeldige API-key |
| 403 | Rol mag niet schrijven of niet verwijderen |
| 404 | code_id of bestand niet in de Workspace; bij download ook: object ontbreekt in opslag |
| 413 | Bestand groter dan de abonnementslimiet |
| 422 | Bestand ontbreekt, ongeldige visibility, limiet “bestanden per code” bereikt, Workspace-opslaglimiet overschreden |
| 429 | Upload-ratelimit (100/uur/Workspace) of algemene rate-limit |
Gerelateerd
- Bestanden & datasheets — de route via het dashboard
- Landingspagina per code