Send mail
POST /members/send sends one email in a project. The effective principal
needs active project membership and mail.send. Use the
production base and JSON request format with a Bearer access
token and, when needed, an organization selection.
Request fields
| Field | Type | Required/default | Meaning |
|---|---|---|---|
project_id |
UUID string | Required for normal requests | Project returned by project creation or listing. |
method |
string | Defaults to email |
email or blank uses email; other delivery methods fail with 400. |
sender_email |
string | Required | From email address; alias from_email. |
recipient_email |
string | Required | One recipient email address; alias to_email. |
sender_name |
string or null | Optional | From display name; alias from_name. Blank/omitted uses the service's configured display name when available. |
recipient_name |
string or null | Optional | Recipient display name; alias to_name. |
reply_to_email |
string or null | Optional | Reply-To address. |
subject |
string | Defaults to an empty string | Subject line. |
body_text |
string or null | At least one nonblank body | Plain text; alias body. |
body_html |
string or null | At least one nonblank body | HTML; when supplied alone, a plain-text alternative is derived. |
Use canonical fields consistently. Email addresses are trimmed, validated, and lowercased. Display names and subject are trimmed and must not contain CR/LF characters. Body line endings normalize to LF; wholly blank bodies are treated as absent. Supplying both text and HTML creates alternatives. Sender and Reply-To fields describe the message; they do not select its owner or grant sending authority.
{
"project_id":"<project-uuid>",
"sender_email":"sender@example.com",
"sender_name":"Example App",
"recipient_email":"recipient@example.com",
"subject":"Your receipt",
"body_text":"Thank you for your order."
}
Normal callers must provide project_id. A machine deployment may have a
server-configured default project; omission works only for an app principal
with that configuration. The default does not grant membership or
mail.send. Include the explicit project ID in portable integrations.
The service sets the owner, actor, and source. Caller-supplied owner,
actor, owner_scope, organization_id, and client_id fail with 400.
Use only documented message and workspace fields.
Queue response and logging
A successful response has status: 1, comment: "OK", and these data fields:
| Field | Meaning |
|---|---|
success |
true when accepted by the mail transport. |
method, provider, transport |
email, postfix, and sendmail. |
status, queued |
queued and true; no recipient-delivery confirmation. |
logged |
Whether an outbound-attempt record was stored. |
item |
Stored log record when available; otherwise an empty object/array. |
message_id |
Composed message identifier, or null. |
log_error |
null when logging succeeded; error detail when logging failed. |
{
"status":1,
"comment":"OK",
"data":{
"success":true,"method":"email","provider":"postfix",
"transport":"sendmail","status":"queued","queued":true,
"logged":false,"item":[],"message_id":"<message-id>",
"log_error":"<logging-error>"
}
}
Transport failure returns an error and attempts to store a failed record.
A message can be accepted even if logging fails; logged: false is not a send
failure. Keep queue acceptance and log persistence as separate outcomes.
Retry handling
The API does not provide an idempotency key or deduplication guarantee. A timeout or connection loss may occur after transport acceptance. A repeated send can produce another message. Reconcile with your application state and project logs before deciding to resend; absence of a log alone cannot prove the message was not queued.