Invoke AI transformers with MailSlurp
Documentation navigation
Invoke MailSlurp AI transformers from code to extract structured fields from email, SMS, attachments, images, and documents with prompts and schemas.
You can call AI transformations on emails, attachments, SMS or any content directly from code and tests.
Invocation options
Choose the input type that matches your workflow:
- Email-centric workflows: invoke on received email content from your inboxes.
- Attachment-centric workflows: invoke on uploaded files or email attachments.
- SMS-centric workflows: invoke on inbound SMS where structured extraction is needed.
- Generic text workflows: invoke on arbitrary content when you already have the payload in your application.
Recommended flow
- Define your schema and extraction intent in AI transformers.
- Validate output fields in output schemas before production use.
- Invoke the transformation from your test or application flow.
- Route results to dashboard review, API retrieval, or webhooks.
- Iterate on prompt/schema design using real examples from failed or partial extractions.
Practical guidance
- Start with a narrow schema (fewer required fields) and expand once extraction is stable.
- Prefer deterministic field names and explicit formats for dates, currency, and identifiers.
- Keep transformer definitions close to the business process that consumes the results.
Next pages
Invoke a saved transformer on an attachment
Create the transform using the invoice example, then pass its ID and the selected attachment ID. This uses the same REST api helper as attachment extraction.
async function invokeInvoiceTransformer(api, transformId, attachmentId) {
const invocation = await api('/ai/transformer/invoke', {
method: 'POST',
body: {
aiTransformId: transformId,
entityType: 'ATTACHMENT',
entityId: attachmentId,
saveResults: true,
},
});
if (!invocation.conditionsMatch) throw new Error('Transformer conditions did not match');
if (!invocation.result) throw new Error('Transformer returned no invoice data');
return invocation;
}
Call invokeInvoiceTransformer(api, transform.id, attachmentId). saveResults: true retains the result for later retrieval. The response contains conditionsMatch, result and tokenCount; it is different from the successful and evidence fields on message-testing AI endpoints.
/ai/transformer/invoke
Invoke a transformer
Execute an AI transformer to generate structured content
Request, parameters, and responses
Request body (required)
| Field | Type | Required | Description |
|---|---|---|---|
aiTransformId | string:uuid | No | |
aiTransformMappingId | string:uuid | No | |
rawInput | string | No | |
entityId | string | No | |
entityType | enum: EMAIL | SMS | ATTACHMENT | No | Values: EMAIL, SMS, ATTACHMENT |
rawConditions | string[] | No | |
rawInstructions | string[] | No | |
rawOutputSchema | StructuredOutputSchema | No | |
contentSelector | enum: RAW | BODY | BODY_ATTACHMENTS | No | Values: RAW, BODY, BODY_ATTACHMENTS |
saveResults | boolean | No |
{
"aiTransformId": "00000000-0000-4000-8000-000000000000",
"aiTransformMappingId": "00000000-0000-4000-8000-000000000000",
"rawInput": "value",
"entityId": "00000000-0000-4000-8000-000000000000",
"entityType": "EMAIL",
"rawConditions": [
"value"
]
}
Responses
| Status | Schema | Description |
|---|---|---|
200 | ConditionalStructuredContentResult | OK |
HTTP examples
HTTP
POST /ai/transformer/invoke HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
{}
cURL
Requires cURL 7.76+ and a POSIX shell. Tested with cURL 8.12.1.
(
set -eu
response_file=$(mktemp)
request_body=$(mktemp)
trap 'rm -f "$response_file" "$request_body"' EXIT
{
printf '%b' '{}'
} > "$request_body"
status=$(curl --silent --show-error \
--request POST \
--url 'https://api.mailslurp.com/ai/transformer/invoke' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--output "$response_file" \
--write-out '%{http_code}' \
--data-binary "@$request_body")
case "$status" in
2??) mv "$response_file" 'response.bin' ;;
*) printf 'HTTP %s\n' "$status" >&2; cat "$response_file" >&2; exit 1 ;;
esac
)
JavaScript (HTTP)
Requires Node.js 22+. Tested with Node.js 22.14.0.
import { writeFile } from "node:fs/promises";
const body = Buffer.concat([
Buffer.from("{}", "utf8")
]);
const response = await fetch("https://api.mailslurp.com/ai/transformer/invoke", {
method: "POST",
headers: {
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
"Accept": "*/*"
},
body,
redirect: "manual",
signal: AbortSignal.timeout(60000),
});
const responseBytes = Buffer.from(await response.arrayBuffer());
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${responseBytes.toString("utf8")}`);
}
await writeFile("response.bin", responseBytes);
Python (HTTP)
Requires Python 3.9+. Tested with Python 3.9.21.
import http.client
from pathlib import Path
from urllib.parse import urlsplit
url = urlsplit("https://api.mailslurp.com/ai/transformer/invoke")
headers = {
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
"Accept": "*/*"
}
body = b"".join([
"{}".encode("utf-8")
])
connection_class = http.client.HTTPSConnection if url.scheme == "https" else http.client.HTTPConnection
connection = connection_class(url.hostname, url.port, timeout=60)
try:
path = (url.path or "/") + ("?" + url.query if url.query else "")
connection.request("POST", path, body=body, headers=headers)
response = connection.getresponse()
response_bytes = response.read()
if not 200 <= response.status < 300:
raise RuntimeError(f"HTTP {response.status}: {response_bytes.decode('utf-8', errors='replace')}")
Path("response.bin").write_bytes(response_bytes)
finally:
connection.close()
Choose a source and replay a sample
For a stored message, set entityType to EMAIL or SMS and use its ID as entityId. For an attachment, use ATTACHMENT. For application-owned text, provide rawInput instead of a stored entity. Choose only the source needed for the invocation and follow the request schema for optional selectors.
When changing instructions or a schema, invoke the new transform against the same known samples. Compare expected fields in your tests, including a sample that lacks a required value and a sample that should fail the conditions. Preserve the source IDs and transform version in your own test record.
A replay is another invocation and can create another saved result. Make downstream writes idempotent and send reviewed results onward deliberately; replaying extraction should not silently duplicate a CRM entry or invoice. See results.
Running this code needs an API key. Get one free