Skip to the documentation
API

Preview a translation

What `translate` on a send would produce, with nothing sent and nothing stored.

POSTapi.openemail.uk/emails/translate

Runs the real call against your workspace, with your own key.

POST /emails/translate

What translate on a send would produce, with nothing sent and nothing stored.

The request

The same three options a send resolves, minus the envelope, run through the same function the send path calls. That identity is the whole value of the endpoint: a preview with its own code would be a promise we do not keep, and the day the two drifted, the thing on somebody’s screen and the thing in the recipient’s inbox would differ with nothing to say so.

Parameters

tostringrequired
The language to write in. A BCP-47 code (`de`), an English name ("German") or the language’s own name ("Deutsch"). The response tells you which code it resolved to, and that is the form to store if you are keeping a language per contact.
htmlstring
The HTML body, up to a megabyte. One of html, text or subject is required.
textstring
The plain-text part. Translated independently of `html`, with its own length check.
subjectstring
The subject LINE: a string, not the boolean it is under `translate` on a send. The two are different questions: there you are saying whether to translate a subject we already hold, here you are handing one over.
fromstring
What you wrote it in, in any of the same three forms. Stating it skips the detection call.
includeOriginalboolean
Whether the returned `html` already carries your original beneath the translation. Defaults to true.

Unknown keys are a 422, as everywhere else. A request with none of html, text or subject is a 422 on html: "One of html, text or subject is required".

Preview it

The round trip the composer makes before showing somebody what they are about to send.

curl
curl -X POST "$OE/emails/translate" -H "$AUTH" -H "Content-Type: application/json" \  -d '{    "subject": "Your September invoice",    "html": "<p>Invoice attached. Payment is due on the 14th.</p>",    "to": "de"  }'
Response
{  "object": "translation",  "language": { "code": "de", "label": "German", "native": "Deutsch", "flag": "🇩🇪", "rtl": false },  "detectedSourceLanguage": {    "code": "en", "label": "English", "native": "English", "flag": "🇬🇧", "rtl": false  },  "subject": "Ihre Rechnung für September",  "html": "<p>Rechnung im Anhang. Zahlbar bis zum 14.</p>\n<div style=\"margin:28px 0 0;padding:14px 0 0;border-top:1px solid #d6dae0\">\n<div style=\"margin:0 0 10px;font-size:12px;line-height:1.5;color:#6b7280\">Ursprüngliche Nachricht (English)</div>\n<div><p>Invoice attached. Payment is due on the 14th.</p></div>\n</div>",  "text": null,  "includeOriginal": true}

html, text and subject come back null rather than absent for a field you did not send, so a client can render the answer without remembering what it asked.

detectedSourceLanguage is null when detection abstained. That is a real answer and not a failure. A body of names, numbers and links gives it nothing to read, and the only consequence is that your original is captioned without a language.

includeOriginal is echoed because it changes what html contains. With it on the body already carries your original beneath the translation, and appending your own copy sends it twice.

Preview, edit, send

The shape this is built for is preview, EDIT, send: show a person the translation, let them change it, then send what they approved as an ordinary html and subject with no translate on the request at all. What they approved is then word for word what leaves.

curl
curl -X POST "$OE/emails" -H "$AUTH" -H "Content-Type: application/json" \  -d '{    "from": "[email protected]",    "to": ["[email protected]"],    "subject": "Ihre Rechnung für September",    "html": "<p>Rechnung im Anhang. Zahlbar bis zum 14.</p>"  }'

Sending with translate after previewing translates a second time and throws the edits away. The send would go out in wording nobody has read, which is the one failure the preview exists to prevent.

What it costs, and what it does not do

  • Three model calls (the body, the subject, and one to work out what you wrote in) issued together, so the wait is the longest of the three rather than their sum. Stating from drops the third. It is the same cost as sending with translate, so preview once rather than per revision.
  • Nothing is sent, no row is written, and no id comes back. There is nothing here to cancel or retrieve later.
  • It translates and does nothing else. It does not proofread, it does not improve the writing, and it never answers the message.
  • Names, companies, links, order numbers, prices and dates come back as they went in, so the translation can be checked against the original line by line.
  • Quoted history is not stripped, unlike the reading half. What you hand over is what is translated, which is right for a composer, where the body is only what somebody just wrote, and worth knowing if you post a whole reply chain.
  • Scoped emails:send, with no scope of its own: it grants nothing a sender could not already do, and a scope nobody can tell apart from emails:send on a consent screen makes every other scope on that list mean slightly less.

The body is capped at the same megabyte a send allows, but translation itself refuses anything over 30,000 characters with translation_too_long. The failure codes are the ones a translated send returns, listed under Send an email.