Files API
Übersicht
Die Files-API hostet Dateien bei qr3 und liefert dafür eine stabile URL. Der QR-Code zeigt auf diese URL — die Datei dahinter kannst du jederzeit austauschen, ohne den Code neu zu drucken.
Basis-URL: https://qr3.app/v1/files
Optional koppelst du eine Datei über code_id an einen Code. Das ist die Grundlage für die Landingpage pro Code, die alle öffentlichen Dateien eines Codes auflistet.
Unterstützte Typen werden per Magic-Byte geprüft, nicht am Dateinamen: PDF, PNG, JPEG, WebP, MP4, glTF/GLB, JSON. Eine .pdf, die keine PDF ist, wird abgelehnt.
Rollen
| Operation | Erforderlich | Bekommt 403 |
|---|---|---|
Alle GET | jede Rolle | — |
POST /upload, PUT /:id | Schreibrolle | viewer |
DELETE /:id | Löschrolle | viewer, contributor |
Die Sonderregel ist contributor: Die Rolle darf anlegen und ändern, aber nichts entfernen.
Datei hochladen
POST /v1/files/upload
Erwartet multipart/form-data.
| Feld | Pflicht | Beschreibung |
|---|---|---|
file | Ja | Die Datei |
code_id | Nein | An einen Code koppeln (muss zum Workspace gehören) |
visibility | Nein | private (Default) oder 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 ist nur bei visibility: "public" und status: "active" gesetzt. Die Adresse braucht keine Anmeldung und eignet sich direkt als Ziel-URL eines QR-Codes.
Dateien auflisten
GET /v1/files
Query: code_id und visibility, beide optional. Liefert die aktiven Dateien des Workspace, neueste zuerst.
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 }}Datei-Info abrufen
GET /v1/files/:id
Liefert die Metadaten inklusive download_url (und public_url bei öffentlichen Dateien). Für alle Rollen lesbar.
Datei herunterladen
GET /v1/files/:id/download
Streamt den Inhalt als Content-Disposition: attachment mit Cache-Control: private, no-store — die Antwort ist also immer der aktuelle Stand, anders als die zwischengespeicherte öffentliche /f/:id-URL.
404 kommt auf zwei Wegen: Die Datei existiert nicht im Workspace (oder ist gelöscht), oder sie existiert, aber das gespeicherte Objekt fehlt.
Datei ersetzen
PUT /v1/files/:id
Tauscht den Inhalt aus und behält die id — und damit die öffentliche /f/:id- und die download_url-Adresse. Ein bereits gedruckter QR-Code bleibt gültig.
curl -X PUT https://qr3.app/v1/files/file_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..." \visibility, code_id und created_at bleiben erhalten; filename, mime_type, size_bytes und hash_sha256 werden aktualisiert. Das Plan-Limit je Datei gilt wie beim Upload, das Workspace-Speicherlimit wird gegen die Differenz geprüft. Die Grenze „Dateien je Code” gilt nicht, es kommt ja keine Datei hinzu.
Datei löschen
DELETE /v1/files/:id
Soft-Delete: Die Datei verschwindet sofort aus der Liste, ist nicht mehr abrufbar und wird — falls öffentlich — nicht mehr unter /f/:id ausgeliefert.
Response (HTTP 200):
{ "data": { "id": "file_a1b2c3d4", "deleted": true }, "meta": { "request_id": "req_abc123" }}Limits
| Plan | Max. je Datei |
|---|---|
| Free | 5 MB |
| Pro | 25 MB |
| Business | 100 MB |
| Agency | 100 MB |
| Enterprise | 250 MB |
Zusätzlich gelten je Plan eine maximale Anzahl Dateien je Code und ein Gesamt-Speicher je Workspace. Das Upload-Ratelimit liegt bei 100 Uploads pro Stunde und Workspace.
Fehler
| Status | Wann |
|---|---|
| 400 | Unbekannte oder nicht passende Dateisignatur, ungültiger multipart-Body |
| 401 | Kein oder ungültiger API-Key |
| 403 | Rolle darf nicht schreiben bzw. nicht löschen |
| 404 | code_id oder Datei nicht im Workspace; beim Download auch: Objekt fehlt im Speicher |
| 413 | Datei größer als das Plan-Limit |
| 422 | Datei fehlt, ungültige visibility, Grenze „Dateien je Code” erreicht, Workspace-Speicherlimit überschritten |
| 429 | Upload-Ratelimit (100/Stunde/Workspace) oder allgemeines Rate-Limit |
Verwandt
- Dateien & Datenblätter — der Weg über das Dashboard
- Landingpage pro Code