Ves a la documentació
API

Enviar un correu

POST /emails: un missatge, ara o més tard.

POSTapi.openemail.uk/emails

Executa la crida real contra el teu espai de treball, amb la teva pròpia clau.

La petició

from és obligatori. A diferència del redactor, no hi ha cap remitent de reserva, perquè aquesta reserva és l'adreça per defecte de l'espai de treball i canvia de manera invisible a mesura que les adreces van i venen.

CampObligatoriNotes
fromUna adreça sola o Name <addr>. Ha de ser una des de la qual la clau pugui enviar.
toFins a 50 destinataris entre to, cc i bcc en conjunt.
cc, bccnoEls destinataris de bcc no s'anomenen mai en els bytes que rep ningú altre.
subjectnoPer defecte és buit.
html, textun d'aquestsTots dos alhora també val. L'HTML és el que veuen els destinataris.
templateun d'aquests{ id, version?, props?, slots? }. Un cos emmagatzemat, per id o per slug. Es rebutja juntament amb html, text o draftId. Vegeu Enviar amb una plantilla.
replyTonoUna sola adreça.
headersnoX-*, List-*, Reply-To, Precedence, Auto-Submitted, Importance, Priority, Feedback-Id.
attachmentsno{ filename, content, contentType } en base64, 5 MB en total, o { fileId } que anomeni un fitxer que ja és a l'espai de treball. 20 fitxers.
attachmentDeliverynomime, link o auto. auto enllaça els fitxers quan superen els 2 MB en un domini amb un domini de fitxers actiu. Per defecte, la configuració de la bústia.
threadIdnoRespondre dins d'un fil existent.
draftIdnoEnviar un esborrany existent.
scheduledAtnoInstant ISO o durada. Vegeu Programació.
cancellableForSecondsnoUna finestra per desfer de 0 a 900 segons en un enviament immediat. Es rebutja juntament amb scheduledAt, que es pot cancel·lar fins que s'envia. Vegeu Programació.
signaturenofalse deixa la signatura fora d'aquest missatge. Altrament, porta la signatura de l'adreça des de la qual s'envia, que és la pròpia d'aquesta adreça o bé la que s'ha definit per a Totes les adreces.
tagsnoFins a 10 etiquetes vostres. Es retornen tal qual, mai no s'interpreten.
trackingno{ opens?, clicks? }. Qualsevol dels dos anul·la la configuració per a aquest missatge; si ometeu un camp, aquella meitat recau en la configuració de l'adreça des de la qual s'envia, o bé en la de Totes les adreces, i està activada tret que alguna d'aquestes l'hagi desactivada.
translateno{ to, from?, subject?, includeOriginal? }. L'envia en la llengua del destinatari. Es resol quan s'accepta la petició, i es rebutja juntament amb draftId.

Els camps desconeguts es rebutgen en lloc d'ignorar-se, de manera que un nom mal escrit és un 422 ara i no una sorpresa més endavant. Les capçaleres que anul·larien l'autorització del remitent (From, Sender, Bcc, Message-ID, Return-Path i d'altres) es rebutgen amb reserved_header.

La resposta

200 quan el missatge ja ha sortit, 202 quan encara li ha de passar alguna cosa. Qui ramifiqui segons el codi d'estat encerta en tots dos casos.

200 OK
{  "object": "email",  "id": "msg_c5f21cc6bfec4e848caf905b",  "status": "sent",  "mode": "live",  "from": "[email protected]",  "subject": "Your September invoice",  "messageId": "<2598…@acme.com>",  "transport": "ses",  "sentAt": "2026-08-29T08:19:08.000Z",  "source": "api",  "replayed": false}

id és l'identificador durador que conserveu, i el que porta un esdeveniment de lliurament quan torna, ja que un webhook de rebot l'anomena emailId. messageId és el Message-ID de RFC 5322 i és null fins que existeix el MIME. No hi correlacioneu res: el servei d'enviament reescriu aquesta capçalera a la sortida, de manera que el valor d'aquí no apareix en cap informe de rebot ni de lliurament i una coincidència per aquest camp no salta mai.

En la llengua del destinatari

translate escriu el missatge en la llengua d'una altra persona abans que surti. El cos, i l'assumpte si no ho desactiveu, es tradueixen en el moment en què s'ACCEPTA la petició, que és la mateixa regla que segueix template i és determinant pels mateixos motius: un missatge programat porta les paraules que es van aprovar i no el que un model produeixi el dimarts, i una traducció que no s'hagi pogut produir rebutja l'enviament abans que existeixi cap fila. No s'entrega res en una llengua que el seu remitent no hagi triat.

translate

tostringobligatori
La llengua en què cal escriure: un codi BCP-47 (`de`), un nom en anglès ("German") o el nom propi de la llengua ("Deutsch"), de 2 a 60 caràcters. Tots tres es normalitzen al codi de la taula abans de res, de manera que són una sola petició, cosa que importa perquè l'empremta de la Idempotency-Key es pren sobre la petició analitzada. Els àlies també es resolen: `zh-TW` esdevé `zh-Hant`. Un que no es resolgui a res és un 422 a `translate.to`.
fromstring
En quina llengua l'heu escrit, en qualsevol de les tres mateixes formes. És purament una optimització. Si l'ometeu, es llegeix el cos i se'n dedueix la llengua, cosa que costa una crida curta al model. Val la pena indicar-la en una ruta d'alt volum, i val la pena indicar-la quan el cos són sobretot noms, números i enllaços: la detecció s'absté en lloc d'endevinar, i un origen indeterminat no us costa res més que la llengua esmentada al rètol que encapçala el vostre original. No és el `from` de primer nivell, que és una adreça.
subjectboolean
Traduir també la línia de l'assumpte. Per defecte és true; amb false s'envia l'assumpte exactament tal com l'heu escrit.
includeOriginalboolean
Posar el que heu escrit realment sota la traducció, darrere d'un separador i amb un rètol en la llengua del destinatari. Per defecte és true, i val la pena deixar-ho activat. És l'única cosa que permet a qui llegeix comprovar una frase que li sona estranya, en lloc d'haver de confiar en un model la sortida del qual no podeu veure cap dels dos.
curl
curl -X POST "$OE/emails" -H "$AUTH" -H "Content-Type: application/json" \  -d '{    "from": "[email protected]",    "to": ["[email protected]"],    "subject": "Your September invoice",    "html": "<p>Invoice attached. Payment is due on the 14th.</p>",    "translate": { "to": "de" }  }'
200 OK
{  "object": "email",  "id": "msg_c5f21cc6bfec4e848caf905b",  "status": "sent",  "from": "[email protected]",  "subject": "Ihre Rechnung für September",  "translation": {    "language": "de",    "languageName": "German",    "detectedSourceLanguage": "en",    "subject": true,    "includeOriginal": true  }}

translation és additiu i només apareix en un missatge que s'ha traduït: en aquesta resposta i a GET /emails/{id}, mai en una fila de llista, perquè una llista no recupera la petició emmagatzemada i el seu silenci allà no diu res en cap sentit. Porta codis i no files de llengua senceres: és un registre del que s'ha fet, i GET /languages és on viu l'endònim. El subject de la resposta és el traduït, de manera que cap consola no llista mai un missatge sota una cadena que el destinatari no ha vist mai.

  • Funciona amb template, i aquest és el cas útil: el que es tradueix és la sortida RENDERITZADA, de manera que un sol cos emmagatzemat serveix per a totes les llengües en què llegeixen els vostres clients. Una plantilla que renderitza un document sencer es desmunta primer: només el que hi ha dins de <body> arriba al model, i el doctype, els blocs <style> i les regles @font-face es tornen a posar al voltant de la resposta. També és el motiu pel qual el límit de 30.000 caràcters mesura la prosa i no el document: un missatge de dues línies embolcallat en un full d'estil de marca continua sent un missatge de dues línies.
  • L'única part d'una plantilla que es deixa sense traduir és el seu <title>, que cap client de correu no mostra. Un <Preview> de react-email es renderitza dins del cos i es tradueix amb la resta.
  • Es rebutja amb draftId: un 422 a translate, que diu "A draft is sent as it was written; translate a body or send a draft, not both". Un esborrany l'ha escrit una persona i s'envia tal com l'ha deixat.
  • Deliberadament no forma part de l'empremta d'idempotència. El que es passa per hash és la petició que heu enviat, translate inclòs; el que ha produït el model, no. Així, reintentar un enviament sense resposta amb la mateixa Idempotency-Key reprodueix l'original. Torna el missatge que ja existeix, sense cap segon enviament ni cap segona traducció. Fer el hash de la redacció faria que un reintent honest tingués una empremta diferent cada vegada, que és com el mateix missatge acaba sortint dues vegades.
  • Un missatge traduït que està en cua o programat queda congelat davant de canvis de redacció. Moveu-lo o cancel·leu-lo; alterar el que diu vol dir cancel·lar-lo i tornar-lo a enviar, davant d'algú que pugui llegir les paraules noves.
  • Una llengua de destinació de dreta a esquerra es produeix de dreta a esquerra: la traducció embolcallada en dir="rtl", i el vostre original a sota, orientat pel seu compte. L'atribut sobreviu al sanejador de sortida, que permet dir exactament per aquest motiu, de manera que el missatge que surt per la xarxa porta la direcció que mostrava la previsualització.
CodiEstatQuan
`invalid_parameter`422translate.to o translate.from no anomena cap llengua que puguem situar. El missatge indica quines tres formes s'accepten i assenyala GET /languages.
`unknown_language`422La mateixa fallada detectada un pas més tard, pel servei en lloc de l'esquema. Una xarxa de seguretat, a translate.to.
`translation_too_long`422Més de 30.000 caràcters a qualsevol dels dos extrems de la crida al model. Un rebuig en lloc d'un truncament: mig missatge traduït no té cap costura que mostri on s'ha aturat, i qui el llegeix actua sobre la meitat que ha rebut.
`translation_not_configured`409L'espai de treball no té cap clau d'IA i la IA de la plataforma està desactivada. Un 409 en lloc d'un 503 perquè el reintent falla igual. No s'ha enviat res. Envieu sense translate si volíeu enviar-lo tal com estava escrit.
`translation_failed`503El proveïdor no ha respost, o ha respost amb res d'aprofitable. No s'ha enviat res; el missatge no s'envia mai sense traduir com a alternativa. Aquest és nostre i val la pena reintentar-lo.
`unknown_parameter`422Una clau no reconeguda dins de translate, que és un objecte estricte com la resta de la petició.

Un enviament des de codi no té ningú que llegeixi la traducció abans. POST /emails/translate és el mateix viatge d'anada i tornada aturat un pas abans, per ensenyar a una persona què està a punt d'enviar. Després envieu el que hagi aprovat com un html/subject normal, sense cap translate a la petició.