> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squadvault.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Dokument hochladen

> Dreistufiger Ablauf, um eine private Datei zu S3 hochzuladen und über die Public API einen Dokumenteneintrag zu erstellen.

Dokument-Uploads laufen in drei Schritten: presigned URL anfordern, Datei in den privaten Speicher hochladen, anschließend den Dokumenteneintrag erstellen. Objekte unter `documents/` sind **nicht** öffentlich lesbar — Vorschau und Download laufen immer über signierte SquadVault-URLs.

## Ablauf

```mermaid theme={null}
sequenceDiagram
  participant Client
  participant API as SquadVault_API
  participant S3 as Object_storage
  Client->>API: POST /v1/uploads/document-file
  API-->>Client: key, fileRef, uploadUrl
  Client->>S3: PUT file to uploadUrl
  Client->>API: POST /v1/documents with fileKey and fileUrl
  API-->>Client: Document
```

### 1. Presigned Upload-URL anfordern

```bash theme={null}
curl -X POST "https://api.squadvault.xyz/v1/uploads/document-file" \
  -H "x-api-key: sv_org_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "organizationId": "YOUR_ORG_ID",
  "contentType": "application/pdf",
  "sizeBytes": 102400
}'
```

Antwort:

```json theme={null}
{
  "key": "documents/YOUR_ORG_ID/uuid.pdf",
  "fileRef": "s3://your-bucket/documents/YOUR_ORG_ID/uuid.pdf",
  "uploadUrl": "https://...presigned..."
}
```

Felder beim Erstellen zuordnen: `fileKey` ← `key`, `fileUrl` ← `fileRef`. Die API überschreibt `fileUrl` mit einer privaten Storage-Referenz.

`sizeBytes` muss exakt der Byte-Länge der Datei aus Schritt 2 entsprechen.

### 2. Datei hochladen

```bash theme={null}
curl -X PUT "<uploadUrl>" \
  -H "Content-Type: application/pdf" \
  --data-binary @playbook.pdf
```

Verwende denselben `Content-Type` und dieselbe Größe wie in Schritt 1.

### 3. Dokumenteneintrag erstellen

```bash theme={null}
curl -X POST "https://api.squadvault.xyz/v1/documents" \
  -H "x-api-key: sv_org_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "organizationId": "YOUR_ORG_ID",
  "name": "Playbook Q3",
  "fileUrl": "<fileRef>",
  "fileKey": "<key>",
  "contentType": "application/pdf",
  "sizeBytes": 102400,
  "tags": ["playbook"]
}'
```

Für Download oder Vorschau später `GET /documents/{documentId}/download` bzw. `/preview` nutzen — `fileUrl` ist kein öffentlicher HTTP-Link.

## Erlaubte Content-Types

* `application/pdf`
* `application/msword`
* `application/vnd.openxmlformats-officedocument.wordprocessingml.document`
* `application/vnd.ms-excel`
* `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
* `text/plain`
* `image/jpeg`, `image/png`, `image/webp`, `image/gif`

Die maximale Dateigröße hängt vom Organisationsplan ab (serverseitig geprüft).

## JavaScript-Beispiel

```javascript theme={null}
const sizeBytes = fileBuffer.byteLength;

const uploadResponse = await fetch(
  "https://api.squadvault.xyz/v1/uploads/document-file",
  {
    method: "POST",
    headers: {
      "x-api-key": process.env.SQUADVAULT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      organizationId: "YOUR_ORG_ID",
      contentType: "application/pdf",
      sizeBytes,
    }),
  },
);

const { key, fileRef, uploadUrl } = await uploadResponse.json();

await fetch(uploadUrl, {
  method: "PUT",
  headers: { "Content-Type": "application/pdf" },
  body: fileBuffer,
});

const documentResponse = await fetch(
  "https://api.squadvault.xyz/v1/documents",
  {
    method: "POST",
    headers: {
      "x-api-key": process.env.SQUADVAULT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      organizationId: "YOUR_ORG_ID",
      name: "Playbook Q3",
      fileUrl: fileRef,
      fileKey: key,
      contentType: "application/pdf",
      sizeBytes,
      tags: ["playbook"],
    }),
  },
);

const document = await documentResponse.json();
```

Benötigte Berechtigung für Upload-URL und Dokument-Create: `document:create`.
