Entwickler
Dem Postfach ist egal,
wer am Steuer sitzt.
Alles, was die App kann, kann auch eigener Code: 104 dokumentierte Operationen über 68 Pfade, hinter einem OpenAPI-3.1-Dokument, das ohne Schlüssel lesbar ist. Der TypeScript-Client wird bei jedem Build an diesem Dokument gemessen.
Für MCP muss kein Schlüssel eingefügt werden. Der Client findet den Autorisierungsserver über den Endpunkt, registriert sich selbst und schickt zur Anmeldung hierher.
104
dokumentierte Operationen
68
Pfade unter einem Host
116
SDK-Methoden, die alle abdecken
20
Webhook-Ereignisse, in drei Familien
Das OpenAPI-3.1-Dokument liegt unter GET /openapi.json, und zum Lesen braucht es keinen Schlüssel.
Oberflächen
Drei Türen,
ein Postfach.
Ein Workspace-Schlüssel entscheidet, was ein Aufruf darf und als welche Adressen er senden darf. Widerrufen ist eine Aktualisierung, keine Löschung, ein späterer Aufruf erfährt also, dass der Schlüssel widerrufen wurde.
Ein Schlüssel sendet als bis zu 25 ganze Domains und 50 einzelne Adressen. GET /ping liest zurück, welche Geltungsbereiche er hält und welche seine Rolle ihm gelassen hat.
Einen Client auf den Endpunkt richten und anmelden. Es gibt keinen Schlüssel zum Einfügen, denn der Client registriert sich selbst und schickt hierher.
Die Werkzeuge entstehen aus dem, was der Aufrufer darf, ein auf Lesen beschränkter Client hat also kein Werkzeug zum Senden. Ein Token reicht trotzdem an das ganze Postfach.
Einen https-Endpunkt registrieren, und das Postfach postet dorthin. Zustellungen löst das Postfach selbst aus, nicht ein API-Aufruf, Verfassen in der App und Posten an die API lösen also dieselbe aus.
20 Ereignisse in drei Familien und zehn Endpunkte je Postfach.
Parität
Der Client kann nicht abweichen
von der API.
Eine Paritätsprüfung liest bei jedem Build das OpenAPI-Dokument und schlägt bei Abweichungen fehl: eine Methode, die auf eine Operation zeigt, die die Spezifikation nicht kennt, eine dokumentierte Operation ohne Methode oder eine Liste von Geltungsbereichen, die nicht zu dem passt, was die Operation verlangt. Sie gibt aus, was sie belegt hat, und heute steht dort: 116 SDK-Methoden über alle 104 dokumentierten Operationen.
Die Konfiguration, die Anfrage und der Aufruf sind dieselbe Operation, dreimal anders geschrieben.
Agenten, API & MCP
OpenEmail soll sich von Software genauso bedienen lassen wie von Menschen. Das Postfach ist in beiden Fällen dasselbe.
MCP-Server
Claude, oder jeden MCP-Client, auf das eigene Postfach richten.
OAuth für Clients von Drittanbietern
BaldClient-Registrierung im Self-Service mit PKCE, damit eine App ordentlich um Zugriff bitten kann.
Zustimmung und Widerruf gibt es, Scopes nicht, also reicht ein Token ans ganze Postfach statt nur an den Teil, den eine App angefragt hat.
REST API
Eine dokumentierte HTTP-API mit Schlüsseln, die sich ausstellen, eingrenzen und widerrufen lassen.
Schnellstart
Von nichts zur gesendeten Nachricht.
Drei Schritte.
- 1
Schlüssel erzeugen
Einstellungen, API-Schlüssel, auf einem eigenen Postfach. Geltungsbereiche wählen und eingrenzen, als was gesendet werden darf: ganze Domains oder einzelne Adressen. Das Geheimnis wird einmal angezeigt, gespeichert wird ein Einweg-Hash.
GET /ping antwortet mit den Geltungsbereichen des Schlüssels und denen, die seine Rolle ihm gelassen hat. export OPENEMAIL_API_KEY=oe_live_9f2c1a4b7e05d3862c1f0a44_kX7… curl https://api.openemail.uk/ping \ -H "Authorization: Bearer $OPENEMAIL_API_KEY" - 2
Client installieren
Ein TypeScript-Client ohne Abhängigkeiten, veröffentlicht als ESM und CommonJS, der den Schlüssel aus OPENEMAIL_API_KEY liest. Wer lieber selbst JSON postet, lässt ihn weg, denn jeder Endpunkt ist schlichtes HTTP.
Node 18 und höher, Workers, Deno, Bun und der Browser. bun add @openemail/sdk - 3
Senden
Die Antwort trägt die id. GET /emails/{id} löst sie auf, /events hat die Spur je Empfänger und /tracking hat Öffnungen und Klicks.
Ein erneuter Versuch mit demselben Idempotency-Key gibt das erste Ergebnis zurück, mit Idempotency-Replayed: true. import { init, openemail } from '@openemail/sdk' init({ apiKey: process.env.OPENEMAIL_API_KEY }) const email = await openemail.emails.send({ from: 'Acme Billing <[email protected]>', to: '[email protected]', subject: 'Your September invoice', html: '<p>Invoice attached.</p>',}) console.log(email.id, email.status)
Fehlt
Was es nicht übernimmt
jedenfalls noch nicht.
Fünf Dinge, die man besser vorher kennt als hinterher, wenn man dagegen baut.
- Kein Upload-Endpunkt
- Eingebettete Anhänge gehen als base64 mit einer Gesamtgrenze von 5 MB. Eine größere Datei wird gesendet, indem eine bereits im Workspace liegende Datei über ihre id benannt wird, die dann als Download-Link mitreist.
- Unzustellbarkeiten enden am Postfach
- Ein Zustellbericht wird geparst, über die Message-ID zugeordnet, am Thread markiert und als email.bounced-Webhook ausgeliefert. In die Sendezeile wird nichts zurückgeschrieben, über GET /emails gilt eine unzustellbare Nachricht also weiterhin als gesendet.
- Mail aus dem Verfassen-Fenster fehlt in GET /emails
- Mail aus dem Verfassen-Fenster der App taucht in dieser Liste nicht auf, weil das Verfassen-Fenster nicht über denselben Sendeweg schreibt.
- OAuth kennt Zustimmung, keine Geltungsbereiche
- Eine Anfrage wird vor der Freigabe angezeigt, und unter Verbundene Apps lässt sie sich zurücknehmen, aber ein Token reicht an das ganze Postfach statt an den Teil, den eine App angefragt hat.
- Kein Release-Workflow
- Das Veröffentlichen des Clients ist ein manueller Durchlauf von Preflight, Build und bun publish, eine Version erreicht npm also dann, wenn jemand ihn ausführt, und nicht, wenn die Änderung landet.
Eine Zustellung prüfen
Jede Zustellung ist signiert,
und jeder erneute Versuch trägt ihre id.
Die Signatur ist ein HMAC-SHA-256 über den Zeitstempel, einen Punkt und den rohen Body. Geprüft wird gegen die Bytes, wie sie ankamen, denn Parsen und erneutes Serialisieren ordnet Schlüssel um und macht sie kaputt.
X-OpenEmail-Signature: t=1758240000,v1=9f0c4b2e7d1a86c3X-OpenEmail-Event: email.deliveredX-OpenEmail-Delivery: evt_4b7e05d3862c1f0a- Replay-Fenster
- 300 Sekunden, und das durchzusetzen ist Sache des Empfängers. Der Verifier im SDK nutzt sie als Standard.
- Idempotency-Key
- Beansprucht über einen eindeutigen Index aus dem Key und dem API-Schlüssel zusammen, ein erneuter Versuch nach einem Timeout gibt also das erste Ergebnis mit Idempotency-Replayed: true zurück, statt zweimal zu senden.
- Wiederholungen
- Fünf Versuche: beim Eintreten des Ereignisses, dann nach 1 Minute, 5, 25 und 2 Stunden. Wiederholt wird nur bei einem Timeout, einer abgelehnten Verbindung, 408, 425, 429 oder einem 5xx.
- X-OpenEmail-Delivery
- Die Ereignis-id wird einmal vergeben und jeder Versuch trägt sie, ein Empfänger, der dieselbe id zweimal sieht, kann die zweite also verwerfen, statt erneut zu handeln.
Für wen es ist
Ein Postfach.
Drei Wege hinein.
Eine kostenlose Adresse bei openemail.uk, mit dem Client dahinter.
Adressen für alle, Mitglieder zählen nie als Plätze.
Dasselbe Postfach über API, SDK und MCP.
Schlüssel erzeugen.
Etwas senden.
Full API, MCP and SDK access in jedem Tarif. Free bringt 50 AI actions a day mit.