Files
archivmail/docs/api-v1.md
T
sysops d360c9a5ba feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg)
- Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist
- Feature-Status auf In Review gesetzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 11:43:19 +01:00

253 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# archivmail REST API v1
> **Lese-API** alle Endpunkte sind read-only (`GET`). Schreiboperationen sind nicht verfügbar.
## Authentifizierung
Jede Anfrage muss einen gültigen API-Key im HTTP-Header mitschicken:
```
Authorization: Bearer <api-key>
```
API-Keys werden vom Admin im Admin-Bereich generiert und verwaltet. Ein API-Key hat eine zugewiesene Rolle (`user` oder `auditor`), die den Zugriffsumfang bestimmt.
| Rolle | Zugriff |
|-------|---------|
| `user` | Nur E-Mails aus zugewiesenen Postfächern |
| `auditor` | Alle E-Mails (postfachübergreifend) |
---
## Fehlercodes
| Code | Bedeutung |
|------|-----------|
| `200 OK` | Erfolg |
| `400 Bad Request` | Ungültige Parameter |
| `401 Unauthorized` | API-Key fehlt, ungültig oder deaktiviert |
| `403 Forbidden` | API-Key hat keine Berechtigung für diese Ressource |
| `404 Not Found` | E-Mail nicht gefunden |
| `405 Method Not Allowed` | Schreibmethode (POST, PUT, DELETE etc.) nicht erlaubt |
| `429 Too Many Requests` | Rate-Limit überschritten (Standard: 60 Anfragen/Minute) |
| `500 Internal Server Error` | Serverfehler |
---
## Endpunkte
---
### E-Mails suchen / filtern
```
GET /api/v1/mails
```
**Query-Parameter (alle optional, kombinierbar):**
| Parameter | Typ | Beschreibung | Beispiel |
|-----------|-----|-------------|---------|
| `q` | string | Volltext-Suche (Xapian QueryParser) | `q=Rechnung+2024` |
| `from` | string | Absender (exakt oder Partial-Match) | `from=alice@firma.de` |
| `to` | string | Empfänger | `to=bob@firma.de` |
| `cc` | string | CC-Empfänger | `cc=team@firma.de` |
| `contact` | string | From **oder** To **oder** CC enthält diese Adresse | `contact=kunde@example.com` |
| `subject` | string | Betreff enthält diesen Text | `subject=Angebot` |
| `date_from` | string (ISO 8601) | Mails ab diesem Datum | `date_from=2024-01-01` |
| `date_to` | string (ISO 8601) | Mails bis zu diesem Datum | `date_to=2024-12-31` |
| `has_attachments` | boolean | Nur Mails mit/ohne Anhänge | `has_attachments=true` |
| `page` | integer | Seite (Standard: 1) | `page=2` |
| `limit` | integer | Ergebnisse pro Seite (Standard: 25, max: 100) | `limit=50` |
| `sort` | string | Sortierung: `date_asc`, `date_desc` (Standard), `relevance` | `sort=date_asc` |
**Beispiel-Request:**
```
GET /api/v1/mails?contact=kunde@example.com&date_from=2024-01-01&limit=25
Authorization: Bearer am_abc123...
```
**Antwort:**
```json
{
"total": 142,
"page": 1,
"limit": 25,
"pages": 6,
"mails": [
{
"message_id": "<abc123@mailserver.firma.de>",
"from": "alice@firma.de",
"to": ["kunde@example.com"],
"cc": [],
"subject": "Angebot vom 15.03.2024",
"date": "2024-03-15T10:23:00Z",
"size": 24680,
"has_attachments": true,
"attachments": [
{
"filename": "Angebot_2024.pdf",
"mime_type": "application/pdf",
"size": 18432
}
]
}
]
}
```
---
### Einzelne E-Mail abrufen (Metadaten + Body)
```
GET /api/v1/mails/{message_id}
```
**Pfad-Parameter:**
| Parameter | Beschreibung |
|-----------|-------------|
| `message_id` | RFC-2822 Message-ID (URL-encoded) |
**Beispiel-Request:**
```
GET /api/v1/mails/%3Cabc123%40mailserver.firma.de%3E
Authorization: Bearer am_abc123...
```
**Antwort:**
```json
{
"message_id": "<abc123@mailserver.firma.de>",
"from": "alice@firma.de",
"to": ["kunde@example.com"],
"cc": [],
"subject": "Angebot vom 15.03.2024",
"date": "2024-03-15T10:23:00Z",
"size": 24680,
"body_plain": "Sehr geehrte Damen und Herren,\n\nim Anhang finden Sie...",
"body_html": "<html>...</html>",
"has_attachments": true,
"attachments": [
{
"filename": "Angebot_2024.pdf",
"mime_type": "application/pdf",
"size": 18432,
"download_url": "/api/v1/mails/%3Cabc123%40mailserver.firma.de%3E/attachments/0"
}
]
}
```
---
### Original-E-Mail als EML herunterladen
```
GET /api/v1/mails/{message_id}/raw
```
Gibt die originale, unveränderte E-Mail im RFC-2822-Format zurück.
**Antwort-Header:**
```
Content-Type: message/rfc822
Content-Disposition: attachment; filename="<message_id>.eml"
```
---
### Einzelnen Anhang herunterladen
```
GET /api/v1/mails/{message_id}/attachments/{index}
```
**Pfad-Parameter:**
| Parameter | Beschreibung |
|-----------|-------------|
| `message_id` | RFC-2822 Message-ID (URL-encoded) |
| `index` | Position des Anhangs (0-basiert, aus der Attachment-Liste) |
**Antwort-Header:**
```
Content-Type: application/pdf (je nach MIME-Type des Anhangs)
Content-Disposition: attachment; filename="Angebot_2024.pdf"
```
---
### Server-Info
```
GET /api/v1/info
```
Gibt Version und Status des Servers zurück. Nützlich zum Testen der Verbindung.
**Antwort:**
```json
{
"version": "1.0.0",
"status": "ok",
"mail_count": 142857
}
```
---
## Volltext-Suche Syntax (`q`-Parameter)
Der `q`-Parameter unterstützt Xapian QueryParser-Syntax:
| Syntax | Beispiel | Bedeutung |
|--------|---------|-----------|
| Einfacher Begriff | `Rechnung` | Enthält "Rechnung" |
| Mehrere Begriffe | `Rechnung Mahnung` | Enthält beide Begriffe (AND) |
| Phrasensuche | `"offene Rechnung"` | Exakter Ausdruck |
| OR-Verknüpfung | `Rechnung OR Angebot` | Eines von beiden |
| Ausschließen | `Rechnung NOT Storno` | Rechnung aber nicht Storno |
| Wildcard | `Rechnun*` | Beginnt mit "Rechnun" |
| Feldspezifisch | `subject:Angebot` | Nur im Betreff suchen |
| Feldspezifisch | `from:alice@firma.de` | Nur von diesem Absender |
---
## Paginierung
Alle Listen-Endpunkte sind paginiert:
```
GET /api/v1/mails?page=2&limit=50
```
Die Antwort enthält immer:
- `total` Gesamtanzahl der Treffer
- `page` aktuelle Seite
- `limit` Einträge pro Seite
- `pages` Gesamtanzahl der Seiten
Maximum: 100 Einträge pro Anfrage. Für größere Abfragen mehrere Seiten iterieren.
---
## Rate Limiting
Standard: **60 Anfragen pro Minute** pro API-Key (konfigurierbar durch Admin).
Bei Überschreitung:
```
HTTP 429 Too Many Requests
Retry-After: 30
```
---
## Changelog
| Version | Datum | Änderungen |
|---------|-------|-----------|
| v1.0 | 2026-03-13 | Initiale Version |