curl --request POST \
--url https://api.dairo.app/v1/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"inboxId": "<string>",
"to": "jsmith@example.com",
"text": "<string>",
"cc": "jsmith@example.com",
"bcc": "jsmith@example.com",
"subject": "",
"html": "<string>",
"idempotencyKey": "<string>",
"attachments": [
{
"filename": "<string>",
"contentBase64": "<string>",
"contentType": "application/pdf",
"objectId": "<string>",
"delivery": "attachment"
}
],
"sendAt": "2023-11-07T05:31:56Z",
"replyTo": "jsmith@example.com",
"headers": {},
"tags": {},
"ignoreComplaints": false,
"contactId": "<string>",
"buttons": [
[
{
"text": "<string>",
"url": "<string>",
"callback": "<string>",
"feedback": "<string>",
"alert": true
}
]
],
"dryRun": false
}
'import requests
url = "https://api.dairo.app/v1/messages"
payload = {
"inboxId": "<string>",
"to": "jsmith@example.com",
"text": "<string>",
"cc": "jsmith@example.com",
"bcc": "jsmith@example.com",
"subject": "",
"html": "<string>",
"idempotencyKey": "<string>",
"attachments": [
{
"filename": "<string>",
"contentBase64": "<string>",
"contentType": "application/pdf",
"objectId": "<string>",
"delivery": "attachment"
}
],
"sendAt": "2023-11-07T05:31:56Z",
"replyTo": "jsmith@example.com",
"headers": {},
"tags": {},
"ignoreComplaints": False,
"contactId": "<string>",
"buttons": [[
{
"text": "<string>",
"url": "<string>",
"callback": "<string>",
"feedback": "<string>",
"alert": True
}
]],
"dryRun": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
inboxId: '<string>',
to: 'jsmith@example.com',
text: '<string>',
cc: 'jsmith@example.com',
bcc: 'jsmith@example.com',
subject: '',
html: '<string>',
idempotencyKey: '<string>',
attachments: [
{
filename: '<string>',
contentBase64: '<string>',
contentType: 'application/pdf',
objectId: '<string>',
delivery: 'attachment'
}
],
sendAt: '2023-11-07T05:31:56Z',
replyTo: 'jsmith@example.com',
headers: {},
tags: {},
ignoreComplaints: false,
contactId: '<string>',
buttons: [
[
{
text: '<string>',
url: '<string>',
callback: '<string>',
feedback: '<string>',
alert: true
}
]
],
dryRun: false
})
};
fetch('https://api.dairo.app/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dairo.app/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'inboxId' => '<string>',
'to' => 'jsmith@example.com',
'text' => '<string>',
'cc' => 'jsmith@example.com',
'bcc' => 'jsmith@example.com',
'subject' => '',
'html' => '<string>',
'idempotencyKey' => '<string>',
'attachments' => [
[
'filename' => '<string>',
'contentBase64' => '<string>',
'contentType' => 'application/pdf',
'objectId' => '<string>',
'delivery' => 'attachment'
]
],
'sendAt' => '2023-11-07T05:31:56Z',
'replyTo' => 'jsmith@example.com',
'headers' => [
],
'tags' => [
],
'ignoreComplaints' => false,
'contactId' => '<string>',
'buttons' => [
[
[
'text' => '<string>',
'url' => '<string>',
'callback' => '<string>',
'feedback' => '<string>',
'alert' => true
]
]
],
'dryRun' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.dairo.app/v1/messages"
payload := strings.NewReader("{\n \"inboxId\": \"<string>\",\n \"to\": \"jsmith@example.com\",\n \"text\": \"<string>\",\n \"cc\": \"jsmith@example.com\",\n \"bcc\": \"jsmith@example.com\",\n \"subject\": \"\",\n \"html\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"attachments\": [\n {\n \"filename\": \"<string>\",\n \"contentBase64\": \"<string>\",\n \"contentType\": \"application/pdf\",\n \"objectId\": \"<string>\",\n \"delivery\": \"attachment\"\n }\n ],\n \"sendAt\": \"2023-11-07T05:31:56Z\",\n \"replyTo\": \"jsmith@example.com\",\n \"headers\": {},\n \"tags\": {},\n \"ignoreComplaints\": false,\n \"contactId\": \"<string>\",\n \"buttons\": [\n [\n {\n \"text\": \"<string>\",\n \"url\": \"<string>\",\n \"callback\": \"<string>\",\n \"feedback\": \"<string>\",\n \"alert\": true\n }\n ]\n ],\n \"dryRun\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.dairo.app/v1/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"inboxId\": \"<string>\",\n \"to\": \"jsmith@example.com\",\n \"text\": \"<string>\",\n \"cc\": \"jsmith@example.com\",\n \"bcc\": \"jsmith@example.com\",\n \"subject\": \"\",\n \"html\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"attachments\": [\n {\n \"filename\": \"<string>\",\n \"contentBase64\": \"<string>\",\n \"contentType\": \"application/pdf\",\n \"objectId\": \"<string>\",\n \"delivery\": \"attachment\"\n }\n ],\n \"sendAt\": \"2023-11-07T05:31:56Z\",\n \"replyTo\": \"jsmith@example.com\",\n \"headers\": {},\n \"tags\": {},\n \"ignoreComplaints\": false,\n \"contactId\": \"<string>\",\n \"buttons\": [\n [\n {\n \"text\": \"<string>\",\n \"url\": \"<string>\",\n \"callback\": \"<string>\",\n \"feedback\": \"<string>\",\n \"alert\": true\n }\n ]\n ],\n \"dryRun\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dairo.app/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"inboxId\": \"<string>\",\n \"to\": \"jsmith@example.com\",\n \"text\": \"<string>\",\n \"cc\": \"jsmith@example.com\",\n \"bcc\": \"jsmith@example.com\",\n \"subject\": \"\",\n \"html\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"attachments\": [\n {\n \"filename\": \"<string>\",\n \"contentBase64\": \"<string>\",\n \"contentType\": \"application/pdf\",\n \"objectId\": \"<string>\",\n \"delivery\": \"attachment\"\n }\n ],\n \"sendAt\": \"2023-11-07T05:31:56Z\",\n \"replyTo\": \"jsmith@example.com\",\n \"headers\": {},\n \"tags\": {},\n \"ignoreComplaints\": false,\n \"contactId\": \"<string>\",\n \"buttons\": [\n [\n {\n \"text\": \"<string>\",\n \"url\": \"<string>\",\n \"callback\": \"<string>\",\n \"feedback\": \"<string>\",\n \"alert\": true\n }\n ]\n ],\n \"dryRun\": false\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "sent",
"warnings": [
{
"recipient": "jsmith@example.com",
"reason": "complaint",
"message": "Recipient previously complained; do not contact again unless you are sure.",
"sourceMessageId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"providerMessageId": "<string>",
"complaintFeedbackType": "<string>",
"complaintUserAgent": "<string>",
"lastEventAt": "2023-11-07T05:31:56Z"
}
],
"providerMessageId": "<string>",
"error": "<string>",
"channel": "email",
"channelMetadata": {},
"scheduledAt": "2023-11-07T05:31:56Z"
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}Send a message from a Dairo inbox
Send a message from a Dairo inbox
curl --request POST \
--url https://api.dairo.app/v1/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"inboxId": "<string>",
"to": "jsmith@example.com",
"text": "<string>",
"cc": "jsmith@example.com",
"bcc": "jsmith@example.com",
"subject": "",
"html": "<string>",
"idempotencyKey": "<string>",
"attachments": [
{
"filename": "<string>",
"contentBase64": "<string>",
"contentType": "application/pdf",
"objectId": "<string>",
"delivery": "attachment"
}
],
"sendAt": "2023-11-07T05:31:56Z",
"replyTo": "jsmith@example.com",
"headers": {},
"tags": {},
"ignoreComplaints": false,
"contactId": "<string>",
"buttons": [
[
{
"text": "<string>",
"url": "<string>",
"callback": "<string>",
"feedback": "<string>",
"alert": true
}
]
],
"dryRun": false
}
'import requests
url = "https://api.dairo.app/v1/messages"
payload = {
"inboxId": "<string>",
"to": "jsmith@example.com",
"text": "<string>",
"cc": "jsmith@example.com",
"bcc": "jsmith@example.com",
"subject": "",
"html": "<string>",
"idempotencyKey": "<string>",
"attachments": [
{
"filename": "<string>",
"contentBase64": "<string>",
"contentType": "application/pdf",
"objectId": "<string>",
"delivery": "attachment"
}
],
"sendAt": "2023-11-07T05:31:56Z",
"replyTo": "jsmith@example.com",
"headers": {},
"tags": {},
"ignoreComplaints": False,
"contactId": "<string>",
"buttons": [[
{
"text": "<string>",
"url": "<string>",
"callback": "<string>",
"feedback": "<string>",
"alert": True
}
]],
"dryRun": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
inboxId: '<string>',
to: 'jsmith@example.com',
text: '<string>',
cc: 'jsmith@example.com',
bcc: 'jsmith@example.com',
subject: '',
html: '<string>',
idempotencyKey: '<string>',
attachments: [
{
filename: '<string>',
contentBase64: '<string>',
contentType: 'application/pdf',
objectId: '<string>',
delivery: 'attachment'
}
],
sendAt: '2023-11-07T05:31:56Z',
replyTo: 'jsmith@example.com',
headers: {},
tags: {},
ignoreComplaints: false,
contactId: '<string>',
buttons: [
[
{
text: '<string>',
url: '<string>',
callback: '<string>',
feedback: '<string>',
alert: true
}
]
],
dryRun: false
})
};
fetch('https://api.dairo.app/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dairo.app/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'inboxId' => '<string>',
'to' => 'jsmith@example.com',
'text' => '<string>',
'cc' => 'jsmith@example.com',
'bcc' => 'jsmith@example.com',
'subject' => '',
'html' => '<string>',
'idempotencyKey' => '<string>',
'attachments' => [
[
'filename' => '<string>',
'contentBase64' => '<string>',
'contentType' => 'application/pdf',
'objectId' => '<string>',
'delivery' => 'attachment'
]
],
'sendAt' => '2023-11-07T05:31:56Z',
'replyTo' => 'jsmith@example.com',
'headers' => [
],
'tags' => [
],
'ignoreComplaints' => false,
'contactId' => '<string>',
'buttons' => [
[
[
'text' => '<string>',
'url' => '<string>',
'callback' => '<string>',
'feedback' => '<string>',
'alert' => true
]
]
],
'dryRun' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.dairo.app/v1/messages"
payload := strings.NewReader("{\n \"inboxId\": \"<string>\",\n \"to\": \"jsmith@example.com\",\n \"text\": \"<string>\",\n \"cc\": \"jsmith@example.com\",\n \"bcc\": \"jsmith@example.com\",\n \"subject\": \"\",\n \"html\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"attachments\": [\n {\n \"filename\": \"<string>\",\n \"contentBase64\": \"<string>\",\n \"contentType\": \"application/pdf\",\n \"objectId\": \"<string>\",\n \"delivery\": \"attachment\"\n }\n ],\n \"sendAt\": \"2023-11-07T05:31:56Z\",\n \"replyTo\": \"jsmith@example.com\",\n \"headers\": {},\n \"tags\": {},\n \"ignoreComplaints\": false,\n \"contactId\": \"<string>\",\n \"buttons\": [\n [\n {\n \"text\": \"<string>\",\n \"url\": \"<string>\",\n \"callback\": \"<string>\",\n \"feedback\": \"<string>\",\n \"alert\": true\n }\n ]\n ],\n \"dryRun\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.dairo.app/v1/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"inboxId\": \"<string>\",\n \"to\": \"jsmith@example.com\",\n \"text\": \"<string>\",\n \"cc\": \"jsmith@example.com\",\n \"bcc\": \"jsmith@example.com\",\n \"subject\": \"\",\n \"html\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"attachments\": [\n {\n \"filename\": \"<string>\",\n \"contentBase64\": \"<string>\",\n \"contentType\": \"application/pdf\",\n \"objectId\": \"<string>\",\n \"delivery\": \"attachment\"\n }\n ],\n \"sendAt\": \"2023-11-07T05:31:56Z\",\n \"replyTo\": \"jsmith@example.com\",\n \"headers\": {},\n \"tags\": {},\n \"ignoreComplaints\": false,\n \"contactId\": \"<string>\",\n \"buttons\": [\n [\n {\n \"text\": \"<string>\",\n \"url\": \"<string>\",\n \"callback\": \"<string>\",\n \"feedback\": \"<string>\",\n \"alert\": true\n }\n ]\n ],\n \"dryRun\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dairo.app/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"inboxId\": \"<string>\",\n \"to\": \"jsmith@example.com\",\n \"text\": \"<string>\",\n \"cc\": \"jsmith@example.com\",\n \"bcc\": \"jsmith@example.com\",\n \"subject\": \"\",\n \"html\": \"<string>\",\n \"idempotencyKey\": \"<string>\",\n \"attachments\": [\n {\n \"filename\": \"<string>\",\n \"contentBase64\": \"<string>\",\n \"contentType\": \"application/pdf\",\n \"objectId\": \"<string>\",\n \"delivery\": \"attachment\"\n }\n ],\n \"sendAt\": \"2023-11-07T05:31:56Z\",\n \"replyTo\": \"jsmith@example.com\",\n \"headers\": {},\n \"tags\": {},\n \"ignoreComplaints\": false,\n \"contactId\": \"<string>\",\n \"buttons\": [\n [\n {\n \"text\": \"<string>\",\n \"url\": \"<string>\",\n \"callback\": \"<string>\",\n \"feedback\": \"<string>\",\n \"alert\": true\n }\n ]\n ],\n \"dryRun\": false\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "sent",
"warnings": [
{
"recipient": "jsmith@example.com",
"reason": "complaint",
"message": "Recipient previously complained; do not contact again unless you are sure.",
"sourceMessageId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"providerMessageId": "<string>",
"complaintFeedbackType": "<string>",
"complaintUserAgent": "<string>",
"lastEventAt": "2023-11-07T05:31:56Z"
}
],
"providerMessageId": "<string>",
"error": "<string>",
"channel": "email",
"channelMetadata": {},
"scheduledAt": "2023-11-07T05:31:56Z"
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"code": "<string>",
"type": "<string>",
"param": "<string>"
}
}Authorizations
Dairo API key, e.g. dairo_test_... or dairo_live_...
Headers
Optional idempotency key for safe retries of side-effecting operations.
128Body
- Option 1
- Option 2
- Option 3
- Option 4
Body-level idempotency key kept for current API compatibility. Prefer Idempotency-Key header for new clients.
128Outbound send attachments. 'attachment' and safe 'auto' sends are inline; current inline API limit is 10 files, 8 MiB per file, 8 MiB total decoded bytes. 'link' is explicit and must be backed by a pre-created Dairo share link placed deliberately in text/html by the caller.
10An outbound attachment. Provide EITHER inline bytes (contentBase64) OR a storage reference (objectId) — exactly one, never both. Inline attachments require filename and are capped at 8 MiB decoded (API Gateway JSON/base64 envelope). A storage-reference attachment names a Dairo storage object you own (the objectId returned by a bucket upload's finalize, or any owned storage object); Dairo fetches its bytes server-side and native-attaches up to 24 MiB, deriving filename and contentType from the object unless you override them here. Over 24 MiB the send fails with a 413 (create a share link and place it in the body yourself; Dairo never auto-edits the body).
- Option 1
- Option 2
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Send by referencing a stored template instead of an inline body. Mutually exclusive with text, html, and react: combining a template with any inline body is a 400. The referenced version is resolved and pinned at request time; supplied variables are validated against that version's variable schema (a bad variable is a synchronous 400). When the version declares a subject template it is used unless an explicit subject is provided on the request.
Show child attributes
Show child attributes
RFC 3339 timestamp WITH an explicit timezone offset to schedule the send for a future time (max 30 days ahead). Omit to send immediately. A scheduled email starts with status scheduled and can be stopped via POST /v1/outbound-emails/{emailId}/cancel before it fires.
Optional explicit delivery channel. "email" forces SES even when every recipient is a Dairo inbox; "a2a" requires every recipient to be a Dairo inbox (400 otherwise) and cannot combine with sendAt. Absent = auto (a2a when all recipients are internal, else email). Unknown values are a 400.
email, a2a Optional single Reply-To address, set verbatim as the MIME Reply-To header.
Optional custom MIME headers ({name: value}). Spoofable/provenance headers are dropped server-side; malformed names or CR/LF are rejected.
Show child attributes
Show child attributes
Optional SES message tags ({name: value}), validated against SES tag constraints.
Show child attributes
Show child attributes
Override complaint suppression for recipients that previously complained.
Optional contact reference: the contact's PRIMARY handle for the sending inbox's channel is added to to, so a send needs no raw address. Accepts a bare contact id, or a contact:<id> / @alias / @me ref. Recipients in to/cc/bcc may ALSO be contact references (@alias, contact:<id>, @me); raw addresses pass through unchanged.
Telegram inline keyboard (Telegram-channel inbox only): rows of {text, url|callback} buttons. A URL button opens a link; a callback button surfaces the tap back to you as an inbound button_tap event and shows a feedback toast on tap (default: ✓ + the button label; set alert:true for a modal).
Show child attributes
Show child attributes
Per-request dry run, at parity with the letters API's dryRun. When true the request is validated and the sending inbox resolved exactly as a real send would be, then a non-persisted MessagePreview (status "preview") is returned: nothing is created, queued, handed to the provider, metered, or billed. Absent or false is a normal send. Test mode is scoped to the REQUEST, not to the API key — an API key's environment label has no effect on delivery.
Response
Success
A single immediate send (POST /v1/emails without sendAt) is performed synchronously and returns 'sent' (with providerMessageId) or 'failed' — it is never accepted as 'queued' only to fail later on something knowable at submit time (oversized attachment, unverified sender, etc.). A scheduled send (sendAt in the future) returns 'scheduled'. 'queued' is returned ONLY for a bulk list broadcast (POST /v1/audiences/{id}/send), whose batches are delivered asynchronously by the worker fleet.
sent, scheduled, failed, queued Warning-only delivery guidance. Complaint suppressions do not block sending; agents should surface these warnings before further contact.
Show child attributes
Show child attributes
Public-safe failure code/message. Provider/internal text is stored internally and never returned to API clients.
The channel this send transited: "email" (SES) or "a2a" (internal Dairo-to-Dairo, delivered as a receipt, providerMessageId 'a2a_…').
email, a2a Channel-specific delivery metadata. For a2a: {receiptId, provenance, provenanceVerified}. For email: provider send metadata.
When a scheduled send will fire (RFC3339); present only when status is "scheduled".