Desarrolladores
Al buzón no le importa
quién lo maneja.
Todo lo que hace la app lo hace tu código: 104 operaciones documentadas repartidas en 68 rutas, tras un documento OpenAPI 3.1 que puedes leer sin clave. El cliente de TypeScript se contrasta con ese documento en cada compilación.
MCP no necesita ninguna clave que pegar. El cliente descubre el servidor de autorización desde el endpoint, se registra solo y te envía aquí para iniciar sesión.
104
operaciones documentadas
68
rutas bajo un solo host
116
métodos del SDK, que las cubren todas
20
eventos de webhook, en tres familias
El documento OpenAPI 3.1 está en GET /openapi.json, y leerlo no necesita clave.
Superficies
Tres puertas,
un solo buzón.
Una clave del espacio de trabajo decide qué puede hacer una llamada y desde qué direcciones puede enviar. Revocarla es una actualización y no un borrado, así que a una llamada posterior se le dice que la clave fue revocada.
Una clave envía desde hasta 25 dominios enteros y 50 direcciones sueltas. GET /ping devuelve los alcances que tiene y los alcances que le dejó su rol.
Apunta un cliente al endpoint e inicia sesión. No hay ninguna clave que pegar, porque el cliente se registra solo y te envía aquí.
Las herramientas se construyen a partir de lo que puede hacer quien llama, así que un cliente limitado a leer no tiene dentro ninguna herramienta de envío. Un token sigue alcanzando todo el buzón.
Registra un endpoint https y el buzón le hace las peticiones. Las entregas las genera el propio buzón y no una llamada a la API, así que redactar en la app y publicar en la API provocan la misma.
20 eventos en tres familias, y diez endpoints por buzón.
Paridad
El cliente no puede quedarse atrás
de la API.
Una comprobación de paridad lee el documento OpenAPI en cada compilación y falla ante cualquier desvío: un método que apunta a una operación que la especificación no tiene, una operación documentada sin método, o una lista de alcances que no concuerda con lo que la operación exige. Imprime lo que demostró, y hoy eso dice 116 métodos del SDK sobre las 104 operaciones documentadas.
La configuración, la petición y la llamada son la misma operación, escrita de tres maneras.
Agentes, API y MCP
OpenEmail está pensado para que lo maneje tanto el software como las personas. El buzón es el mismo en ambos casos.
Servidor MCP
Apunta Claude, o cualquier cliente MCP, a tu buzón.
OAuth para clientes de terceros
ProntoRegistro de clientes autogestionado con PKCE, para que una app pueda pedir acceso como corresponde.
El consentimiento y la revocación ya están; el alcance no, así que un token llega a todo tu buzón y no solo a la parte que pidió la app.
API REST
Una API HTTP documentada con claves que se emiten, se acotan y se revocan.
Guía rápida
De cero a un mensaje enviado.
Tres pasos.
- 1
Crea una clave
Ajustes, Claves de API, en un buzón que sea tuyo. Elige sus alcances y limita las direcciones desde las que puede enviar a dominios enteros o direcciones sueltas. El secreto se muestra una sola vez y lo que se guarda es un hash de un solo sentido.
GET /ping responde con los alcances de la clave y los alcances que le dejó su rol. export OPENEMAIL_API_KEY=oe_live_9f2c1a4b7e05d3862c1f0a44_kX7… curl https://api.openemail.uk/ping \ -H "Authorization: Bearer $OPENEMAIL_API_KEY" - 2
Instala el cliente
Un cliente de TypeScript sin dependencias, publicado como ESM y CommonJS, que lee la clave de OPENEMAIL_API_KEY. Sáltatelo si prefieres enviar el JSON tú mismo, porque cada endpoint es HTTP puro.
Node 18 en adelante, Workers, Deno, Bun y el navegador. bun add @openemail/sdk - 3
Envía
La respuesta lleva el id. GET /emails/{id} lo resuelve, /events tiene el rastro por destinatario y /tracking tiene las aperturas y los clics.
Un reintento que lleve la misma Idempotency-Key devuelve el primer resultado con 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)
Ausente
Lo que no hará
por ti todavía.
Cinco cosas que conviene saber antes de construir sobre esto, no después.
- Sin endpoint de subida
- Los adjuntos en línea van en base64 con un tope total de 5 MB. Un archivo más grande se envía nombrando por su id un archivo que ya está en el espacio de trabajo, que viaja como enlace de descarga.
- Los rebotes se quedan en el buzón
- Un informe de entrega se analiza, se empareja por Message-ID, se etiqueta en la conversación y se envía como un webhook email.bounced. Nada se escribe de vuelta en el registro de envío, así que a través de GET /emails un mensaje rebotado se sigue leyendo como enviado.
- El correo del redactor no está en GET /emails
- El correo enviado desde el redactor de la app no aparece en esa lista, porque el redactor no escribe por la misma ruta de envío.
- OAuth tiene consentimiento, no alcance
- Una solicitud se muestra antes de concederse y Aplicaciones conectadas la revoca, pero un token alcanza todo tu buzón y no solo la parte que pidió una aplicación.
- Sin flujo de publicación
- Publicar el cliente es una ejecución manual del preflight, la compilación y bun publish, así que una versión llega a npm cuando alguien la ejecuta y no cuando aterriza el cambio.
Verificar una entrega
Cada entrega va firmada,
y cada reintento lleva su id.
La firma es un HMAC-SHA-256 sobre la marca de tiempo, un punto y el cuerpo en bruto. Verifica contra los bytes tal como llegaron, porque analizarlos y volver a serializarlos reordena las claves y la rompe.
X-OpenEmail-Signature: t=1758240000,v1=9f0c4b2e7d1a86c3X-OpenEmail-Event: email.deliveredX-OpenEmail-Delivery: evt_4b7e05d3862c1f0a- Ventana de repetición
- 300 segundos, y aplicarla es tarea del receptor. El verificador del SDK la usa por defecto.
- Idempotency-Key
- Se reclama contra un índice único sobre la clave y tu clave de API juntas, así que un reintento tras un tiempo de espera agotado devuelve el primer resultado con Idempotency-Replayed: true en lugar de enviar dos veces.
- Reintentos
- Cinco intentos: en el momento del evento, y luego al minuto, a los 5, a los 25 y a las 2 horas. Solo se repite un tiempo de espera agotado, una conexión rechazada, un 408, 425, 429 o un 5xx.
- X-OpenEmail-Delivery
- El id del evento se acuña una vez y cada intento lo lleva, así que un receptor que vea dos veces el mismo id puede descartar el segundo en lugar de volver a actuar sobre él.
Para quién es
Un solo buzón.
Tres formas de entrar.
Una dirección gratuita en openemail.uk, con el cliente detrás.
El mismo buzón por API, por SDK y por MCP.
Crea una clave.
Envía algo.
Full API, MCP and SDK access en todos los planes. Free lleva 50 AI actions a day consigo.