API
Check an email from your app.
Send the raw email to POST /v1/check. The answer is a stream of JSON lines, one per check, sent as each check finishes. A verdict line arrives with the first check that decides, and again whenever a later check changes the verdict. The last line, done, has the final verdict.
Usage
1curl -sN --data-binary @message.eml "$MAILWEFT_API/v1/check?llm=off"Read the stream line by line in JavaScript:
1const response = await fetch(`${api}/v1/check?llm=auto`, { method: 'POST', body: raw });2const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();3let buffer = '';4for (;;) {5 const { value, done } = await reader.read();6 if (done) break;7 buffer += value;8 const lines = buffer.split('\n');9 buffer = lines.pop();10 for (const line of lines.filter(Boolean)) {11 const event = JSON.parse(line);12 if (event.event === 'verdict') show(event.verdict, event.reason); // first answer, then any change13 if (event.event === 'done') finish(event.verdict);14 }15}Request
| Part | Value |
|---|---|
| Body | The raw email, with headers. At most 1 MB. |
llm | auto (default) runs the judge when needed. always runs it on every email. off never runs it. |
The judge may run 30 times an hour for each address. Only runs count; a check where the judge is not needed does not. After that the judge is skipped and the judge line says why.
Events
Events arrive in this order. A verdict event can appear after any check that changes the verdict.
| Event | Fields |
|---|---|
parsed | subject, from, chars, auth (SPF, DKIM and DMARC results), links |
rules | flag, claimed (organisations the email claims to be), reasons |
b2 | score, logit, model_ms |
b3 | score, band, model, flag_at, safe_below, raises, lowers |
memory | matches, each with level, class, harmful, score, date, source, start and campaign; unavailable when the server has no memory |
b2_sentences | sentences, each with the text and the score drop when it is removed |
judge | ran, verdict, confidence, reason, quotes, quotes_verified, model_ms, or skipped with the reason |
verdict | verdict (phishing, unsure or safe), by (the check that decided), reason, first |
done | The final verdict |
Every event except error has ms, the time since the request arrived on the server.
Errors
| Status | Message |
|---|---|
| 400 | Empty email. Paste an email or open a sample. |
| 413 | Email is larger than 1 MB. Remove attachments and try again. |
An error during a check arrives as an error event in the stream.
Health
GET /v1/health returns the loaded models, the number of memory entries, and whether the judge is configured.