# HTTP-API-Referenz

## Sprachen und Fehlercodes

Englisch ist die Standardeinstellung. Die API, die Webkonsole und die Benachrichtigungsrenderer nutzen die eingebetteten Kataloge in `internal/i18n/locales/` gemeinsam. `internal/i18n/languages.json` definiert diese kanonischen Codes und nativen Namen:

| Code      | Sprache            |
| --------- | ------------------ |
| `en`      | English            |
| `zh-CN`   | 简体中文           |
| `zh-Hant` | 繁體中文           |
| `ja`      | 日本語             |
| `ko`      | 한국어             |
| `de`      | Deutsch            |
| `fr`      | Français           |
| `es`      | Español            |
| `pt-BR`   | Português (Brasil) |

- Beim ersten Besuch verwendet die Konsole den `Accept-Language` des Browsers. Sein Selektor speichert den ausgewählten kanonischen Code lokal. Beim Wechseln der Konsolensprache bleiben gespeicherte Benachrichtigungseinstellungen unverändert.
- API-Anfragen, einschließlich App-Management-Anfragen, verhandeln `Accept-Language` nach Qualitätsgewichtungen. Zu den Antworten gehören `Content-Language` und `Vary: Accept-Language`. Nicht unterstützte Einstellungen werden übersprungen; Fehlende, ungültige oder völlig nicht unterstützte Einstellungen fallen auf `en` zurück. Eine Sprache mit Gewicht 0 ist von der Verhandlung ausgeschlossen.
- Regionale Varianten werden ihrer unterstützten Sprache zugeordnet: `fr-CA` → `fr` , `es-MX` → `es` , `pt` / `pt-PT` → `pt-BR` . Chinesische Schrift wird respektiert: `zh-Hans` / `zh-CN` / `zh-SG` → `zh-CN` ; `zh-Hant` / `zh-TW` / `zh-HK` / `zh-MO` → `zh-Hant` . Ein explizites Skript hat Vorrang vor der Region. plain `zh` verwendet vereinfachtes Chinesisch.
- `GET /locales/default.json` bedient den ausgehandelten Katalog; `GET /locales/{canonical-code}.json` bedient diesen Katalog explizit. Unbekannte Katalogpfade geben `locale_not_supported` zurück.
- Zustellungseinstellungen `language` steuert die vom Außenposten generierten Benachrichtigungen unabhängig von der Anfrage oder der Konsolensprache. Es akzeptiert die kanonischen Codes und unterstützten regionalen Varianten, behält den kanonischen Code bei und verwendet standardmäßig `en`, wenn es weggelassen oder leer ist. Ein nicht unterstützter expliziter Wert gibt 400 `config_language_invalid` zurück.
- Der Push-Zustelldienst generiert einen nativen Testbenachrichtigungstext in der Sprache des gekoppelten Geräts. Die Benachrichtigungssprache des Außenpostens überschreibt diese Sprache nicht. Der Push-Zustelldienst und die App unterstützen jeweils ihre eigenen Sprachen.
- Standardordnerrollen und allgemeine Ordnernamen werden in der Konsole lokalisiert. Rohe IMAP-Pfade, benutzerdefinierte Namen und `folder_roles` bleiben in APIs unverändert; Apps lokalisieren diese Rollen mit ihren eigenen Katalogen. Benachrichtigungstitel verwenden weiterhin den ursprünglichen Blattordnernamen. Vom Benutzer eingegebene Namen, E-Mail-Betreff, E-Mail-Inhalte und Bestätigungscodes bleiben wörtlich.
- Für Protokolle und CLI-Ausgaben wird Englisch verwendet. Geschäftsfehler behalten stabile englische `snake_case`-Codes und benannte Parameter bei; Der Speicher speichert Codes und Parameter und Anzeigeebenen übersetzen Nachrichten. Datumsangaben und Zahlen in API-Antworten behalten ihre bestehenden maschinenlesbaren Formate; Die Konsole formatiert Zeitstempel mit dem von ihr gewählten Gebietsschema.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Sign in with a valid session or API token."
  }
}
```

`last_error` in Lieferdatensätzen und `notice` im Ordnerstatus verwenden dieselbe `{code, message, params?}`-Form, zum Beispiel `bark_http_error` mit `{"status":"503"}` . Zweig auf `code` ; `message` anzeigen.

Jedes Postfach reserviert eine Verbindung für seine Ordnererkennung und Verbindungstests. Die Beobachteranforderung beträgt `realtime Folder count + (1 if any scheduled Folders exist, otherwise 0)`, höchstens `connection_limit - 1`-Verbindungen (standardmäßig 9); Alle Vorgänge für dieses Postfach bleiben zusammen innerhalb von `connection_limit` (2–100). Gespeicherte Konfigurationen mit einem Limit von 1 Start im Wiederherstellungsmodus mit `configuration_invalid`.

## HTTP-API

`GET /` bedient die aktuelle Seite; Statische Assets und `/healthz` sind öffentlich. Vor der Einrichtung gibt jeder andere Verwaltungsendpunkt 403 `setup_required` zurück. `POST /api/v1/setup` ist einmal verfügbar; `POST /api/v1/session` ist nach der Einrichtung öffentlich. Alle übrigen APIs erfordern das Sitzungscookie oder `Authorization: Bearer mwk_…` .

Cookie-Sitzungen verwenden HttpOnly, SameSite=Strict, Path=/, Secure auf einer TLS-Verbindung oder einem HTTPS-Ursprung, ein Leerlauf-Timeout von sieben Tagen und ein absolutes Timeout von 30 Tagen. Jede Cookie-authentifizierte Mutation erfordert `X-CSRF-Token` und einen HTTP(S) `Origin`, dessen Host und optionaler Port genau mit dem Anforderungshost übereinstimmen. Inhaberanfragen überspringen CSRF-Prüfungen. Ein ungültiger Autorisierungsheader schlägt fehl, selbst wenn ein gültiges Cookie vorhanden ist.

Anmelde- und Setup-Code-Fehler teilen sich ein Quell-Adress-Budget: zehn Fehler pro 15 Minuten, gefolgt von 429 `too_many_attempts` mit `Retry-After` in Sekunden. Die Quelle ist Gin ClientIP unter Verwendung der oben genannten vertrauenswürdigen Proxy-Bereiche. Auch Passwortänderungen verbrauchen dieses Budget. Explizite standortübergreifende Ursprünge werden bei der Anmeldung und Einrichtung abgelehnt. Da jeder Peer im privaten Netzwerk als Proxy vertrauenswürdig ist, kann ein Client in Ihrem lokalen Netzwerk X-Forwarded-For festlegen und seine Versuche auf viele Quelladressen verteilen. Setzen Sie den Außenposten-Listener keinem nicht vertrauenswürdigen lokalen Netzwerk aus; Veröffentlichen Sie es nur über Ihren Reverse-Proxy.

Alle JSON-Körper sind auf 64 KiB begrenzt; Unbekannte Felder oder nachgestelltes JSON geben 400 zurück. Passwörter bestehen aus mindestens 12 Zeichen und maximal 1024 UTF-8-Bytes. Benutzernamen und Token-Namen sind 1–128 Byte lang. Alle Zeitstempel der Verwaltungs-API sind RFC 3339-Zeichenfolgen in UTC, einschließlich Lieferung `created_at` / `accepted_at`, Token `created_at` / `last_used_at`, Ordnerprüfungen, Protokollzeiten und Diagnosegenerierungszeit. Sekundenbruchteile bewahren die gespeicherte Präzision. Das nicht verwendete Token `last_used_at` ist null; Lieferungen ohne Abnahme entfallen `accepted_at`. Anzahl, Dauer und Revisionen bleiben Zahlen.

401 identifiziert eine ungültige Sitzung oder ein ungültiges API-Token oder abgelehnte Anmeldeinformationen für `POST /api/v1/session`. Ein falscher Setup-Code gibt 400 `setup_code_invalid` zurück; Der Assistent kehrt zum Codeschritt zurück und behält den Benutzernamen bei. Ein falsches aktuelles Passwort für `PUT /api/v1/admin/password` gibt 400 `current_password_invalid` zurück und zählt zur Fehlergrenze; Die aktuelle Sitzung bleibt gültig. Anmeldefehler und Fehler beim aktuellen Passwort werden im Formular angezeigt, wobei die Eingaben erhalten bleiben.

| Verfahren          | Weg                                   | Anfrage/Antwort                                                                                                                        |
| ------------------ | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| POST               | `/api/v1/setup`                       | `{ "code":"XXXX-XXXX-XXXX", "username":"admin", "password":"…" }` ; 201, Cookie + `{ "csrf_token":"…" }` ; Setup wiederholen: 409      |
| POST               | `/api/v1/session`                     | `{ "username":"admin", "password":"…" }` ; 200, Cookie + CSRF-Token                                                                    |
| GET                | `/api/v1/session`                     | `{ "authenticated":true, "csrf_token":"…" }` ; Bearer gibt `method: "token"` anstelle von CSRF zurück                                  |
| DELETE             | `/api/v1/session`                     | 204; widerruft die aktuelle Cookie-Sitzung; erfordert eine Sitzung                                                                     |
| PUT                | `/api/v1/admin/password`              | `{ "current_password":"…", "password":"…" }` ; 204, widerruft andere Sitzungen; Der Inhaber widerruft alle Sitzungen                   |
| POST               | `/api/v1/tokens`                      | `{ "name":"automation" }` ; 201, `{ "id":"…", "name":"…", "created_at":"2026-09-29T01:02:03Z", "last_used_at":null, "token":"mwk_…" }` |
| GET                | `/api/v1/tokens`                      | `{ "tokens":[…] }` ; Nur Metadaten                                                                                                     |
| DELETE             | `/api/v1/tokens/:id`                  | 204; widerruft einen Token; Wiederholtes Löschen gibt ebenfalls 204 zurück                                                             |
| GET                | `/api/v1/mailboxes`                   | `{ "mailboxes":[…] }` ; geschwärzte Postfachansichten                                                                                  |
| POST               | `/api/v1/mailboxes`                   | Erstellen Sie mit dem untenstehenden Postfachformular; 201, redigierte Ansicht mit generiertem `id` und Revision 1                     |
| GET / PUT / DELETE | `/api/v1/mailboxes/:id`               | Lesen/Aktualisieren mit aktueller Revision/Löschen (204); Fehlende ID gibt 404 `mailbox_not_found` zurück                              |
| POST               | `/api/v1/mailboxes/test`              | Testen Sie ein nicht gespeichertes Formular. gibt `{ "folders":[…] }` zurück, behält die Konfiguration unverändert bei                 |
| POST               | `/api/v1/mailboxes/:id/test`          | Testen Sie das Formular mit ausgelassenen Anmeldeinformationen, die aus diesem Postfach zusammengeführt wurden                         |
| GET                | `/api/v1/mailboxes/:id/folders`       | Entdecken Sie auswählbare Ordner mit dem Budget dieses Postfachs                                                                       |
| GET / PUT          | `/api/v1/mailboxes/:id/subscriptions` | Abonnements mit ihrer eigenen Revision lesen/speichern; Erfolgreiches Speichern gibt 202 zurück                                        |
| GET / PUT          | `/api/v1/settings/delivery`           | Globale Liefereinstellungen mit eigener Revision lesen/speichern                                                                       |
| DELETE             | `/api/v1/settings/delivery`           | Löschen Sie gespeicherte Kanäle und Anmeldeinformationen mit `{revision}`. 204, veraltete Revision 409                                 |
| POST               | `/api/v1/settings/delivery/test`      | Testen Sie das Lieferformular mit zusammengeführten gespeicherten Anmeldeinformationen. 204, Konfiguration unverändert                 |
| GET                | `/api/v1/status`                      | Ordnerstatus, Kanal, Zustellungsanzahl und Benachrichtigungen zum Gültigkeitsbereich                                                   |
| GET                | `/api/v1/diagnostics`                 | Laden Sie einen redigierten JSON-Bericht ohne Laufzeitprotokolle herunter                                                              |
| GET                | `/api/v1/logs`                        | Authentifizierte Betriebsprotokolle; Filter `after`, `level`, `mailbox_id`, `limit` (siehe unten)                                      |
| GET                | `/api/v1/deliveries`                  | Die letzten 50 Zustellungsdatensätze, einschließlich Betreff und Postfach-/Ordnerübersicht                                             |
| POST               | `/api/v1/test-push`                   | Senden Sie einen Test mit gespeicherten Einstellungen. 204 bei Annahme, Konfiguration unverändert                                      |
| POST               | `/api/v1/deliveries/:id/retry`        | Eine `dead`-Aufgabe erneut in die Warteschlange stellen; 202                                                                           |

Zustellungsdatensätze enthalten ein optionales `message`-Objekt: `mailbox_id`, `mailbox_label`, `folder`, `subject` (Zeichenfolge oder Null) und `test` (boolean). Namen sind Schnappschüsse aus der Zeit, in der sie in die Warteschlange gestellt werden, und überdauern das Umbenennen oder Löschen von Postfächern. Ein Nullsubjekt bedeutet, dass es nicht beibehalten wurde; Eine leere Zeichenfolge bedeutet, dass die E-Mail keinen Betreff hatte. Testbenachrichtigungen haben `test=true` und keine Postfachquelle. Die API lässt Absender und Text in dieser Zusammenfassung weg.

Beispiel für die Postfacherstellung:

```json
{
  "label": "Work mailbox",
  "host": "imap.example.org",
  "port": 993,
  "username": "user@example.org",
  "password": "…",
  "connection_limit": 10
}
```

Der Außenposten erlaubt höchstens 20 gespeicherte Postfächer, einschließlich ungültiger Konfigurationen, die auf eine Reparatur warten; Die nächste Erstellung gibt 400 `mailbox_limit_exceeded` zurück. IDs werden als `mbx_` plus einer zufälligen Zeichenfolge generiert und bleiben stabil. `label` verwendet standardmäßig den Benutzernamen (E-Mail-Adresse), erlaubt höchstens 64 Unicode-Zeichen und lehnt Zeilenumbrüche ab. Ein Benutzername mit mehr als 64 Zeichen benötigt eine explizite kürzere Bezeichnung. Ausgelassene Beschriftungen bei der Aktualisierung behalten den gespeicherten Wert; ein leeres Label verwendet den übermittelten Benutzernamen.

Das Postfach PUT verwendet das gleiche Formular plus `"revision":1` (den aus GET gelesenen Wert) und erfordert Host, Port und Benutzernamen. Bei unverändertem Host, Port und Benutzernamen bleibt ein weggelassenes Passwort erhalten; ein explizit leeres Passwort wird abgelehnt. Weggelassen `connection_limit` behält den aktuellen Wert; Neue Postfächer sind standardmäßig 10, Bereich 2–100. Bei der Erstellung von POST wird die Revision weggelassen oder 0 gesendet. Testrouten akzeptieren dieselben Felder, ohne dass eine Revision erforderlich ist, und behalten die Konfiguration unverändert bei. Für den nicht gespeicherten Test sind Anmeldeinformationen erforderlich. Der Test für gespeicherte Postfächer führt ausgelassene Anmeldeinformationen nur von der angegebenen ID zusammen.

Eine Postfach-GET-Ansicht umfasst `id`, `label`, `revision`, `host`, `port`, `username`, `connection_limit`, `connections_in_use` und `"password":{"configured":true}`. Ein wiederhergestelltes ungültiges Postfach meldet `configured:false` und behält seine ID und Revision, damit es repariert werden kann. Das Kennwortobjekt GET ist eine Ansicht, kein gültiger Schreibwert.

Jedes Postfach verfügt über ein unabhängiges Verbindungsbudget. Echtzeitordner belegen jeweils einen Steckplatz. Alle seine geplanten Ordner verbrauchen zusammen einen. Ihr kombinierter Bedarf muss in `connection_limit - 1` passen und einen Steckplatz für die Verwaltung reservieren. Das Abonnement PUT und die Änderungen an der Postfachbegrenzung erzwingen diese Formel. Erschöpfte Kapazität gibt `connection_budget_exceeded` zurück. Das Testen eines nicht gespeicherten Postfachs verbraucht ein temporäres Budget. Die nicht gespeicherten Test-, gespeicherten Postfachtest- und Ordnererkennungsendpunkte haben außerdem ein gemeinsames globales Parallelitätslimit von 2; Überzählige Anfragen geben sofort 429 `discovery_busy` zurück. Bei Abschluss oder Absage entfällt die Zulassung.

Auslieferungsbeispiel PUT für einen zunächst unkonfigurierten Kanal:

```json
{
  "revision": 0,
  "channel": "bark",
  "preview": "off",
  "retry_count": 0,
  "language": "en",
  "bark": { "endpoint": "https://api.day.app", "key": "…" }
}
```

Lesen Sie `/settings/delivery` vor jedem Update und senden Sie die Revision; Beim ersten Speichern geht es von 0 auf 1. Pushover verwendet `"pushover":{"token":"…","user":"…"}`; Webhook verwendet `"webhook":{"url":"https://hooks.example.org/mail","secret":"…"}` . Kanal, Vorschau und Überarbeitung sind erforderlich. Ausgelassene Sprache und Wiederholungsanzahl verwenden Standardwerte. Bei unverändertem Ziel bleiben ausgelassene Zugangsdaten einschließlich der Webhook-URL erhalten; Ein explizit leerer aktiver Berechtigungsnachweis wird abgelehnt. GET ersetzt alle Anmeldeinformationen durch `{"configured":true|false}`. Der separate Testendpunkt erfordert keine Überarbeitung.

Beim Erstellen und Ändern von Postfächern wird die Verbindung/Anmeldung vor dem Speichern getestet. Wenn Host, Port, Benutzername und Verbindungslimit (connection_limit) mit den gespeicherten Werten übereinstimmen und das Passwort weggelassen wird, ändert PUT nur die Bezeichnung: Revisionsprüfung und Persistenz gelten weiterhin, während Tests und Watcher-Ersetzung übersprungen werden. Aufgaben in der Warteschlange behalten ihre ursprüngliche Bezeichnung; Zukünftige Aufgaben verwenden das neue Label. Das Erstellen oder Aktualisieren einer Identität, die bereits von einem anderen Postfach verwendet wird, gibt 409 `mailbox_duplicate` zurück (Host- und Benutzername werden ohne Berücksichtigung der Groß- und Kleinschreibung verglichen, Port genau); Durch die gleichzeitige Erstellung kann diese Identität nur einmal gespeichert werden. Die Lieferung PUT speichert alle Kanäle nach Feld, Adresse, ausgewähltem Paarungsstatus und Revisionsvalidierung, ohne einen Test zu senden oder einen Anbieter zu kontaktieren. Bei expliziten Zustellungstests bleiben die gespeicherten Einstellungen unverändert; Ihr Scheitern blockiert nicht eine spätere Speicherung. Postfachtests werden außerhalb von Konfigurationssperren ausgeführt und halten vorhandene Beobachter aktiv; Bei einem fehlgeschlagenen Postfachtest bleibt die vorherige Konfiguration erhalten. Veraltete Einstellungsrevisionen geben 409 `settings_conflict` zurück; Eine Abonnementänderung während eines Postfachtests macht auch den Snapshot dieses Tests ungültig. Laden Sie es erneut, bevor Sie es erneut versuchen. Jedes Postfach und die globalen Zustellungseinstellungen verfügen über unabhängige Revisionen, sodass Änderungen an verschiedenen Postfächern oder an einem Postfach und der Zustellung nicht zu Konflikten führen.

Ein erfolgreicher PUT gibt die redigierte Ansicht zurück und wird sofort angewendet. Eine Änderung der Postfachverbindung stoppt die eigenen Beobachter vor dem Speichern und dem optionalen Zurücksetzen des Cursors. ein fehlgeschlagener Speichervorgang stellt sie wieder her. Andere Postfächer laufen weiter. Bei Zustellungsänderungen bleibt die Momentaufnahme eines Flugversuchs erhalten; Nachfolgende Versuche verwenden das neue. Ausstehende Aufgaben warten, während die Zustellung nicht konfiguriert ist.

`GET /api/v1/mailboxes/:id/subscriptions` gibt `{"revision":1,"folders":[{"name":"INBOX","check":"realtime"},{"name":"Clients","check":"5m"}]}` zurück. PUT sendet die gelesene Revision und das komplette `folders`-Array; Ein leeres Array meldet sich von allem ab. Namen sind innerhalb jedes Postfachs eindeutig, INBOX ist normalisiert und jeder Name umfasst höchstens 4096 UTF-8-Bytes. Für jeden Ordner sind `name` und `check` erforderlich. Die Prüfung lautet `realtime`, `5m` oder `15m`. Fehlende/ungültige Prüfungen und das vorherige String-Array-Format geben 400 zurück. Die obige Formel für den Verbindungsbedarf ersetzt die Begrenzung der Ordneranzahl. Wenn Sie nur die Prüfung ändern, bleibt der Fortschritt erhalten, neue E-Mails werden abgerufen und vorhandene Ereignis-IDs bleiben erhalten. Durch das Kündigen und spätere erneute Abonnieren entsteht eine neue Grundlinie. Alle Felder sind Pflichtfelder. Beim Speichern wird bei der nächsten Revision 202 zurückgegeben; Veraltete Revisionen geben 409 `subscriptions_conflict` zurück. Das Vorhandensein des Ordners wird vom Watcher bestätigt, sodass Abonnements entfernt werden können, während das Postfach offline ist. Speicherfehler geben 503 zurück und behalten aktuelle Abonnements bei.

Zu jedem `/status.folders[]`-Artikel gehören `mailbox_id`, `mailbox_label` und `check`. `mode` ist `idle`, `poll` oder `scheduled`; Zu den geplanten Ordnern gehört auch `next_check` (RFC 3339-Zeit, einschließlich Wiederholungszeiten). Echtzeitordner lassen `next_check` weg. Gespeicherte Konfigurationen, die die JSON- oder Modellvalidierung nicht bestehen, werden dekonfiguriert, mit `configuration_invalid` in `/status.notices` unter `mailbox:<id>` oder `delivery`; PUT repariert diesen Artikel. Überschüssige Abonnements pausieren nur dieses Postfach und melden `connection_budget_exceeded` unter `subscriptions:<id>`. Durch die Reduzierung der Abonnements oder die Erhöhung des Limits wird die Überwachung wieder aufgenommen. Entschlüsselungsfehler stoppen den Start.

Die Diagnose-Zulassungsliste enthält Generierungszeit, Build-/Go-/Plattforminformationen, Warteschlangenanzahl sowie anonyme Postfach- und Watcher-Status, einschließlich `check` und `mode`. `mailboxes[].index` und `watches[].mailbox_index` identifizieren „Mailbox 1“, „Mailbox 2“ usw. in diesem Bericht; Die Beobachter jedes Postfachs haben ihren eigenen `index` . Postfacheinträge enthalten Konfigurations-/Abonnementbenachrichtigungscodes. Nur `imap_folder_rejected` kann `watches[].response_code` enthalten. Der Bericht lässt Postfach-IDs, Anzeigenamen, Adressen, Servernamen, Ordnernamen, Nachrichtendaten, Aufgaben-IDs, Anmeldeinformationen und alle anderen Fehlerparameter weg.

Aufgabenstatus: `pending` wartet auf eine Anfrage, `accepted` bedeutet, dass der Kanal die Anfrage akzeptiert hat, `dead` bedeutet, dass der Versuch mit einem aufgezeichneten Fehler endete.

## Laufzeitprotokolle

Verwenden Sie `docker compose logs -f core` (oder `docker logs <container>`) für die JSON-Stdderr-Ausgabe. Authentifizierte Clients können dieselben Betriebsereignisse über `GET /api/v1/logs?after=0&level=info&mailbox_id=mbx_example&limit=200` abfragen. Es ist ein Sitzungscookie oder API-Token erforderlich.

Der In-Memory-Ring speichert die neuesten **2000** Info-/Warn-/Fehlereinträge und löscht sie beim Neustart. `after` ist eine exklusive nichtnegative Sequenz; `level` wählt diese Stufe und höher aus (`info`-Standardeinstellung); weggelassen `mailbox_id` umfasst alle Postfächer und globalen Vorgänge. `limit` ist standardmäßig 200, Bereich 1–500. Ungültige Parameter geben 400 `logs_request_invalid` zurück.

```json
{
  "entries": [
    {
      "seq": 42,
      "time": "2026-09-29T00:00:00Z",
      "level": "info",
      "message": "Folder connection established",
      "attrs": {
        "mailbox_id": "mbx_example",
        "folder": "INBOX",
        "mode": "idle",
        "check": "realtime"
      }
    }
  ],
  "next": 42,
  "cleared_through": 0
}
```

Verwenden Sie `next` als `after` der nächsten Anfrage. Am Seitenlimit ist es die letzte zurückgegebene Sequenz; Nach dem Scannen des Snapshots geht es zum Snapshot-Ende über, auch wenn die Filter keine Übereinstimmung ergeben. Bereinigte Einträge werden übersprungen. Wenn der Neustart `next < after` zurückgibt, setzen Sie den Cursor auf 0 zurück. Die Einträge werden nach Reihenfolge sortiert.

Die Protokolle umfassen Postfach- und Ordner-Lebenszyklen, Basis-/Warteschlangenanzahl, Zustellungsversuche, Konfigurationsänderungen und Administratoraktionen. Globale Ereignisse verwenden ein leeres `mailbox_id` . Nur diese Skalarattribute werden angezeigt: `mailbox_id`, `folder`, `mode`, `check`, `code`, `event_id`, `channel`, `attempt`, `duration_ms`. `http_status`, `next_attempt`, `backoff_seconds`, `count`, `revision`, `token_id`, `version`, `listen`, `request_id`, `method`, `route`, `stage`, `outcome`, `cause_code`, `response_code`. `http_status=0` bedeutet, dass keine HTTP-Antwort empfangen wurde; `token_id` ist eine öffentliche Datensatzkennung, nicht der Tokenwert. Passwörter, Token-/Sitzungswerte, Setup-Codes, Absender, Betreff, Textkörper und Anmeldeinformations-URLs werden weggelassen. Die Setup-Code-Zeile geht nur an die Konsole. Protokolle enthalten Ordnernamen; Der anonyme Diagnoseexport schließt Protokolle und Namen aus.

Ordnererkennungs- und Administrator-Postfachtests geben `folders` als ursprüngliches Pfadarray sowie optional `folder_roles` zurück, eine Zuordnung vom Pfad zu `inbox`, `drafts`, `sent`, `trash`, `junk`, `archive`, `all` oder `flagged` . Rollen stammen aus IMAP SPECIAL-USE-Attributen; INBOX wird anhand seines protokolldefinierten Namens erkannt. Wenn keine Rollen vorhanden sind, greift die Web-Benutzeroberfläche auf exakte Übereinstimmungen ohne Berücksichtigung der Groß- und Kleinschreibung für gebräuchliche englische Ordnernamen zurück. Übersetzte Namen zeigen den ursprünglichen Pfad in Klammern; andere Namen bleiben unverändert. Durch Anzeigeübersetzungen werden die Abonnementpfade nie geändert. Benachrichtigungstitel verwenden das letzte Segment der durch Schrägstriche getrennten Ordnerpfade; Strukturierte Ordnerfelder behalten den vollständigen Pfad. App-Postfachtests geben weiterhin nur den Verbindungsstatus zurück.

`GET /api/v1/session` enthält `username` für eine authentifizierte Cookie-Sitzung. Die Token-Authentifizierung behält ihre bestehende Antwort.

### App-Empfangsgerät

Zu den Liefereinstellungen gehört `native_pairing_id`. Wählen Sie für den Kanal `native` eine aktive Paarung aus `/api/v1/native/devices` aus. Sowohl Testbenachrichtigungen als auch neue Ereignisse zielen nur auf diese Paarung ab. Wenn Sie das Feld bei einer Aktualisierung weglassen, bleibt die gespeicherte Auswahl erhalten. Eine leere Auswahl gibt `native_target_required` zurück. Eine nicht verfügbare Auswahl gibt `native_target_unavailable` zurück. Durch das Widerrufen der ausgewählten nativen Paarung werden Kanal und native_pairing_id atomar gelöscht und die Revision einmal erhöht. Andere Ziele und Kanäle bleiben erhalten. Bestehende Lieferungen behalten ihr Ziel und Widerrufsergebnis. Informationen zu Timing, Parallelität und Neustartverhalten finden Sie unter [Pairing-Synchronisation](https://github.com/mingzaily/mailwake/blob/main/docs/native-push.md#pairing-revocation-synchronization).

Die App-Autorisierung verwaltet die Administration und die Push-Berechtigung unabhängig voneinander. Wenn Sie eine der Berechtigungen widerrufen, bleibt die andere unverändert.

### Native Testbenachrichtigungen

Der Außenposten verwendet signiertes `POST /v1/pairing-tests` mit `{pairing_id,test_id}` (eine neue UUID pro explizitem Test). Der Push-Zustelldienst generiert feste Inhalte und übermittelt sie synchron an APNs, ohne dass eine Native Push-Berechtigung erforderlich ist. Formulartests, Tests mit gespeicherten App-Einstellungen und `/api/v1/test-push` verwenden denselben Pfad. Tests sind vom E-Mail-Postausgang getrennt und haben keine automatischen Zustellungswiederholungen.

Der Außenposten gibt HTTP 204 nur zurück, wenn der Push-Zustelldienst `accepted` meldet. APNs-Ablehnung, unbekannte Ergebnisse und `sending` geben einen lokalisierten Fehler zurück; Durch die Ratenbegrenzung des Push-Zustelldienstes gibt der Außenposten HTTP 429 mit `Retry-After` zurück. Zu den sicheren Protokollen gehören der HTTP-Status des Push-Zustelldienstes und der stabile Fehlercode, ausgenommen Antworttexte, Token und Benachrichtigungsinhalte. Der Außenposten und die App teilen sich die vorhandenen Tageskontingente pro Gerät, Minute und Betreff sowie die `(device_id,test_id)`-Idempotenz des Push-Zustelldienstes. Ein Benutzer, der einen anderen Test startet, erstellt eine neue Test-ID.

Formale E-Mails verwenden `/v1/push` und bleiben unabhängig von der Ereignis-ID oder den Client-Testflags berechtigungsgeschützt. Stellen Sie die Push-Delivery-Service-Pairing-Test-Route vor dieser Außenposten-Version bereit; Der Außenposten greift nicht auf die Zustellung bezahlter Post zurück.

## Löschen Sie den Lieferverlauf und die Laufzeitprotokolle

- `DELETE /api/v1/deliveries` gibt `200 {"deleted":N}` zurück. Es entfernt abgeschlossene Datensätze ( `accepted` / `dead` ) dauerhaft im gesamten Verlauf, einschließlich der zugehörigen nativen Datensätze. Ausstehende Übermittlungen/Wiederholungsversuche, native Datensätze, die noch ausstehen/in der Warteschlange stehen/gesendet werden oder für Statusprüfungen geplant sind, und ausstehende native Aktivitätsaktualisierungen werden beibehalten. Durch das Löschen von Fehlern wird die manuelle Wiederholungsoption entfernt. Postfachprüfpunkte und -konfiguration bleiben erhalten.
- `DELETE /api/v1/logs` gibt `200 {"cleared_through":N}` zurück und löscht den gemeinsamen In-Memory-Ring für alle Ebenen und Postfächer. Die Sequenznummern nehmen weiter zu; stderr/container-Protokolle und exportierte Dateien bleiben erhalten. `GET /api/v1/logs` gibt auch `cleared_through` zurück; Clients verwerfen zwischengespeicherte Einträge mit `seq <= cleared_through`, bevor sie die zurückgegebenen Einträge anhängen.
- Für beide Endpunkte ist eine Administratorsitzung + Origin/CSRF oder ein Administrator-API-Token erforderlich. Mit den Anmeldeinformationen des App-Geräts sind diese Vorgänge nicht möglich. Wiederholtes Löschen ist sicher; Nach dem Vorgang können neue Arbeits- und Protokolleinträge erscheinen.

## Inhalt der App-Nachricht

`POST /api/v1/app/content` verwendet einen gerätegebundenen Controller-Zugang und den vom Eigentümer gewährten `content`-Scope. Senden Sie `{ "reference": <message_ref> }`; die Antwort enthält `text`, `truncated`, optional bereinigtes `html` und `has_remote_images`. Das Lesen ist kostenlos.

Sobald der Text lesbar ist, markiert `POST /api/v1/app/content/read` mit demselben Zugang, Scope und Verweis die Nachricht im Postfach als gelesen. Erfolg liefert `204 No Content` und `Cache-Control: no-store`. Der reine Abruf des Inhalts erhält den Lesestatus. Beide Vorgänge prüfen die aktuelle Berechtigung, den abonnierten Ordner, die Postfachidentität und den Nachrichtenverweis.

## Zielbindung der Zugangsdaten

Bei Tests und beim Speichern erfordert eine Änderung von `host`, `port` oder `username` die erneute Eingabe des gespeicherten Postfachpassworts; andernfalls folgt 400 `mailbox_password_required_for_change`. Eine Änderung der gespeicherten Bark-Adresse erfordert den Geräteschlüssel, auch wenn ein anderer Kanal ausgewählt ist; andernfalls folgt 400 `bark_key_required_for_change`. Port, Pfad und abschließender Schrägstrich gehören zur Adresse. Abgelehnte Anfragen öffnen keine Verbindung und erhalten Konfiguration und Revision.

## Diagnose von App-Anfragen

Diagnoseexporte verwenden `schema_version: 2`. `app_requests` enthält bis zu 300 kürzlich abgeschlossene App-Anfragen aus dem gemeinsamen Speicherprotokoll mit 2000 Einträgen: Zeit, serverseitige `request_id` (auch in `X-Request-ID`), Routenvorlage, Methode, HTTP-Status, Dauer, Phase, Ergebnis und sichere Fehlercodes. Ressourcen-IDs, Abfrageparameter, Zugangsdaten, signierte Referenzen, Nachrichteninhalte und vollständige Laufzeitprotokolle bleiben ausgeschlossen. Neustart und Protokolllöschung entfernen die Einträge; andere Ereignisse können ältere Anfragen verdrängen. Der Download aktualisiert den Bericht zuerst. Anfragen, die den Server nicht erreichen, benötigen App-Diagnosen.

`POST /api/v1/app/content/read` prüft UID und Flags. Bereits gelesene Nachrichten sind erfolgreich; ungelesene werden markiert und erneut geprüft. STORE OK allein beweist keine Existenz. Fehlende UID, geänderte UIDVALIDITY oder ausdrücklich fehlender Ordner ergeben 404, Anbieter- oder Berechtigungsfehler 503 und Zeitüberschreitungen 504. Zwischengespeicherte Inhalte bleiben bei ungültiger Remote-Referenz lesbar.
